目录
1、需求分析
2、程序架构
3、代码实现(分函数呈现)
(1)主函数代码实现
分析:
异常处理:
(2)菜单函数的实现
分析:
(3)游戏函数的实现
分析:
(4)棋盘的初始化
分析:
(5)棋盘展示代码实现
分析:
(6)玩家下棋
分析:
异常处理:
(7)电脑下棋
分析:
(8)判断是否结束
分析:
(9)判断谁获胜
分析:
(10)特别说明
4、代码实现(总代码)
test.c代码
game.c代码
game.h代码
需求:通过C语言实现三子棋小游戏。
注:由于作者水平有限,只能将计算机下棋设定为随机下棋,所以看起来略显呆笨,并且程序中也没有采用图像界面的方式,敬请谅解!
程序分为test.c、game.c两个源文件和game.h一个头文件。
test.c:主函数接口引入。
game.c:游戏的相关函数实现。
game.h:头文件引入、函数声明。
int main() { srand((unsigned int)time(NULL)); int input = 0; do { menu(); printf("请选择:->"); scanf("%d", &input); system("cls"); switch (input) { case 1: game(); break; case 0: int main() { srand((unsigned int)time(NULL)); int input = 0; do { menu(); printf("请选择:->"); scanf("%d", &input); system("cls"); switch (input) { case 1: game(); break; case 0: printf("已退出!\n"); break; default: break; } } while (input); return 0; } break; default: break; } } while (input); return 0; }
分析:
1.主函数主要是引入了随机种子(后续计算机下棋时会用到),并且通过switch()提供了游戏的接口,让玩家可以通过输入1开始游戏或者通过输入0结束游戏。
2.为了让用户能够多次进行游戏,采用了do while死循环的方式,同时,采用while语句的另一个原因就是可以利用该语句程序执行语句比条件表达式执行多一次的特点,来让玩家无论是否玩游戏,打开后先看到的是菜单。
异常处理:
在主函数中对于用户输入非0和非1的数字采用了重新进入循环的方式。
void menu() { printf("*************************\n"); printf("******* 1.play ********\n"); printf("******* 0.exit ********\n"); printf("*************************\n"); }
分析:
利用简单的printf语句进行输出即可将菜单呈现给玩家。(注意不要忘记'\n\进行换行操作)
//游戏函数 void game() { char board[ROW][COL] = { 0 }; Init_board(board, ROW, COL);//棋盘初始化 Display_board(board, ROW, COL);//棋盘展示 while (1) { player_board(board, ROW, COL);//玩家下棋 Display_board(board, ROW, COL);//棋盘展示 printf("\n"); if (is_end(board, ROW, COL) != 'c') { is_win(is_end(board, ROW, COL)); break; } computer_board(board, ROW, COL);//电脑下棋 Display_board(board, ROW, COL);//棋盘展示 printf("\n"); if (is_end(board, ROW, COL) != 'c') { is_win(is_end(board, ROW, COL)); break; } } }
分析:
1、先定义并初始化存放数据的棋盘(利用二维数组实现)
2、初始化棋盘并展示棋盘
3、玩家下棋,然后电脑下棋,只要有一方获胜就停止游戏,同时在任何一方下完棋后都进行棋盘的呈现。
void Init_board(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = ' '; } } }
分析:
利用两个for循环将二维数组的每个元素赋值为空格即可。
void Display_board(char board[ROW][COL], int row, int col) { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (j < col - 1) printf(" %c |", board[i][j]); else printf(" %c \n", board[i][j]); } if (i < row-1 ) { for (int j = 0; j < col; j++) { if (j < col - 1) printf("___|"); else printf("___\n"); } } else { for (int j = 0; j < col; j++) { if (j < col - 1) printf(" |"); else printf(" \n"); } } } }
分析:
大家先看成品代码:
具体思路:首先这个地方需要用到双层for循环这是毋庸置疑的,但我们在打印的时候一定要注意,我们在打印一行的每个的时候,前面的元素即前两个形式为 (空格)棋盘元素(空格)(竖线),最后面即第三个元素为(空格)棋盘元素(空格)(换行符),当我们打印完一行带有棋盘的元素后,我们需要打印出分割线,分割线也是通过for循环打印的,思路同上,前两个元素为(下划线)(下划线)(下划线)(竖线),第三个即最后一个元素为(下划线)(下划线)(下划线)(换行符)。
另外需要注意的是最后一行即原本应该打印分割线的位置不需要分割线,所以打印方式为:前两个元素为(空格)(空格)(空格)(竖线)(换行符),与前面相比,少了下划线。
总结来说,就是注意前两个元素或者前两行与最后一个元素或者最后一行的区别即可,此处一样是通过for循环实现。
void player_board(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; while (1) { int i = 0; int j = 0; printf("请输入下棋位置->"); scanf("%d %d", &i, &j); if (i <= row && i >= 1 && j <= col && j >= 1) { if (board[i-1][j-1] == ' ') { board[i-1][j-1] = '*'; break; } else { printf("坐标已有棋,清重新输入!\n"); } } else { printf("坐标非法,清重新输入!\n"); } } }
分析:
这个函数中主要是通过对想要下棋的位置判断该位置处有无元素即可,如果没有元素,即可正常下棋。
异常处理:
对输入的棋盘位置数据进行筛选后对于不符合要求的数据或者输入的坐标位置处有棋都会要求玩家重新输入。
void computer_board(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; while (1) { i = rand() % 3; j = rand() % 3; if (board[i][j] ==' ') { board[i][j] = '#'; break; } else continue; } }
分析:
此处利用随机种子生成随机数即可,只要生成的随机的位置处为空白就正常下棋,反之重新生成随机数直到为空白处下棋后停止。
//判断是否结束 char is_end(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; //行相同 for (i = 0; i < row; i++) { if (board[i][0] == board[i][1] &&board[i][1]== board[i][2] && board[i][0] != ' ') return board[i][0]; } //列相同 for (i = 0; i < col; i++) { if (board[0][i] == board[1][i] &&board[1][i]== board[2][i] && board[0][i] != ' ') return board[0][i]; } //’\'对角线 if (board[0][0] == board[1][1] && board[1][1]== board[2][2] && board[0][0] != ' ') return board[0][0]; //'/'对角线 if (board[2][0] == board[1][1] == board[0][2] && board[2][0] != ' ') return board[2][0]; //未结束 for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (board[i][j] == ' ') return 'c'; } } //平局 return '-'; }
分析:
当棋盘并未填满并且玩家与电脑均为未胜利时返回字符'c'说明可以继续,同时根据获胜的要求返回不同的值,当返回字符'*'时玩家获胜,返回'#'说明电脑获胜,返回字符'-'说明平局,返回字符'c'说明可以不符合上面的任意一种条件,可以正常继续。
//判断谁获胜 void is_win(char flag) { if (flag == '*') { printf("玩家获胜!\n"); system("pause"); system("cls"); } else if (flag == '#') { printf("电脑获胜!\n"); system("pause"); system("cls"); } else if (flag == '-') { printf("平局!\n"); system("pause"); system("cls"); } }
分析:
根据上面判断是否结束的返回时来进行判断并且输出即可。
1、代码中使用的system("cls")是清屏命令。system("pause")是使屏幕暂停的命令,按任意键后可以使程序正常进行。这两者均需要引windows.h头文件。
2、生成随机数的函数rand需要引stdlib.h头文件,使用时间戳time()需要引time.h头文件。
test.c代码
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" int main() { srand((unsigned int)time(NULL)); int input = 0; do { menu(); printf("请选择:->"); scanf("%d", &input); system("cls"); switch (input) { case 1: game(); break; case 0: break; default: printf("已退出!\n"); break; } } while (input); return 0; }
game.c代码
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" //菜单实现 void menu() { printf("*************************\n"); printf("******* 1.play ********\n"); printf("******* 0.exit ********\n"); printf("*************************\n"); } //游戏函数 void game() { char board[ROW][COL] = { 0 }; Init_board(board, ROW, COL);//棋盘初始化 Display_board(board, ROW, COL);//棋盘展示 while (1) { player_board(board, ROW, COL);//玩家下棋 Display_board(board, ROW, COL);//棋盘展示 printf("\n"); if (is_end(board, ROW, COL) != 'c') { is_win(is_end(board, ROW, COL)); break; } computer_board(board, ROW, COL);//电脑下棋 Display_board(board, ROW, COL);//棋盘展示 printf("\n"); if (is_end(board, ROW, COL) != 'c') { is_win(is_end(board, ROW, COL)); break; } } } //棋盘初始化 void Init_board(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = ' '; } } } //棋盘展示 void Display_board(char board[ROW][COL], int row, int col) { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (j < col - 1) printf(" %c |", board[i][j]); else printf(" %c \n", board[i][j]); } if (i < row-1 ) { for (int j = 0; j < col; j++) { if (j < col - 1) printf("___|"); else printf("___\n"); } } else { for (int j = 0; j < col; j++) { if (j < col - 1) printf(" |"); else printf(" \n"); } } } } //玩家下棋 void player_board(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; while (1) { int i = 0; int j = 0; printf("请输入下棋位置->"); scanf("%d %d", &i, &j); if (i <= row && i >= 1 && j <= col && j >= 1) { if (board[i-1][j-1] == ' ') { board[i-1][j-1] = '*'; break; } else { printf("坐标已有棋,清重新输入!\n"); } } else { printf("坐标非法,清重新输入!\n"); } } } //电脑下棋 void computer_board(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; while (1) { i = rand() % 3; j = rand() % 3; if (board[i][j] ==' ') { board[i][j] = '#'; break; } else continue; } } //判断是否结束 char is_end(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; //行相同 for (i = 0; i < row; i++) { if (board[i][0] == board[i][1] &&board[i][1]== board[i][2] && board[i][0] != ' ') return board[i][0]; } //列相同 for (i = 0; i < col; i++) { if (board[0][i] == board[1][i] &&board[1][i]== board[2][i] && board[0][i] != ' ') return board[0][i]; } //’\'对角线 if (board[0][0] == board[1][1] && board[1][1]== board[2][2] && board[0][0] != ' ') return board[0][0]; //'/'对角线 if (board[2][0] == board[1][1] == board[0][2] && board[2][0] != ' ') return board[2][0]; //未结束 for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (board[i][j] == ' ') return 'c'; } } //平局 return '-'; } //判断谁获胜 void is_win(char flag) { if (flag == '*') { printf("玩家获胜!\n"); system("pause"); system("cls"); } else if (flag == '#') { printf("电脑获胜!\n"); system("pause"); system("cls"); } else if (flag == '-') { printf("平局!\n"); system("pause"); system("cls"); } }
game.h代码
#include
#include #include #include #define ROW 3 #define COL 3 //菜单函数声明 void menu(); //游戏函数声明 void game(); //棋盘初始化函数声明 void Init_board(char board[ROW][COL], int row, int col); //棋盘展示函数声明 void Display_board(char board[ROW][COL], int row, int col); //玩家下棋函数声明 void player_board(char board[ROW][COL], int row, int col); //电脑下棋函数声明 void computer_board(char board[ROW][COL],int row,int col); //判断是否结束函数声明 char is_end(char board[ROW][COL], int row, int col); //判断谁获胜函数声明 void is_win(char flag);