目录
三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利,而对方就算输了,但是三子棋在很多时候会出现和棋的局面。
- void menu()
- {
- printf("*******************\n");
- printf("*******1.Play******\n");
- printf("*******0.Exit******\n");
- printf("*******************\n");
- }
-
- int main()
- {
- menu();
- return 0;
- }
运用以上代码可以实现简易菜单的编写以及打印,如下图:
在这里我们有两个选择,选1就进入游戏,选0就直接退出游戏。那么我们不妨定义一个变量input。这样当input == 1时开始游戏,当input == 2时自动退出游戏。综上,我们可以考虑使用do....while循环和switch分支选择语句来实现选择的底层的逻辑代码。
代码如下:
- void menu()
- {
- printf("*******************\n");
- printf("*******1.Play******\n");
- printf("*******0.Exit******\n");
- printf("*******************\n");
- }
-
- int main()
- {
- menu();
- int input = 0;
- do
- {
- printf("请选择:");
- scanf("%d", &input);
- switch (input)
- {
- case 0:
- printf("正在退出游戏...\n");
- break;
- case 1:
- printf("开始游戏\n");
- break;
- default:
- printf("请重新输入\n");
- }
- } while (input);
- return 0;
- }
运行之后如下图所示:
如此一来,菜单的创建和选择就已经编写完毕了,接下来就是实现游戏内容的代码编写操作 。
对于一个程序来说,在未来,如果我们要编写一个程序或者简单的小游戏,一定会需要使用库函数,使用库函数就需要包含相对应的头文件,例如#include
因此我们设置一个头文件game.h
再在第一个源文件test.c以及随后创建的源文件game.c里包含#include"game.h"
在头文件内部我们就可以包含以下代码
#include
#include
#include
这些头文件的库函数随后就会用到。
在game.c的源文件里,我们则可以在此文件里实现函数的定义和实现操作,这样我们在test.c源文件里只需要调用函数,而具体的实现函数则就会在game.c函数中实现,这样可以大大缩短test.c源文件的代码量,使得读者在阅读代码的时候一目了然。
在这里,我们需要知道的是,下棋,则必须要使用棋盘,并且还需要打印出来。
棋盘是一个具有行和列的二维图形,所以我们只需要在二维空间上面进行操作。
因此我们将使用二维数组board[][]来实现关于棋盘的一系列操作。
我们在此项目只需要实现三子棋棋盘的应,因此棋盘的行和列都应该为3,即3行3列。
那如果以后我们需要实现五子棋棋盘初始化和打印呢?
那这样我们就会需要在原代码中出现的3全部改为5,这样会十分麻烦,而且极容易造成错误致使存在偏差。
所以我们可以在头文件game.h中定义关于行和列的宏。
- #define ROW 3
- #define COL 3
这样,在未来,我们想要实现五子棋的时候,我们就可以将3改为5。
如今,我们已经将行和列定义完毕,我们现在可以使用如下函数实现对二维数组的初始化了
- void InitBoard(char board[ROW][COL], int row, int col)
- {
-
- }
这里要注意的是,我们应当将如上的函数定义和实现写在game.c的源文件里,而对于如下的函数调用应写在test.c的源文件里并在void game()函数里面。
InitBoard(board,ROW,COL)
这里给予例子:
别忘了还要在头文件game.h里对函数进行声明,注意要加上分号
void InitBoard(char board[ROW][COL], int row, int col);
对遍历数组初始化的具体操作如下:
- //1初始化棋盘
- void InitBoard(char board[ROW][COL], int row, int col)
- {
- int i = 0;
- int j = 0;
- for (i = 0; i < row; i++)
- {
- for (j = 0; j < col; j++)
- {
- board[i][j] = ' ';
- }
- }
- }
打印棋盘为本次游戏实现的一个重难点,想要彻底学会实现棋盘的打印,光是听一遍是远远不够的,还需要多次练习,多次默写,并且多多总结回顾。
- | |
- ---|---|---
- | |
- ---|---|---
- | |
以上就是一个最简单的棋盘形状
以下是代码的实现
- //2.打印棋盘
- void DisplayBoard(char board[ROW][COL], int row, int col)
- {
- int i = 0;
- int j = 0;
-
- for (i = 0; i < row; i++)
- {
- for (j = 0; j < col; j++)
- {
- printf(" %c ", board[i][j]);
- if (j < col - 1)
- {
- printf("|");
- }
- }
- printf("\n");
-
- if (i < col - 1)
- {
- for (j = 0; j < col; j++)
- {
- printf("---");
- if (j < col - 1)
- {
- printf("|");
- }
- }
- printf("\n");
- }
-
- }
-
- }
这一串代码的底层逻辑,翻译过来就是如下
“空格——数据——空格 | 空格——数据——空格 | 空格——数据——空格 ”
“------------------------------------|---------------------------------------|----------------------------------”
“空格——数据——空格 | 空格——数据——空格 | 空格——数据——空格 ”
“------------------------------------|---------------------------------------|----------------------------------”
“空格——数据——空格 | 空格——数据——空格 | 空格——数据——空格 ”
此次循环主要以一行一行打印,先打印关于数据和下划线,再换行打印关于数据和下划线。
以此类推
并且运用循环,告诉编译器当我的棋盘
在(i < row - 1)的时候打印“---”
在(j < col - 1)的时候打印“|”
如此棋盘的打印就实现完毕了。
对于玩家下棋,需要注意的是,玩家不会如同程序员甚至是计算机一样,从0开始进行数数,而是从1开始数数。
因此我们在赋值的时候
实际上对board[x-1][y-1]进行赋值,这是需要注意的!
以下为代码的实现
- //3.玩家下棋
- void PlayerMove(char board[ROW][COL], int row, int col)
- {
- int x = 0;
- int y = 0;
- while (1)
- {
- scnaf("%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");
- }
- }
- }
对于电脑下棋,我们采取的是随机生成坐标,并进行判断,
该坐标是否被占用?
改坐标是否在棋盘范围内?
如果判断无误,将把生成的随机坐标赋值‘#’。
如此一来电脑下棋就实现完毕了。,
以下为代码:
- //4.电脑下棋
- void ComputerMove(char board[ROW][COL], int row, int col)
- {
- int x = 0;
- int y = 0;
- while (1)
- {
- x = rand() % row;
- y = rand() % col;
- if (x >= 0 && x < row&&y >= 0 && y < col)
- {
- if (board[x][y] == ' ')
- {
- board[x][y] = '#';
- break;
- }
- }
- }
- }
我们对于下棋是回合制的,因此我们需要用到循环,我们可以在game()函数里实现while循环
如:
- while (1)
- {
- //3.玩家下棋
- PlayerMove(board, ROW, COL);
- //4.电脑下棋
- ComputerMove(board, ROW, COL);
- DisplayBoard(board, ROW, COL);
这样就代表一回合一回合的下棋
对于输赢的判断,会出现的情况就两种,要么电脑赢要么玩家赢,所以我们应当分别在PlayerMove和ComputerMove后面加上IsWin函数来判断输赢还是平局
我们在这里可以定义对于的返回值:
玩家赢----" * "
电脑赢----" # "
平局-------" 'Q' "
继续-------" 'C' "
如果
电脑赢返回#
玩家赢返回*
平局返回Q
继续返回C
所以我们可以进行以下操作:
- while (1)
- {
- //3.玩家下棋
- PlayerMove(board, ROW, COL);
- ret = IsWin(board, ROW, COL);
- if (ret != 'C')
- {
- break;
- }
- //4.电脑下棋
- ComputerMove(board, ROW, COL);
- ret = IsWin(board, ROW, COL);
- if (ret != 'C')
- {
- break;
- }
- DisplayBoard(board, ROW, COL);
- }
-
- if (ret == '*')
- {
- printf("玩家赢\n");
- }
-
- else if (ret == '#')
- {
- printf("电脑赢\n");
- }
-
- else
- {
- printf("平局\n");
- }
接下来就是实现IsWin函数的具体操作:
- //5.判断输赢还是平局
- char IsWin(char board[ROW][COL], int row, int col)
- {
- int i = 0;
- int j = 0;
- for (i = 0; i < row; i++)
- {
- for (j = 0; j < col; j++)
- {
- if (board[i][0] == board[i][1] && board[i][1] == board[i][2]
- && board[i][0] != ' ')
- {
- return board[i][0];
- }
-
- else if (board[0][i] == board[1][i] && board[1][i] == board[2][i]
- && board[0][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];
- }
-
- else if (board[2][0] == board[1][1] && board[1][1] == board[0][2]
- && board[1][1] != ' ')
- {
- return board[1][1];
- }
-
- else if (IsFull(board, ROW, COL))
- {
- return 'C';
- }
- return 'Q';
- }
在函数内部,我们又创建了个函数,叫IsFull,这个函数是用来判断当前棋盘有没有装满,也就是可以用它遍历数组,
来查找“空格”。
如果有空格我就返回1,然后IsWin函数就返回‘C’,代表继续,循环继续。
如果没有空格了就返回0,然后IsWIn函数就返回‘Q’,代表平局,循环结束,并且打印“平局”。
对于IsFul函数的实现如下:
- static int IsFull(char board[ROW][COL], int row, int col)
- {
- int i = 0;
- int j = 0;
- for (i = 0; i < row; i++)
- {
- for (j = 0; j < col; j++)
- {
- if (board[i][j] == ' ')
- {
- return 1;
- }
- }
- }
- return 0;
- }
因为IsFull函数只出现在game.c的源文件中,因此可以运用static进行修饰。
对于以上代码的实现和设置,重难点的地方应当是棋盘的打印还有返回值的底层逻辑关系,这些是我们必须要去练习,去钻研的。
第一次可能会有难度,但是写久了以后对代码的理解就会更深刻,对循环和返回值的逻辑思维会有显著的思维提升。
完整代码在我的gitee里:Game with C: 这一仓库全部以c语言编写的小游戏 - Gitee.com