前言
今天我们用C语言实现一下扫雷小游戏,运用多文件写代码的形式来完成我们的扫雷游戏,希望通过这个小游戏能对大家有所帮助,话不多说开始我们今天的讲解。
一、整体思路
工欲善其事必先利其器,首先我们得确定我们这个游戏的大概思路:
首先是各个文件的功能:
其次就是游戏的大概思路:
- 打印菜单,做个简单的用户交互界面。
- 创建两个二维数组,一个存储布置好的雷的信息,一个存储玩家排查出的雷的信息。
- 初始化棋盘(二维数组),防止内存中遗留的脏数据影响我们游戏的正常进行。
- 打印棋盘,将我们的棋盘打印出来,方便用户更好地扫雷、排雷
- 布置雷,在我们的后台中布置好雷,这个布置好的雷不能给玩家看。
- 玩家开始排查雷,这里是个循环,直到排雷成功或者玩家踩雷循环才会跳出。
以上,就是游戏的大概思路,接下来,让我们根据上面的思路具体实现一下。
二、打印菜单
首先,在这里打印菜单的目的是做个可视化界面,实现简单的和玩家进行交互,具体看代码:
#include<stdio.h>
void menu()
{
printf("*************************\n");
printf("****** 1.play ******\n");
printf("****** 0.exit ******\n");
printf("*************************\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择你的操作:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("扫雷\n");
break;
case 0:
printf("退出游戏中.....");
break;
default:
printf("输入错误,请重新输入\n");
}
} while (input);
}
这里我们写一段测试一段,防止我们代码出问题。让我们看看上面这段代码的运行效果:
这里我们因为还没有添加游戏的逻辑,所以玩游戏这里我们就暂时用“扫雷”这两字来代替。这里我们可以看到以下几种输入情况:
- 输入“1”时:代码执行我们正常游戏的逻辑。
- 输入“0”时:代码退出循环,游戏结束。
- 输入其他数字时:会提醒玩家输入错误,并再次让玩家输入。
以上几种情况就充分保证了无论用户输入了什么,我们的程序都可以有相应的反馈,保证了代码的健壮性。
三、创建两个二维数组
在这里我们要创建两个二维数组。为什么是两个呢?这里有的小伙伴可能不理解了。其实,一个二维数组是用来存放我们计算机布置好的雷的信息,另一个呢是用来存放我们玩家排查出来的雷。在实际排雷过程中,计算机会对着我们布置好的雷的信息来判定玩家每下一步棋之后,游戏是结束了还是继续进行。这就相当于一个棋盘是给电脑来判定游戏胜负的(明盘),另一个棋盘是给玩家用于排查雷的(暗盘)。这样可能有的小伙伴还是不能理解,让我们上图片:
玩家棋盘中的星号表示,这是不是个雷,这个星号周围有几个雷,都是未知数。而在电脑的视角里,每个雷的位置都是知道的,电脑会根据玩家下的坐标来判断玩家是踩雷被炸死了,还是游戏继续进行。说到这里,小伙伴们应该也明白了这里为什么要创建两个二维数组的用意了。那就让我们上代码:
#include<stdio.h>
#include"game.h"
void menu()
{
printf("*************************\n");
printf("****** 1.play ******\n");
printf("****** 0.exit ******\n");
printf("*************************\n");
}
void game()
{
char mine[ROWS][COLS];//存储电脑设置好的雷的信息
char show[ROWS][COLS];//存储玩家排查出的雷的信息
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择你的操作:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏中.....");
break;
default:
printf("输入错误,请重新输入\n");
}
} while (input);
}
这里,我们还在game.h文件里另外定义了一些东西,因为不好展示,我就用截图了:
这里我们设置的棋盘大小是11*11的大小,但最终展示给玩家的大小是9*9,为什么呢?这里我们留个悬念,后面再讲。至于为什么要采用宏定义的方式来确定棋盘大小,这是为了我们后面想修改棋盘大小时方便修改。
四、初始化棋盘
这里,我们需要初始化一下我们的棋盘,防止脏数据遗留,我这里采用的是玩家棋盘的初始化用’*‘;电脑棋盘初始化用’0‘,为什么呢,我们在后面跟大家解释。先看代码:
//初始化函数棋盘
void InitBoard(char board[ROWS][COLS], int rows ,int cols, char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
这里要注意,在函数定义前,需要在game.h文件内声明一下这个函数。
五、打印棋盘函数
现在,我们已经将二维数组内的各个元素都初始化了一遍,现在我们不妨将它打印出来看看。这也就是我们的棋盘打印函数
//打印棋盘函数
void PrintBoard(char board[ROWS][COLS], int row, int col)
{
printf("------扫雷-------\n");
int k = 0;
for (k = 0; k <= col; k++)
{
printf("%d ", k);
}
printf("\n");
int i = 0;
for (i = 1; i <= row; i++)
{
printf("%d ", i);
int j = 0;
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("------扫雷-------\n");
}
这里我们不仅打印了棋盘,还打印了棋盘对印的行号和列号,方便用户排雷时快速定位自己要输入的坐标。但是,这里打印坐标时要小心间隔,换行符等小细节。同理呢,在函数定义前,需要在game.h文件内声明一下这个函数。
六、布置雷的函数
现在我们已经能够将我们初始化的结果打印在屏幕上了,接下来,我们就要让电脑布置好我们雷的信息,并将其存储起来。我这里采用的是使用rand函数生成随机数的方法,来达到生成随机数的效果。再把生成的随机数取模,得到一个合法坐标,最后再判断这个合法坐标上是否已经布置了雷,如果布置了雷,就再生成一个坐标;如果这个坐标没有雷,那么就在此坐标内种上一个雷。话不多说,让我们看代码:(这里说的雷都是布置在mine这一二维数组上的,搞清楚哦)
//布置雷的函数
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int x = 0;//随机生成的横坐标
int y = 0;//随机生成的纵坐标
int count = 10;//雷的数量
while (count)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (mine[x][y] == '0')//判断此随机坐标下有没有雷
{
mine[x][y] = 1;//没有雷就种下雷
count--;
}
}
}
在函数定义前,需要在game.h文件内声明一下这个函数。
现在,我们完成了布置雷的函数,让我们运行代码看看我们生成雷的位置在哪
显然,我们这10个雷是生成成功了,接下来就到了最后一个玩家排查雷的环节了
七、排查雷的函数
到了这里,我们就只剩最后一步了,玩家排查雷。
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x][y + 1] + mine[x][y - 1] + mine[x][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0';
}
//排查雷的函数
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win < row * col - 10)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了,游戏结束!\n");
PrintBoard(mine, row, col);
break;
}
else
{
int count = get_mine_count(mine, x, y);
show[x][y] = count + '0';
win--;
}
}
else
{
printf("坐标不合法,请重新输入\n");
}
}
}
到这里排雷小游戏就已经完成了,接下来让我们再回顾各个函数的功能和职责。
至此,我们今天的讲解就算结束了,感谢大家的观看。