目录
一·基本思路
可以通过创建一个二维数组作为这个棋盘,这个棋盘初始条件下所有数据为空格,当用户输入对应的坐标时,把坐标对应的值替换为*,电脑利用随机数生成一个坐标,将其替换为#,再通过判定是否有没有横向竖向或对角线三个数组的值是一样的来判定输赢或平局。
二·设置菜单界面
设置一个菜单函数,提示用户输入对应数字以继续
void menu() { printf("*******************************\n"); printf("** 0.game *********** 1.exit **\n"); printf("*******************************\n"); }
三·设置进入游戏界面
提示用户输入对应的值来进行游戏或者退出游戏
void test() { int i = 0; menu(); do { printf("请输入你的选择-->"); scanf("%d", &i); switch (i) { case 1: { printf("开始游戏\n"); game(); //在game函数中整体实现算法 break; } case 0: { printf("退出游戏\n"); break; } default: { printf("重新输入\n"); break; } } } while (i); //当i为1或其他时,判定其为真继续循环,输入为0时为假,跳出循环 }
四·初始化棋盘
令二维数组中的每一个数都为空格
void Initboard(char board[ROW][CAL]) //初始化棋盘 { int i = 0; int j = 0; for (i = 0; i < ROW; i++) { for (j = 0; j < CAL; j++) { board[i][j] = ' '; } } }
五·打印棋盘
打印时优化为分组打印,其中要注意最后一列没有分隔符,最后一行也没有分隔符,这样的好处是不局限于ROW和CAL为3的情况,能够打印其他规格的棋盘
void Printboard(char board[ROW][CAL]) //打印棋盘 { int i, j; for (i = 0; i < ROW; i++) { for (j = 0; j < CAL; j++) { printf(" %c ", board[i][j]); if (j < CAL - 1) //最后一列不打印纵向分隔符 printf("|"); } printf("\n"); for (j = 0; j < CAL; j++) { if(i<ROW-1) //最后一行不打印横向分隔符 printf("----"); } printf("\n"); } }
六·玩家下棋
玩家落子条件是要输入一个1--3之间的坐标,然后把*替换原来的空格即可
void Usersmove(char board[ROW][CAL]) { int x; int y; printf("玩家走\n"); scanf("%d %d", &x, &y); while(1) { if (x <= ROW && x >= 1&& y <= ROW && y >= 1) { if (board[x - 1][y - 1] == ' ') { board[x - 1][y - 1] = '*'; break; } else { printf("该位置已被占用,请重新输入\n"); break; } } else { printf("输入1-3之间正确的坐标\n"); break; } } }
七·电脑下棋
值得注意的是,模拟电脑下棋本应该使用rand函数,但由于rand函数的伪随机性,需要我们再次运用srand函数更改为时间播种,再强转换为unsigned int,最后利用取余模拟出1-3的坐标
void Computermove(char board[ROW][CAL]) { int x = 0; int y = 0; printf("电脑走\n"); while (1) { x = rand() % ROW;//生成的数字为012中的一个 y = rand() % CAL;//利用srand改用时间播种随机数字 if (board[x - 1][y - 1] == ' ') //判断格子内有没有棋子 { board[x - 1][y - 1] = '#'; break; } } }
八·判断对局情况
1.棋盘满了
根据棋盘内有没有空格来判断有没有满,具体函数可以写成以下
int Isfull(char board[ROW][CAL])//1表示满了 0表示没满 { int i = 0; int j = 0; for (i = 0; i < ROW; i++) { for (j = 0; j < CAL; j++) { if (board[i][j] == ' ') return 0;//没满 } } return 1;//满了 }
2.有一方连成三子
三子分为横着三子和竖着三子还有对角三子,都要考虑到这些情况
char Iswin(char board[ROW][CAL]) { 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 < CAL; i++)//判断竖三列 { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ') return board[0][i]; } if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')//判断第一个对角线 return board[1][1]; if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')//判断第二个对角线 return board[1][1]; if (Isfull(board) == 1) { return 'Q'; } return 'C'; }
九·基本主体组合
上面的操作我们就完成了各个模块的函数,那么只需要用一些循环语句把这些函数组合在一起即可,下面是参考代码
void game()//游戏的整个逻辑 { char ret = 0; char board[ROW][CAL] = { 0 }; //定义数组用来模拟棋盘 Initboard(board); //初始化棋盘 Printboard(board); //打印棋盘 while (1) { Usersmove(board);//玩家先下 Printboard(board); ret = Iswin(board);//判断玩家是否胜利 if (ret != 'C') { break; } Computermove(board);//电脑下棋 Printboard(board); ret = Iswin(board);//判断电脑是否胜利 if (ret != 'C') { break; } } if (ret == '*') printf("玩家赢\n"); else if (ret == '#') printf("电脑赢\n"); else printf("平局\n"); }
十·完整代码
那么把这些所有项组合在一起就能完成简易的三子棋游戏了
#include <stdio.h> #include <stdlib.h> #include <time.h> #define ROW 3 #define CAL 3 void Initboard(char board[ROW][CAL]) //初始化棋盘 { int i = 0; int j = 0; for (i = 0; i < ROW; i++) { for (j = 0; j < CAL; j++) { board[i][j] = ' '; } } } void Printboard(char board[ROW][CAL]) //打印棋盘 { int i, j; for (i = 0; i < ROW; i++) { for (j = 0; j < CAL; j++) { printf(" %c ", board[i][j]); if (j < CAL - 1) //最后一列不打印纵向分隔符 printf("|"); } printf("\n"); for (j = 0; j < CAL; j++) { if(i<ROW-1) //最后一行不打印横向分隔符 printf("----"); } printf("\n"); } } void Usersmove(char board[ROW][CAL]) { int x; int y; printf("玩家走\n"); scanf("%d %d", &x, &y); while(1) { if (x <= ROW && x >= 1&& y <= ROW && y >= 1) { if (board[x - 1][y - 1] == ' ') { board[x - 1][y - 1] = '*'; break; } else { printf("该位置已被占用,请重新输入\n"); break; } } else { printf("输入1-3之间正确的坐标\n"); break; } } } void Computermove(char board[ROW][CAL]) { int x = 0; int y = 0; printf("电脑走\n"); while (1) { x = rand() % ROW;//生成的数字为012中的一个 y = rand() % CAL;//利用srand改用时间播种随机数字 if (board[x - 1][y - 1] == ' ') //判断格子内有没有棋子 { board[x - 1][y - 1] = '#'; break; } } } int Isfull(char board[ROW][CAL])//1表示满了 0表示没满 { int i = 0; int j = 0; for (i = 0; i < ROW; i++) { for (j = 0; j < CAL; j++) { if (board[i][j] == ' ') return 0;//没满 } } return 1;//满了 } char Iswin(char board[ROW][CAL]) { 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 < CAL; i++)//判断竖三列 { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ') return board[0][i]; } if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')//判断第一个对角线 return board[1][1]; if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')//判断第二个对角线 return board[1][1]; if (Isfull(board) == 1) { return 'Q'; } return 'C'; } void game()//游戏的整个逻辑 { char ret = 0; char board[ROW][CAL] = { 0 }; //定义数组用来模拟棋盘 Initboard(board); //初始化棋盘 Printboard(board); //打印棋盘 while (1) { Usersmove(board);//玩家先下 Printboard(board); ret = Iswin(board);//判断玩家是否胜利 if (ret != 'C') { break; } Computermove(board);//电脑下棋 Printboard(board); ret = Iswin(board);//判断电脑是否胜利 if (ret != 'C') { break; } } if (ret == '*') printf("玩家赢\n"); else if (ret == '#') printf("电脑赢\n"); else printf("平局\n"); } void menu() { printf("*******************************\n"); printf("** 1.game *********** 0.exit **\n"); printf("*******************************\n"); } void test() { int i = 0; do { menu(); printf("请输入你的选择-->"); scanf("%d", &i); switch (i) { case 1: { printf("开始游戏\n"); game(); //在game函数中整体实现算法 break; } case 0: { printf("退出游戏\n"); break; } default: { printf("重新输入\n"); break; } } } while (i); //当i为1或其他时,判定其为真继续循环,输入为0时为假,跳出循环 } int main() { srand((unsigned int)time(NULL)); test(); return 0; }