1、什么是三子棋
三子棋我们大家应该都不陌生,就像我这边叫做井字棋,他的玩法是三乘三的棋盘,我们需要横三、竖三或者对角线是一种棋,这样才能赢,类似下图所示。
2、主函数的实现
首先,我们想去做一个三子棋,肯定要先写上一个主函数。
int mian() { return 0; }
其次就是我们需要进入主菜单,可以供我们选择是否开始玩游戏,就像下图所示。
我们这里采用了一个函数去实现,这个函数只负责打印菜单,在写完菜单函数时,我们可以放进主函数看看是否成功。
void menu()//菜单 { printf("*********************\n"); printf("*****1、进入游戏*****\n"); printf("*****0、退出游戏*****\n"); printf("*********************\n"); } 如上,我们可以选择是否进入游戏,这是就需要输入一个数,这个数可以是1、0或者其他,但是我为了方便就使用了1进入,0退出。 int main() { int input = 0; do { menu();//菜单 scanf("%d", &input);//输入菜单选择是否进入游戏 switch (input) { case 1: game();//游戏进入 break; case 0: printf("游戏已退出\n"); break; default: printf("选择错误请重新输入\n"); break; } } while (input); return 0; }
就像上方代码,输入任何数,都会进入do{}while()语句中,判断执行哪一块,如果是1进入switch语句中game()函数,也是我们三子棋的游戏本体,如果是0,则在屏幕上打印退出游戏,并且退出这个循环体,如果是其他数字,则会提示选择错误让你重新输入,这里利用了do{}while()语句的先执行一次,在进行判断是否为非零,再选择是否循环。
3、游戏的实现
进入游戏时,我们首先要打印棋盘,三子棋的棋盘是个三乘三的矩阵,我第一个想到的就是二维矩阵,所以我先创建了一个二维矩阵,然后再把矩阵全部初始化为空格字符,这里我也是利用了一个函数实现的。
void InitBoard(char board[ROW][COL], int row, int col)//棋盘初始化 { int i = 0; for (i = 0; i < row; i++)//利用for循环把数组board初始化成空格符 { int j = 0; for (j = 0; j < col; j++) { board[i][j] = ' '; } } } 再初始化数组后,我们还要写一个打印棋盘的函数,并且打印出来看一下,是否满足我们的要求。 void DisplayBoard(char board[ROW][COL], int row, int col)//打印棋盘 { int i = 0; for (i = 0; i < row; i++)//利用for循环把数组board打印出来 { int j = 0; for (j = 0; j < col; j++) { printf(" %c ", board[i][j]); } printf("\n"); //每次行打印完进行一次换行 } }
咦,我们发现什么都没有啊,哦哦哦,原来是我们只打印了数组,数组里面现在都是空格符,怎们看得到,所以我们只需要美化一点点就会得到下图。
是不是很简单,我这里是利用for循环把棋盘的轮廓打印出来,代码如下:
void DisplayBoard(char board[ROW][COL], int row, int col)//打印棋盘 { int i = 0; for (i = 0; i < row; i++)//利用for循环把数组board打印出来 { int j = 0; for (j = 0; j < col ; j++) { printf(" %c ", board[i][j]); if (j < col - 1) { printf("|"); } } printf("\n"); //每次行打印完进行一次换行 if (i < row- 1) { for (j = 0; j < col ; j++) { printf("---"); if (j < col - 1) { printf("|"); } } } printf("\n"); } }
好了,我们现在实现了棋盘的打印,下面就可以进行下棋的设置了,我们先写玩家的下棋,下棋的思路就是把我们想要下的坐标给进行赋值,简单来说就是给二维数组赋值,这里我们下棋和电脑下棋肯定不是一回合就结束了,肯定要放在循环里,所以我这里使用了一个while()循环。
player_move(board, ROW, COL);//玩家下棋
DisplayBoard(board, ROW, COL);//打印棋盘
这里我也是应用了一个函数去写的,写完了肯定还是要打印出来看看的,所以在玩家下棋后再把棋盘打印出来,我们就来看看代码是如何实现的,并且写完后一定要调试看一下。
void player_move(char board[ROW][COL], int row, int col)//玩家下棋 { int x = 0; int y = 0; printf("玩家下棋\n"); printf("请玩家输入坐标\n"); 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"); } } }
看,我们的写法没有毛病,先判断二维数组这个坐标有没有,被别人下过,判断好后,如果没有下过就把,我们想要下的坐标赋值'*'这个字符,然后我们就下好了,这时就轮到电脑下棋了,我们就要去考虑下电脑是如何实现的,这里和上文一样写个电脑下棋的函数,然后进行打印。
computer_move(board, ROW, COL);//电脑下棋
DisplayBoard(board, ROW, COL);//打印棋盘
电脑这边下棋,我们这里就采用了一个随机数进行下棋,因为是简易的三子棋,所以就没有进行那么复杂的运算,判断。而且我也不会,嘿嘿,废话不多说了,我们来看看代码是如何实现的。
void computer_move(char board[ROW][COL], int row, int col)//电脑下棋 { int x = 0; int y = 0; printf("电脑下棋\n"); while (1) { x = rand() % 3; //利用随机数让电脑进行下棋 y = rand() % 3; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } }
我们想法是对的,随机数产生的数字%3产生的刚好是0-2,在数组范围内,但是要注意随机数要先进行srand(),要不随机数每次开始都是一样的srand()使用如下,要记得加上和头文件。
srand((unsigned int)time(NULL));//srand是随机数rand的初始化,这里利用电脑时间进行初始化
最后,我们要写判断谁嬴得函数了,我是判断二维数组里是否还有空格字符,例如:判断第一行是否都是空格符,如果是,不执行,如果不是则判断数组中是否是同一字符,是的话返回数组中的字符,如果是'*'就是玩家赢了,如果是'#'就是电脑赢了,如果行列还有对角线都不是同一字符,这时就进行判断是否满了,如果没满就返回'C'就是继续下棋,如果满了就返回'Q'就是平局了,同样结束游戏进行下一句。
static int if_full(char board[ROW][COL], int row, int col)//判断是否满了 { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { if (board[i][j] == ' ') { return 0;//没满 } } } return 1;//满了 } char if_win(char board[ROW][COL], int row, int col)//判断谁赢 { int i = 0; for (i = 0; i < row; i++)//判断行 { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ') { return board[i][1]; } } for (i = 0; i < col; i++)//判断列 { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ') { return board[1][i]; } } if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')//判断斜线 { return board[1][1]; } if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')//判断斜线 { return board[1][1]; } if (if_full(board, ROW, COL) == 1)//判断是否满了 { return 'Q'; } return 'C'; }
上面就是这个判断函数的实现,我们还要把他使用在game()函数中,并且运行看看游戏是否是我们想象中的。
void game()//游戏进入 { char board[ROW][COL];//定义一个二维数组 char ret = 0; InitBoard(board,ROW,COL);//棋盘初始化 DisplayBoard(board,ROW ,COL);//打印棋盘 srand((unsigned int)time(NULL));//srand是随机数rand的初始化,这里利用电脑时间进行初始化 while (1) { player_move(board, ROW, COL);//玩家下棋 DisplayBoard(board, ROW, COL);//打印棋盘 ret=if_win(board, ROW, COL);//判断谁赢 if (ret != 'C') { break; } computer_move(board, ROW, COL);//电脑下棋 DisplayBoard(board, ROW, COL);//打印棋盘 ret = if_win(board, ROW, COL);//判断谁赢 if (ret != 'C') { break; } } if (ret == '*') { printf("玩家赢了\n"); } else if (ret == '#') { printf("电脑赢了\n"); } else { printf("平局\n"); } } //'C'继续 //'*'玩家赢了 //'#'电脑赢了 //'Q'平局
三种情况都可以,和我们的想法一摸一样,我们的简易版三子棋也就实现了,各位再见了,拜拜!