我们自己在自己的编译器上创建一个三子棋项目,创建完毕后分别创建test.c,用来测试运行代码,game.h,用来引用所需要的头文件和所需函数的声明,game.c,用来定义game.h中的函数。以后我们写这种代码较长的函数较多的项目,都应该养成分文件的习惯,代码看起来也很分明。
2.在test.c文件中引头文件和写主函数#include"game.h"//因为在game.h中引用头文件,为了方便,我们在test.c和game.c都加上,表示用了game.h里 //面的头文件和game.h里面的函数 void menu() { printf("*************************************n"); printf("************ 1.paly **********n"); printf("************ 0.exit **********n"); printf("*************************************n"); } int main() { int input = 0; do { menu(); printf("请选择 >:n"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("欢迎下次再玩!n"); break; default: printf("输入错误,请重新输入!n"); break; } } while (input); return 0; }
我们首先需要打印一个菜单让玩家选择,玩家可能玩一次还想再玩一次,所以我们让它至少执行一次,用do while循环,然后循环里面用分支语句来分别跳转玩家的选择。
3.在test.c文件写开始玩游戏代码void game() { char board[ROW][COL] = { 0 };//创建一个二维数组棋盘 init_board(board, ROW, COL);//初始化棋盘 display_board(board, ROW, COL);//打印棋盘让玩家看到 }
我们需要将棋盘打印成这种形状:
我们将二维数组棋盘初始化为3行3列的,但是为了让代码灵活起来,我们选择用宏定义,将行定义为ROW,列定义为COL:于是在game.h文件里面:
#define ROW 3 #define COL 34.初始化棋盘
现在game.h文件里面声明初始化棋盘的函数并引用头文件:
#include//初始化棋盘 void init_board(char board[ROW][COL], int row, int col);
接下来转到game.c文件中写函数的定义:
void init_board(char board[ROW][COL], int row, int col) { int i = 0, j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = ' '; } } }
这里已经将3*3个格子的元素全部初始化为空格。而为什么要初始化为空格不为0,原因是空格占一个字符,0占两个,打印出来会对不齐。
5.打印棋盘在game.h文件里面声明打印棋盘的函数:
//打印棋盘 void display_board(char board[ROW][COL], int row, int col);
接下来转到game.c文件中写函数的定义:
void display_board(char board[ROW][COL], int row, int col) { int i = 0, j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { printf(" %c ", board[i][j]);//要把格子打印在中央 if(jfor (j = 0; j < col; j++) { printf("---"); if (j < col - 1) printf("|"); } printf("n"); } } }
然后我们就成功的打印出了上面图中我们需要的棋盘,当然,也可以把ROW和COL定义的3改为4,就会打印出4*4的棋盘了。
6.开始下棋我们要实现玩家下一步棋,电脑下一步棋,直到有一方赢,所以就是一直循环到有人赢,循环里面,玩家走一步,打印给玩家看,电脑走一步,打印给玩家看,先给死循环,判断条件我们下面再说
void game() { char ret = 0; char board[ROW][COL] = { 0 }; init_board(board, ROW, COL); display_board(board, ROW, COL); while (1) { player_move(board, ROW, COL);//玩家下棋 display_board(board, ROW, COL);//打印棋盘 computer_move(board, ROW, COL);//电脑下棋 display_board(board, ROW, COL);//打印棋盘 } }
在game.h中声明玩家下棋和电脑下棋的函数:
//玩家下棋 void player_move(char board[ROW][COL], int row, int col); //电脑下棋 void computer_move(char board[ROW][COL], int row, int col);
在game.c文件中定义这两个函数:
//玩家下棋: //这里我们把玩家下的子定义为* void player_move(char board[ROW][COL], int row, int col) { printf("玩家下:n"); //判断下棋合法 int x = 0, y = 0; while (1) { scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if (board[x - 1][y - 1] == ' ') { board[x - 1][y - 1] = '*'; break; } else { printf("该坐标已被占用,请重新输入:n"); } } else { printf("非法坐标,请重新输入:n"); } } }
//电脑下棋 //这里我们把电脑下的子定义为# void computer_move(char board[ROW][COL], int row, int col) { printf("电脑下:n"); int x = 0, y = 0; while (1) { x = rand() % row;//产生一个0到2的随机数 y = rand() % col;//产生一个0到2的随机数 //判断坐标合法即可下子 if (x >= 0 && x <= row - 1 && y >= 0 && y <= col - 1 && board[x][y] == ' ') { board[x][y] = '#'; break; } //这里给电脑下的不需要提示坐标是否合法,玩家的才需要。电脑下了子直接跳出就行了。 } }
我们在电脑下棋那的x和y要产生随机数,所以我们需要写一个时间种子,在game.h里面引用时间函数的头文件和srand函数的头文件:
#include#include
我们srand函数只需要调用一次,所以我们在main()函数里面调用一次即可:
int main() { int input = 0; srand((unsigned int)time(NULL));//就是这。 do { menu(); printf("请选择 >:n"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("欢迎下次再玩!n"); break; default: printf("输入错误,请重新输入!n"); break; } } while (input); return 0; }7.判断谁赢
我们以返回的棋子来判断谁赢或者平局,需要每下一步就判断一次:
我们这里返回*就是玩家赢,返回#就是电脑赢,返回Q就是平局,返回C,就是继续游戏
void game() { char ret = 0; char board[ROW][COL] = { 0 }; init_board(board, ROW, COL); display_board(board, ROW, COL); while (1) { player_move(board, ROW, COL); display_board(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret != 'C') break; computer_move(board, ROW, COL); display_board(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret != 'C') break; } if (ret == '*') { printf("玩家赢!n"); } else if (ret == '#') { printf("电脑赢!n"); } else if (ret == 'Q') { printf("平局!n"); } }
在game.h文件中写函数的声明:
//判断谁赢 char is_win(char board[ROW][COL], int row, int col);
在game.c中写函数的定义:
我用了标签flag来判断,使得判断灵活了起来,无论的4*4的还是其它数的,都可以判断
int is_full(char board[ROW][COL], int row, int col) { int i = 0, j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (board[i][j] == ' ') { return 0; } } } return 1; } char is_win(char board[ROW][COL], int row, int col) { int i = 0, j = 0;//横线判断: for (i = 0; i < row; i++) { int flag1 = 1; for (j = 0; j < col-1; j++) { if (board[i][j] != board[i][j + 1] || board[i][j+1] == ' ') { flag1 = 0; break; } } if (flag1 == 1) { return board[i][j]; } } //竖直判断: for (i = 0; i < col; i++) { int flag2 = 1; for (j = 0; j < row - 1; j++) { if (board[j][i] != board[j + 1][i]|| board[j+1][i] == ' ') { flag2 = 0; break; } } if (flag2 == 1) { return board[j][i]; } } //从左到右斜线判断: int flag3 = 1; for (i = 0; i < row-1; i++) { if (board[i][i] != board[i + 1][i + 1] || board[i+1][i+1] == ' ') { flag3 = 0; break; } } if (flag3 == 1) { return board[i][i]; } //从右到左斜线判断: int flag4 = 1; for (i = 0, j = col - 1; i < row, j>0; i++, j--) { if (board[i][j] != board[i + 1][j - 1] || board[i+1][j-1] == ' ') { flag4 = 0; break; } } if (flag4 == 1) { return board[i][j]; } int ret = is_full(board, ROW, COL);//判断是否为平局 if (ret == 1) { //返回平局 return 'Q'; } //以上的都不是,就返回继续游戏 return 'C'; }8.总结
写到这里,恭喜你!你已经把三子棋的代码完成了!
放出最后代码的样子:
test.c文件:
//三子棋 #include "game1.h" void menu() { printf("*************************************n"); printf("************ 1.paly **********n"); printf("************ 0.exit **********n"); printf("*************************************n"); } void game() { char ret = 0; char board[ROW][COL] = { 0 }; init_board(board, ROW, COL); display_board(board, ROW, COL); while (1) { player_move(board, ROW, COL); display_board(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret != 'C') break; computer_move(board, ROW, COL); display_board(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret != 'C') break; } if (ret == '*') { printf("玩家赢!n"); } else if (ret == '#') { printf("电脑赢!n"); } else if (ret == 'Q') { printf("平局!n"); } } int main() { int input = 0; srand((unsigned int)time(NULL)); do { menu(); printf("请选择 >:n"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("欢迎下次再玩!n"); break; default: printf("输入错误,请重新输入!n"); break; } } while (input); return 0; }
game.h文件:
#pragma once #define ROW 3 #define COL 3 #include#include #include //初始化棋盘 void init_board(char board[ROW][COL], int row, int col); //打印棋盘 void display_board(char board[ROW][COL], int row, int col); //玩家下棋 void player_move(char board[ROW][COL], int row, int col); //电脑下棋 void computer_move(char board[ROW][COL], int row, int col); //判断谁赢 char is_win(char board[ROW][COL], int row, int col);
game.c文件:
#include "game1.h" //初始化棋盘 void init_board(char board[ROW][COL], int row, int col) { int i = 0, 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) { int i = 0, j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { printf(" %c ", board[i][j]); if(jfor (j = 0; j < col; j++) { printf("---"); if (j < col - 1) printf("|"); } printf("n"); } } } void player_move(char board[ROW][COL], int row, int col) { printf("玩家下:n"); //判断下棋合法 int x = 0, y = 0; while (1) { scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if (board[x - 1][y - 1] == ' ') { board[x - 1][y - 1] = '*'; break; } else { printf("该坐标已被占用,请重新输入:n"); } } else { printf("非法坐标,请重新输入:n"); } } } void computer_move(char board[ROW][COL], int row, int col) { printf("电脑下:n"); int x = 0, y = 0; while (1) { x = rand() % row; y = rand() % col; if (x >= 0 && x <= row - 1 && y >= 0 && y <= col - 1 && board[x][y] == ' ') { board[x][y] = '#'; break; } } } int is_full(char board[ROW][COL], int row, int col) { int i = 0, j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (board[i][j] == ' ') { return 0; } } } return 1; } char is_win(char board[ROW][COL], int row, int col) { int i = 0, j = 0; for (i = 0; i < row; i++) { int flag1 = 1; for (j = 0; j < col-1; j++) { if (board[i][j] != board[i][j + 1] || board[i][j+1] == ' ') { flag1 = 0; break; } } if (flag1 == 1) { return board[i][j]; } } for (i = 0; i < col; i++) { int flag2 = 1; for (j = 0; j < row - 1; j++) { if (board[j][i] != board[j + 1][i]|| board[j+1][i] == ' ') { flag2 = 0; break; } } if (flag2 == 1) { return board[j][i]; } } int flag3 = 1; for (i = 0; i < row-1; i++) { if (board[i][i] != board[i + 1][i + 1] || board[i+1][i+1] == ' ') { flag3 = 0; break; } } if (flag3 == 1) { return board[i][i]; } int flag4 = 1; for (i = 0, j = col - 1; i < row, j>0; i++, j--) { if (board[i][j] != board[i + 1][j - 1] || board[i+1][j-1] == ' ') { flag4 = 0; break; } } if (flag4 == 1) { return board[i][j]; } int ret = is_full(board, ROW, COL); if (ret == 1) { return 'Q'; } return 'C'; }
写的不好,欢迎批评指正!你的每一句建议,都对我很重要!希望我们都可以一起进步!