大家好,我是萧寒,最近学习了一下用C语言编写一个小游戏-----三子棋,在现实生活中非常只需要一只笔,一张小白,便能随时随地玩,我现在都还记得以前上课摸鱼,就是随便拿本教材找个空白的地方,自己和自己在纸上画圈圈画差差。结果就是自己赢不了自己,果然最强的对手还是自己,哈哈哈。今天我就分享一下用C语言实现简单版的三子棋。
首先打开自己的C语言编译器,新建一个项目用来存放三子棋这个项目,在此项目中新建三个文件
比如我的
text_1.c
game.c
game.h
text_1.c用来测试三子棋游戏,所以将主函数编写在这里,在这里面调用实现游戏的函数,并完成游戏的三大重要部分,第一部分一个简单游戏菜单引导用户玩游戏,第二部分游戏的算法实现的整体框架,第三部分对用户的在菜单的选择进行判断。
game.c专门用来写实现三子棋游戏的函数.
game.h声明函数和预定义常量的地方
####实现游戏菜单
#include
//游戏菜单 void menu() { printf("****************************\n");//调用printf函数,需要先#include printf("****1. 三子棋 0. 退出游戏***\n"); printf("****************************\n"); }
菜单中有两种选择,所以我们需要实现两个选项的具体功能,当用户选1的时候就开始玩游戏,当用户选0则是退出游戏,如果用户选择了其它则给用户一条提示信息,让用户重新选择。实现选择这个功能我们可以用switch语句然后在调用相应的函数即可,仅仅是这样还是不够,这就好比王者只让你玩一把就不让你玩了,所以还需要加一个循环,让用户无限的享受游戏。
void text() { int input = 0; srand((unsigned int)time(NULL));//随机数的起始,先忽略 do { menu(); printf("请输入你的选择:"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏"); break; default: printf("你输入的有误,请重新输入!\n"); } } while (input); }
实现了菜单接下来就要考虑游戏的具体实现,我们先来看看样图,再去思考我们如何去是实现功能
结合现实我们下棋需要棋盘以及棋子,相应的在程序设计过程中我们也需要设计棋盘,棋子,还有一个对手,这样游戏才能正常进行,接下来就来实现。
//为了日后更改升级棋盘,所以采用宏定义棋盘的行与列 #define ROW 3 #define COL 3 char board[ROW][COL];
#### 2.格式化棋盘
未下棋时,棋盘为空,所有将所有数组元素初始化为空格
char board[ROW][COL] = {0};//数组内容为空格 void InitBoard(char board[ROW][COL], int row, int col) { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { board[i][j] = ' ';//初始化为空格 } } }
void DisplayBoard(char board[ROW][COL], int row, int col) { int i; for ( i = 0; i < row; i++) { int j; for ( j = 0; j < col; j++) { //1.打印 一行的数据 printf(" %c ", board[i][j]); if (j < col - 1) { printf("|");最左边一行不打印 } } printf("\n"); //2.打印分割行 if (i < row - 1) { for (j = 0; j < col; j++) { printf("---"); if (j < col - 1) { printf("|");//最后一行不打印 } } printf("\n"); } } }
二维数组的下标是从 0 0 开始的,但是这也是开发人员所知道的,普通的用户其实是默认是从1 开始,所以为了用户有更好的游戏体验,行和列都应该-1.咋这个游戏也不够只能输入两个在规定范围的数字去落子,有时候容易特别手贱容易输错,所以还需要加一个循环,和一句提示一句,既能让用户重复使用,也能让用户知道他那输错了。
void PlayerMove(char board[ROW][COL], int row, int col) { int x = 0 , y = 0; printf("玩家走:>\n"); while (1) { 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"); } } }
电脑会在玩家落子之后自动在棋盘空白处落子。咋们采用随机数的方法去实现。所以需要用到时间戳和随机数两个函数(rand(), tiem()),而调用rand()时需要调用srand()实际上用了三个函数。电脑自动落子的过程中它也要去把九宫格挨个找一遍,找到空白位置后才随机落子,所以还需要循环让电脑去找空白的位置,果然重复是计算机最强的能力,重复的计算,重复的查找不知疲惫。
void ComputerMove(char board[ROW][COL], int row, int col) { int x=0, y = 0; printf("电脑走:>\n"); while (1) { x = rand() % row; y = rand() % col; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } }
玩家赢 ------返回 ‘*’
电脑赢-------返回’#’
平局–继续游戏
胜利条件
char 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] != ' ') { 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[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ') { return board[1][1]; } //判断是否平局 if (1 == IsFull(board, ROW, COL)) { return 'Q'; } return 'C'; }
判断是否平局
//IsFull();的实现 int IsFull(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;//棋盘已满 } //判断是否平局 if (1 == IsFull(board, ROW, COL)) { return 'Q'; } returnC 'C';
游戏实现的函数调用
void game() { char ret = 0; //定义数组-存放数信息 char board[ROW][COL] = {0};//数组内容为空格 //格式化棋盘 InitBoard(board,ROW,COL); //打印键盘 DisplayBoard(board, ROW, COL); while(1) { //玩家下棋 PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL);//玩家下完棋后立即打印新的棋盘 //判断玩家是否赢 ret=IsWin(board,ROW,COL); if (ret != 'C') { break; } //电脑下棋 ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL);//更新棋盘 ret = IsWin(board, ROW, COL); if (ret != 'C') { break; } } if (ret == '*') { printf("玩家赢!\n"); } else if (ret == '#') { printf("电脑赢!\n"); } else { printf("平局!\n"); } }
game.h代码 #define _CRT_SECURE_NO_WARNINGS 1 #define ROW 3 #define COL 3 #include
#include #include //声明函数 void InitBoard(char board[ROW][COL],int row,int col); void DisplayBoard(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); //告诉玩家四种游戏状态 //玩家赢 -'*' //电脑赢-'#' //平局-'Q' //继续-'C' char IsWin(char board[ROW][COL], int row, int col); int IsFull(char board[ROW][COL], int row, int col); game.c代码 #define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" void InitBoard(char board[ROW][COL], int row, int col) { for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { board[i][j] = ' ';//初始化为空格 } } } //1.0版本 //void DisplayBoard(int board[ROW][COL], int row, int col) //{ // for (int i = 0; i < row; i++) // { // //1.打印 一行的数据 // printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]); // //2.打印分割行 // printf("---|---|---\n"); // } // //} void DisplayBoard(char board[ROW][COL], int row, int col) { int i; for ( i = 0; i < row; i++) { int j; for ( j = 0; j < col; j++) { //1.打印 一行的数据 printf(" %c ", board[i][j]); if (j < col - 1) { printf("|"); } } printf("\n"); //2.打印分割行 if (i < row - 1) { for (j = 0; j < col; j++) { printf("---"); if (j < col - 1) { printf("|"); } } printf("\n"); } } } void PlayerMove(char board[ROW][COL], int row, int col) { int x = 0 , y = 0; printf("玩家走:>\n"); while (1) { 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"); } } } void ComputerMove(char board[ROW][COL], int row, int col) { int x=0, y = 0; printf("电脑走:>\n"); while (1) { x = rand() % row;//取模得到在合理范围里的坐标 y = rand() % col; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } } int IsFull(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 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] != ' ') { 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[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ') { return board[1][1]; } //判断是否平局 if (1 == IsFull(board, ROW, COL)) { return 'Q'; } return 'C'; } //测试游戏 //text_1.c #define _CRT_SECURE_NO_WARNINGS 1 #include #include "game.h" //测试三子棋游戏 //游戏菜单 void menu() { printf("****************************\n"); printf("****1. 三子棋 0. 退出游戏***\n"); printf("****************************\n"); } //游戏的算法实现 void game() { char ret = 0; //定义数组-存放数信息 char board[ROW][COL] = {0};//数组内容为空格 //格式化棋盘 InitBoard(board,ROW,COL); //打印键盘 DisplayBoard(board, ROW, COL); while(1) { //玩家下棋 PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); //判断玩家是否赢 ret=IsWin(board,ROW,COL); if (ret != 'C') { break; } //电脑下棋 ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = IsWin(board, ROW, COL); if (ret != 'C') { break; } } if (ret == '*') { printf("玩家赢!\n"); } else if (ret == '#') { printf("电脑赢!\n"); } else { printf("平局!\n"); } } void text() { int input = 0; srand((unsigned int)time(NULL)); do { menu(); printf("请输入你的选择:"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏"); break; default: printf("你输入的有误,请重新输入!\n"); } } while (input); } int main() { text(); return 0; }
通过这个游戏让我觉得电脑也不过如此,电脑智商有待提高。不过要提高也是我给它赋能而不是自己涨智商。哈哈哈。扯皮了扯皮了,昨日子看狂神的视频是看到一句话,分享给正在前行的你,即使在小的帆也能远航,无能什么时候都要保持自信。