5.玩家下棋
玩家落子之后,应当判断是否落子正确(包括落子位置即坐标是否正确,以及落子位置是否被占用)在落子。由于下棋时一个人和电脑反复下直至分出胜负,因此为一个循环过程。
test.c 中代码如下:
while (1) { //玩家下棋 playmove(board, ROW, COL); print_board(board, ROW, COL);//每一次下棋后打印出棋盘目以便观察 }
game.h 中代码如下:
//函数体申明 #include<stdio.h> #include<stdlib.h> #include<time.h> #define ROW 3 //三行 #define COL 3 //三列 //初始化棋盘 void Initboard(char board[ROW][COL], int row, int col); //打印棋盘 print_board(char board[ROW][COL], int row, int col); //玩家下棋 playmove(char board[ROW][COL], int row, int col);
game.c 中代码如下:
playmove(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; while (1) //玩家下棋由于存在落子问题,因此采用循环直至这一次落子成功 { printf("当前为玩家下棋\n"); printf("玩家请落子: "); 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"); } }
效果展示:
6.电脑下棋
test.c 中代码如下:
computermove(board, ROW, COL); print_board(board, ROW, COL);
game.c 中代码如下:
computermove(char board[ROW][COL], int row, int col) { //电脑随机下棋,须产生一个随机坐标 int x = 0; int y = 0; printf("电脑落子:\n"); while (1) { //必须在循环里面,限制范围 x = rand() % row; //限定电脑随机生成的坐标范围 y = rand() % col; //rand需设置随机数的生成起点 if (board[x][y] == ' ') { board[x][y] = '#';//电脑落子成功用 # 表明 break; } } }
game.h 中代码如下:
//函数体申明 #include<stdio.h> #include<stdlib.h>//rand的头文件 #include<time.h> //随机数起点设置以时间为起点 #define ROW 3 //三行 #define COL 3 //三列 //初始化棋盘 void Initboard(char board[ROW][COL], int row, int col); //打印棋盘 print_board(char board[ROW][COL], int row, int col); //玩家下棋 playmove(char board[ROW][COL], int row, int col); //电脑下棋 computermove(char board[ROW][COL], int row, int col);
电脑不够按照随机下棋不够灵活,可以将其完善,例如第一步先判断玩家是否下在中间位置(2 2),若不在电脑可将第一步先下在此处,会更有利,由于我们这是一个非常初阶的三子棋,就暂时不考虑这些,有兴趣的朋友们可以考虑一下。
7.判断输赢
在判断输赢时,做如下约定: 判断输赢情况 1.电脑赢 #三连--返回 1 2.玩家赢 *三连--返回 2 3.棋盘未满,且双方都未赢,接着下--返回 3 4.棋盘满了,双方未赢,判定平局--返回 4
test.c 中代码如下:
void game() { //创建棋盘 char board[ROW][COL] = { 0 };//存储棋盘 //棋盘初始化 Initboard(board,ROW,COL); //打印初始化后的棋盘 print_board(board, ROW, COL); int m = 0; while (1) { //玩家下棋 playmove(board, ROW, COL); print_board(board, ROW, COL); m = Iswin(board, ROW, COL); if (m != 3)//棋盘未满且双方都还未分出胜负下才有意义判断输赢 { break; //还未分出胜负并且需要继续下棋时,及时跳出判断继续下棋 } //判断输赢 //m = Iswin(board, ROW, COL); //电脑下棋 computermove(board, ROW, COL); print_board(board, ROW, COL); m = Iswin(board, ROW, COL); if (m !=3)//在不是平局的前提下 { break; //还未分出胜负并且需要继续下棋时,及时跳出判断继续下棋 } } if (m == 1) printf("电脑获胜\n"); else if (m == 2) printf("玩家获胜!\n"); else printf("平局\n"); }
game.h 中代码如下:
//函数体申明 #include<stdio.h> #include<stdlib.h> #include<time.h> #define ROW 3 //三行 #define COL 3 //三列 //初始化棋盘 void Initboard(char board[ROW][COL], int row, int col); //打印棋盘 print_board(char board[ROW][COL], int row, int col); //玩家下棋 playmove(char board[ROW][COL], int row, int col); //电脑下棋 computermove(char board[ROW][COL], int row, int col); //判断输赢 int Iswin(char board[ROW][COL], int row, int col);
game.c 中代码如下:
int IsFull(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; //前面循环结束都未找到空格,说明棋盘满了 } //从此处开始阅读 int Iswin(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] != ' ') { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] == '*') return 2; else return 1; } } //竖三列 //前提不为初始化的0三子 int j = 0; for (j = 0; j < col; j++) { if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ' ) { if(board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] =='*') return 2; else return 1; } } //对角线判断 //前提不为初始化0的三子 if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ') { if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] == '*') return 2; else return 1; } if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') { if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] == '*') return 2; else return 1; } //若前面均为分出输赢,此时则有可能为平局或者继续 //若平局 此时棋盘应该已经下满,没有空位可以继续下 if (IsFull(board, row, col) ) //返回1则条件成立进入 { return 4; } //前面没有人赢,棋盘也没有满,此时应该处于需要继续下棋 return 3; }
以上判断输赢时,可考虑将电脑胜利以 ‘ #’返回,玩家胜利以‘ *’返回,可以省去在判断时该处是电脑三子还是玩家三子,即可将下面代码替换:
替换为:
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] != ' ') { /*if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] == '*') return 2; else return 1;*/ return board[i][1];//这个三子后期中一个子返回的值无论是‘#’还是‘*’,均可以直接判断输赢 } }
在上述判断输赢时,采取的是最原始的方法,将行列的三个数组坐标列出来进行判断,此处优化空间很大,可以试着去优化它。
效果展示:
1.玩家获胜
2.电脑获胜
3.平局
8.打印最后结果
最后,无论是电脑还是玩家赢了等情况,我们均需要让玩家观察最后的棋盘情况,因此我们在这还需要给判断输赢后的结果打印出来
test.c 中加入这个之前的打印函数即可:
void game() { //创建棋盘 char board[ROW][COL] = { 0 };//存储棋盘 //棋盘初始化 Initboard(board,ROW,COL); //打印初始化后的棋盘 print_board(board, ROW, COL); int m = 0; while (1) { //玩家下棋 playmove(board, ROW, COL); print_board(board, ROW, COL); m = Iswin(board, ROW, COL); if (m != 3)//棋盘未满且双方都还未分出胜负下才有意义判断输赢 { break; //还未分出胜负并且需要继续下棋时,及时跳出判断继续下棋 } //判断输赢 //m = Iswin(board, ROW, COL); //电脑下棋 computermove(board, ROW, COL); print_board(board, ROW, COL); m = Iswin(board, ROW, COL); if (m !=3)//棋盘未满且双方都还未分出胜负下才有意义判断输赢 { break; //还未分出胜负并且需要继续下棋时,及时跳出判断继续下棋 } } if (m == 1) printf("电脑获胜\n"); else if (m == 2) printf("玩家获胜!\n"); else printf("平局\n"); //游戏结束后,打印出棋盘让玩家观察输赢情况 print_board(board, ROW, COL); }
在此,我们的这个三子棋简单版就写完了!各位大佬给个关注(仰望大佬)