三子棋
- 代碼實作
- 主函式
- 選單函式
- 游戲函式
- 初始化棋盤函式
- 列印棋盤函式
- 玩家放置棋子的函式
- 電腦放置棋子的函式
- 判斷游戲的函式
- 判斷棋盤是否已滿的函式
- 完整代碼
- 頭檔案:game.h
- 存放函式的檔案:game.c
- 存放主函式的檔案:test.c
最近學習了C語言陣列相關的基礎知識, 學知識就是為了用嘛,使用知識也會讓我們的學習程序更有趣,我們就用這些基礎的知識寫一個簡單的三子棋小游戲,讓我們與電腦對抗(當然,由于實力原因,這個電腦只能純隨機地放置棋子)實作效果如下圖:
好家伙,之前我試了多少遍來故意讓電腦贏,可他就是不贏,這我一寫博客,想再試一次,就成功了(我只是想說我是故意輸給電腦的,好面子)
代碼實作
首先我們要知道,寫這樣一個游戲,我們會寫很多行的代碼,而如果這時候我們規劃不得當的話,我們的代碼就會變得非常亂,因此我們遵照以下規則:
- 把整個工程分為3個檔案,test.c,game.c,game.h
- test.c存放main函式,用來當作程式的入口,并參考game.h頭檔案,即
#include"game.h" - game.c中存放各種各樣的函式,并參考game.h頭檔案
- game.h中存放各種函式的宣告以及VS提供的頭檔案的包含
- 每個函式盡量只實作一個功能,這樣我們的代碼會更有序,更易修改
- 把棋盤的行、列定義為宏,便于修改,即:
#define R 3
#define C 3
- 玩家放置的棋子為’*’,電腦放置的棋子為’#’, 默認的格子為’ ’
- 用一個3*3的二維陣列來盛放整個棋盤
主函式
int main()
{
int input = 0;//存放用戶的選擇
srand((unsigned int)time(NULL));//設定亂數種子,后面會用到
do//至少執行一次回圈
{
menu();//列印選單
printf("Please enter you choice(0/1):>");//要求用戶輸入他的選擇
scanf("%d", &input);
switch (input)
{
case 1:
game();//用戶輸入1,進入游戲
break;
case 0:
printf("Exit.\n");
exit(886);//用戶輸入0,退出程式
break;
default:
printf("Wrong!Please enter a right choice(0/1):>\n");//處理特殊情況
break;
}
} while (input);//游戲結束后,再次進入回圈
return 0;
}
選單函式
功能就是列印選單
void menu()
{
printf("----------------------------\n");
printf("----- 1.play ------\n");
printf("----- 0.exit ------\n");
printf("----------------------------\n");
}
游戲函式
void game()
{
char ret = 0;//用ret來判斷游戲輸贏,ret為'*'就代表玩家贏,為'#'就代表電腦贏,為'C'就表示繼續,為'Q'就表示平局
char arr[R][C] = { 0 };//棋盤
init(arr,R,C);//初始化棋盤
show(arr,R,C);//列印棋盤
while (1)//人機回圈放置棋子
{
player(arr, R, C);
ret=judge(arr,R,C);//放置一次,判斷一次
if (ret != 'C')//直至ret!='C',說明游戲已結束,跳出回圈
{
break;
}
computer(arr, R, C);
ret=judge(arr,R,C);
if (ret != 'C')
{
break;
}
}
//游戲已結束,判斷結束的三種情況:人贏;電腦贏;平局,
if (ret == '*')
{
printf("You win!\n");
}
else if (ret == '#')
{
printf("You lose!\n");
}
else
{
printf("This is a draw!\n");//draw:n.平局
}
}
初始化棋盤函式
把棋盤都初始化為空格
void init(char arr[R][C],int r,int c)
{
for (int i = 0; i < R; i++)
{
for (int j = 0; j < C; j++)
{
arr[i][j] = ' ';
}
}
}
列印棋盤函式
為了列印的好看,我們增加了一點別的東西
void show(char arr[R][C], int r, int c)
{
int i = 0;
for (i = 0; i < r; i++)
{
int j = 0;
for (j = 0; j < c; j++)
{
printf(" %c ", arr[i][j]);
if (j < c - 1)
printf("|");
}
printf("\n");
if (i < r - 1)
{
for (j = 0; j < c; j++)
{
printf("---");
if (j < c - 1)
printf("|");
}
}
printf("\n");
}
}
分析可知:這個函式需要在游戲開始時呼叫一次,而后在玩家或電腦放置棋子后呼叫一次
玩家放置棋子的函式
void player(char arr[R][C], int r, int c)
{
printf("This is your turn,and you want to place it on:>");
int row, col;
scanf("%d%d", &row, &col);
while (1)
{
if (arr[row - 1][col - 1] == ' ')//棋盤上的坐標減一才等于陣列里的下標
{
arr[row - 1][col - 1] = '*';//玩家放置*
show(arr,r,c);//放置后列印一下
break;
}
else//放置的位置不是空格,說明放置的未知錯誤
{
printf("Wrong!Please choose again.");
}
}
}
電腦放置棋子的函式
void computer(char arr[R][C], int r, int c)
{
printf("This is the computer's turn.");
while (1)
{
int row = rand() % R;//亂數除以行數得到0~R-1之間的亂數
int col = rand() % C;//同理
if (arr[row][col] == ' ')
{
arr[row][col] = '#';//電腦放置#
printf("And computer puts it on %d %d.\n", row + 1, col + 1);
show(arr,r,c);
break;
}
}
}
判斷游戲的函式
每次玩家或電腦放置一次棋子后,我們都需要判斷游戲是否已經結束
char judge(char arr[R][C],int r,int c)
{
int i = 0;
//判斷一行的情況
for (i = 0; i < r; i++)
{
if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' ')
{
return arr[i][0];//回傳的值即為玩家或電腦所下的字符,分別代表玩家或電腦贏
}
}
//判斷一列的情況
for (i = 0; i < c; i++)
{
if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ')
{
return arr[0][i];
}
}
//判斷對角線
if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[1][1] != ' ')
return arr[1][1];
if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[1][1] != ' ')
return arr[1][1];
//判斷棋盤是否已滿,回傳值為1時,回傳'Q',代表平局
if (full(arr, r, c))
{
return 'Q';
}
return 'C';//棋盤未滿,回傳'C',繼續游戲
}
判斷棋盤是否已滿的函式
int full(char arr[R][C], int r, int c)//判斷棋盤是否已滿,未滿則回傳0,繼續游戲,否則回傳1,平局結束游戲
{
int i = 0;
int j = 0;
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
if (arr[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
完整代碼
頭檔案:game.h
#pragma once
#define R 3
#define C 3
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
void menu();
void init(char arr[R][C],int r,int c);
void show(char arr[R][C], int r, int c);
void game();
void player(char arr[R][C], int r, int c);
void computer(char arr[R][C], int r, int c);
char judge(char arr[R][C], int r, int c);
存放函式的檔案:game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void game()
{
char ret = 0;//用ret來判斷游戲輸贏
char arr[R][C] = { 0 };//棋盤
init(arr,R,C);//初始化棋盤
show(arr,R,C);//列印棋盤
while (1)//人機回圈放置棋子
{
player(arr, R, C);
ret=judge(arr,R,C);//放置一次,判斷一次
if (ret != 'C')//直至ret!='c',說明游戲已結束,跳出回圈
{
break;
}
computer(arr, R, C);
ret=judge(arr,R,C);
if (ret != 'C')
{
break;
}
}
//游戲已結束,判斷結束的情況:人贏;電腦贏;平局,
if (ret == '*')
{
printf("You win!\n");
}
else if (ret == '#')
{
printf("You lose!\n");
}
else
{
printf("This is a draw!\n");//draw:n.平局
}
}
void player(char arr[R][C], int r, int c)
{
printf("This is your turn,and you want to place it on:>");
int row, col;
scanf("%d%d", &row, &col);
while (1)
{
if (arr[row - 1][col - 1] == ' ')//棋盤上的坐標減一才等于陣列里的下標
{
arr[row - 1][col - 1] = '*';//玩家放置*
show(arr,r,c);//放置后列印一下
break;
}
else//放置的位置不是空格,說明放置的未知錯誤
{
printf("Wrong!Please choose again.");
}
}
}
void computer(char arr[R][C], int r, int c)
{
printf("This is the computer's turn.");
while (1)
{
int row = rand() % R;//亂數除以行數得到0~R-1之間的亂數
int col = rand() % C;//同理
if (arr[row][col] == ' ')
{
arr[row][col] = '#';//電腦放置#
printf("And computer puts it on %d %d.\n", row + 1, col + 1);
show(arr,r,c);
break;
}
}
}
int full(char arr[R][C], int r, int c)//判斷棋盤是否已滿,未滿則回傳0,繼續游戲,否則回傳1,結束游戲
{
int i = 0;
int j = 0;
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
if (arr[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
char judge(char arr[R][C],int r,int c)
{
int i = 0;
//判斷一行的情況
for (i = 0; i < r; i++)
{
if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' ')
{
return arr[i][0];//回傳的值即為玩家或電腦所下的字符,分別代表玩家或電腦贏
}
}
//判斷一列的情況
for (i = 0; i < c; i++)
{
if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ')
{
return arr[0][i];
}
}
//判斷對角線
if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[1][1] != ' ')
return arr[1][1];
if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[1][1] != ' ')
return arr[1][1];
//判斷棋盤是否已滿,回傳值為1時,回傳'Q',代表平局
if (full(arr, r, c))
{
return 'Q';
}
return 'C';//棋盤未滿,回傳'C',繼續游戲
}
void menu()
{
printf("----------------------------\n");
printf("----- 1.play ------\n");
printf("----- 0.exit ------\n");
printf("----------------------------\n");
}
void init(char arr[R][C],int r,int c)
{
for (int i = 0; i < R; i++)
{
for (int j = 0; j < C; j++)
{
arr[i][j] = ' ';
}
}
}
void show(char arr[R][C], int r, int c)
{
int i = 0;
for (i = 0; i < r; i++)
{
int j = 0;
for (j = 0; j < c; j++)
{
printf(" %c ", arr[i][j]);
if (j < c - 1)
printf("|");
}
printf("\n");
if (i < r - 1)
{
for (j = 0; j < c; j++)
{
printf("---");
if (j < c - 1)
printf("|");
}
}
printf("\n");
}
}
存放主函式的檔案:test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
int main()
{
int input = 0;//存放用戶的選擇
srand((unsigned int)time(NULL));//設定亂數種子
do//至少執行一次回圈
{
menu();//列印選單
printf("Please enter you choice(0/1):>");//要求用戶輸入他的選擇
scanf("%d", &input);
switch (input)
{
case 1:
game();//用戶輸入1,進入游戲
break;
case 0:
printf("Exit.\n");
exit(886);//用戶輸入0,退出程式
break;
default:
printf("Wrong!Please enter a right choice(0/1):>\n");//處理特殊情況
break;
}
} while (input);
return 0;
}
放在最后:
本人能力實在有限,不會實作圖形化界面,而且這個游戲里的電腦笨的出奇,只會隨機亂下,但自己會不斷努力,在日后實作對此游戲的優化:如只能電腦,圖形化界面等,這次就到這里吧,
另外,如果有些錯誤本人未察覺,歡迎大家批評指正!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/352040.html
標籤:其他
下一篇:C語言實作【N子棋】
