三子棋(介绍)
游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利,而对方就算输了,但是三子棋在很多时候会出现和棋的局面。 🌞
实现效果
🧐首先开始执行程序,一张菜单,可以选择0或者1,0退出,1进入游戏
如果选择1的话,开始游戏,根据坐标填入数字,直到棋盘满了或者一方先连成一条线获胜为止。
代码实现
1.打印菜单
void menu() //菜单 { printf("****************************\n"); printf("****** 1. play *****\n"); printf("****** 0. exit *****\n"); printf("****************************\n"); }
菜单必不可少,让用户进来了解怎么操作
2.main函数
int main() { int input = 0; srand((unsigned)time(NULL)); //生成随机数用于人机自动落子 do { menu(); //do-while语句进来先打印菜单栏 printf("请进行选择(0/1)\n"); //这里进行输入有一个小细节就是把退出设置为0,然后把输入数字放在dowhile()里面这样输入0就直接退出循环了 scanf("%d", &input); switch (input) //switch语句进行选择,一目了然 { case 1: game(); //进入游戏 break; case 0: printf("成功退出"); break; default: printf("输入错误,请重新输入"); break; } } while (input); //为0中止 }
由于进程序就有菜单弹出所以这里选择do。while语句,再用switch语句进行判断,当玩家输入1,进入游戏,当玩家输入0,退出程序
让我们想想进入游戏后都需要些什么(也就是game()函数都需要什么)❔
首先我们需要一张棋盘,棋盘本质上来说是一个3*3的空间,我们这里选择用二维数组来放下。
char board[ROW][COL] = { 0 };
3.初始化棋盘
- 在刚进游戏的时候,棋盘上是空的,所以我们要把棋盘上所有位置都初始化成空格
void InitBoard(char board[ROW][COL],int row,int col) //形参的名字不能和define定义的相同,不然会报错 { for (int i = 0; i < row; i++) //把棋盘初始化为空格 { for(int j=0;j< col;j++) { board[i][j] =' '; } } //也可以使用库函数memset //memset(&board[0][0], ' ', row * col * sizeof(board[0][0])); }
4.打印棋盘
- 初始化棋盘之后我们就可以开始打印了
void printboard(char board[ROW][COL],int row,int col)//~用于打印棋盘 { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) //打印一行 { printf(" %c ", board[i][j]); if (j<col - 1) //打印col-1个|,做到 棋子|棋子|棋子 { printf("|"); } } printf("\n"); if (i < row - 1) //打印分割线---|---|--- { for (int j = 0; j < col; j++) { printf("---"); if (j < COL - 1) { printf("|"); } } printf("\n"); } } }
✨✨如果游戏开始只有棋子,那么玩家看到的是一片空,所以我们要打印一个棋盘出来,这里选择用ROW(行)和COL(列)来控制棋盘的长短,如果想打印更大的棋盘就只需改掉define定义的ROW和COL即可。
5.玩家落子
- 打印完棋盘之后玩家进行落子
void playerMove(char board[ROW][COL], int row, int col)//~玩家下子 { printf("该你了,请选择坐标(?,?)\n"); while (1) { int num1=0; //玩家输入的行 int num2=0; //玩家输入的列 scanf("%d,%d", &num1, &num2); if ((num1 > 3 || num1 < 0) || (num2 > 3 || num2 < 0)) //如果超出棋盘范围,结束本次循环重新选择 { printf("请输入正确位置"); continue; } if (board[num1-1][num2-1] == ' ') { board[num1-1][num2-1] = '*'; //返回1 ,落子成功,跳出循环 break; } else { printf("请选择空位下子\n"); //返回0 落子失败,重新输入 } } }
✨✨轮到玩家输入,首先要给个提示,提示玩家落子,如果玩家输入的坐标不对的话,提示重新下子,如果玩家输入的坐标已经有棋子的话,提示重新下子。
6.人机落子
- 玩家落子之后人机落子
void computerMove(char board[ROW][COL], int row, int col)//~电脑下子 { while(1) { int num1 = rand() % row; //生成随机数并取模row,保证row范围在棋盘大小内 int num2 = rand() % col; //生成随机数并取模COL,保证COL范围在棋盘大小内 if (board[num1][num2] == ' ') { board[num1][num2] = '#'; //如果为空落子成功,如果不为空重新生成随机数 break; } } printf("人机落子并说道:你输定了小伙子\n"); }
7.判断输赢
- 判断输赢是很重要的一步,不论是玩家落子后或电脑落子后,我们都应该进行判断程序是否应该结束
char ending(char board[ROW][COL], int row, int col) //判断游戏是否应该结束 { for (int i = 0; i < ROW; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i]) { return board[0][i]; //列相等返回所在列的字符,游戏结束 } } for (int i = 0; i < COL; i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2]) { return board[i][1];//行相等返回所在行的字符,游戏结束 } } if (board[0][0] == board[1][1] && board[1][1] == board[2][2]) { return board[1][1];//斜线相等返回所在字符,游戏结束 } if (board[0][2] == board[1][1] && board[1][1] == board[2][0]) { return board[1][1];//斜线相等返回所在字符,游戏结束 } for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { if (board[i][j] == ' ') { return; //如果还有空位,则游戏继续 } } } return 'q';//运行到这里证明棋盘已经满了,游戏结束 }
8.game函数
- 最后我们根据这些函数的作用将所有的函数整合到一块,就形成了我们整个游戏程序
void game() { char board[ROW][COL] = { 0 }; //三子棋是一个长3宽3的棋盘,这里用二维数组来装这个棋盘 init(board, ROW, COL); //此函数用于二维数组初始化 printboard(board, ROW, COL); //~用于打印棋盘 while (1) { char end = '\0'; playerMove(board, ROW, COL); //~玩家下子 printboard(board, ROW, COL); //~打印棋盘 end = ending(board, ROW, COL); //查看是否应该结束 if (end == '*') //返回值为*玩家胜利 { printf("Player WIN!!!\n"); break; } else if (end == 'q') //返回值为棋盘满了未分胜负,平局,退出游戏 { printf("敌人太强大了,居然平分秋色\n"); } computerMove(board, ROW, COL); //~电脑下子 printboard(board, ROW, COL); //打印棋盘 end = ending(board, ROW, COL); //查看是否应该结束 if (end == '#') //返回值为#人机获得胜利 { printf("Computer WIN!!!\n"); break; } else if (end == 'q') { printf("平局\n"); } } }
文件分类
🌞🌞为了使代码更有阅读性,我们不建议把所有函数写在一个文件里,所以这里分成三个文件
test.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 }; //三子棋是一个长3宽3的棋盘,这里用二维数组来装这个棋盘 initboard(board, ROW, COL); //此函数用于二维数组初始化 printboard(board, ROW, COL); //~用于打印棋盘 while (1) { char end = '\0'; playerMove(board, ROW, COL); //~玩家下子 printboard(board, ROW, COL); //~打印棋盘 end = ending(board, ROW, COL); //查看是否应该结束 if (end == '*') { printf("Player WIN!!!\n"); break; } else if (end == 'q') { printf("敌人太强大了,居然平分秋色\n"); } computerMove(board, ROW, COL); //~电脑下子 printboard(board, ROW, COL); //打印棋盘 end = ending(board, ROW, COL); //查看是否应该结束 if (end == '#') { printf("Computer WIN!!!\n"); break; } else if (end == 'q') { printf("平局\n"); } } } int main() { int input = 0; srand((unsigned)time(NULL)); //生成随机数用于人机自动落子 do { menu(); //do-while语句进来先打印菜单栏 printf("请进行选择(0/1)\n"); //这里进行输入有一个小细节就是把退出设置为0,然后把输入数字放在dowhile()里面这样输入0就直接退出循环了 scanf("%d", &input); switch (input) //switch语句进行选择,一目了然 { case 1: game(); //进入游戏 break; case 0: printf("成功退出"); break; default: printf("输入错误,请重新输入"); break; } } while (input); }
game.c
- 进入游戏后需要的所有函数都封装在这里
#define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" void initboard(char board[ROW][COL],int row,int col)//此函数用于二维数组初始化 { memset(&board[0][0], ' ', row * col * sizeof(board[0][0])); } void printboard(char board[ROW][COL],int row,int col)//~用于打印棋盘 { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { printf(" %c ", board[i][j]); if (j<col - 1) { printf("|"); } } printf("\n"); if (i < row - 1) { for (int j = 0; j < col; j++) { printf("---"); if (j < COL - 1) { printf("|"); } } printf("\n"); } } } void playerMove(char board[ROW][COL], int row, int col)//~玩家下子 { printf("该你了,请选择坐标(?,?)\n"); while (1) { int num1=0; int num2=0; scanf("%d,%d", &num1, &num2); if ((num1 > 3 || num1 < 0) || (num2 > 3 || num2 < 0)) { printf("请输入正确位置"); continue; } if (board[num1-1][num2-1] == ' ') { board[num1-1][num2-1] = '*'; break; } else { printf("请选择空位下子\n"); } } } void computerMove(char board[ROW][COL], int row, int col)//~电脑下子 { while(1) { int num1 = rand() % row; int num2 = rand() % col; if (board[num1][num2] == ' ') { board[num1][num2] = '#'; break; } } printf("你输定了小伙子\n"); } char ending(char board[ROW][COL], int row, int col) //判断游戏是否应该结束 { for (int i = 0; i < ROW; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i]) { return board[0][i]; //列相等返回所在列的字符,游戏结束 } } for (int i = 0; i < COL; i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2]) { return board[i][1];//行相等返回所在行的字符,游戏结束 } } if (board[0][0] == board[1][1] && board[1][1] == board[2][2]) { return board[1][1];//斜线相等返回所在字符,游戏结束 } if (board[0][2] == board[1][1] && board[1][1] == board[2][0]) { return board[1][1];//斜线相等返回所在字符,游戏结束 } for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { if (board[i][j] == ' ') { return; //如果还有空位,则游戏继续 } } } return 'q';//运行到这里证明棋盘已经满了 }
game.h
- 将;主程序所需要的函数全部在头文件中声明,增加代码阅读性
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <string.h> #define COL 3 #define ROW 3 void printboard(char board[ROW][COL], int row, int col);//~用于打印棋盘 void initboard(char board[ROW][COL], int row, int col);//此函数用于二维数组初始化 void playerMove(char board[ROW][COL], int row, int col);//~玩家下子 void computerMove(char board[ROW][COL], int row, int col);//~电脑下子 char ending(char board[ROW][COL], int row, int col);//查看是否应该结束
撒花
这就是实现三子棋的全部内容了,创作不易,还请各位小伙伴多多点赞关注,以后也会更新各种小游戏还有关于c语言的博客。