前言
扫雷游戏是一种益智类游戏,目标是通过揭示方块出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。
游戏规则
扫雷游戏规则如下:
(1).输入坐标位置是雷,游戏失败。(2).如果不是雷,则在该位置标记出周围一圈雷的个数,玩家继续输入,
(3).如果不是雷,而且周围一圈都没有雷(即显示数字0),那么,将显示周围一片周围雷数都为0的区域只到遇到非零。
(4).当排除所有不是雷的地方(即只剩下有雷的地方未显示)游戏胜利。
游戏结构的分析
扫雷过程中,布置的雷,排查的雷的信息都需要存储,所以我们需要一定的数据结构来存储这些信息。
这个时候我们会想到一个9*9的矩阵。(10颗雷)
我们将有雷的地方设置为‘1’,将没雷的设置为‘0’。
示例
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
1 |
0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
3 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
4 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |
6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
7 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
8 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
9 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
假设我排查(7,3),那么在(7,3)周围一圈有雷的话就会被记下来,并且在(7,3)处显示有几个雷,打印到屏幕上。如果我们要排除(8,9)或者(9,6)时,我的访问就会越界,控制台就会乱码,为了解决这个问题,我们会将棋盘设计成[rows+2][cols+2]的数组。而多加的两行的目的是防止越界,所以不需要布置雷。
如图所示
继续分析,当我们排查到一个雷时,需要将雷的信息储存起来,然后打印,作为排雷的重要参考信息,那么这个雷的个数信息应该存放在哪呢?因为存放雷的信息和雷的个数信息会在打印上出现困难。
为了清晰的将棋盘上有雷、非雷的信息和排查出雷的个数在棋盘上展示出来,我们采用另外一个方案,我们专门给一个棋盘(对应一个数组mine)存放布置好的雷的信息,再给另外一个棋盘(对应另外一个数组show)排查出的雷的信息。这样问题就解决了,把雷布置的到mine数组,在mine数组中排查雷,排查出的数据存放在show数组中,并且打印首位数组的信息到后期排查使用。
对于show数组就是将所有的'1','0'换成'*'。
游戏的程序设计
一、创建项目
这里为了提高代码的组织性、可维护性、可重用性和扩展性,提高编译效率和测试效率,我们使用多文件的编程方式来设计扫雷的程序代码。
首先我们创建项目准备一个头文件game.h用来做函数的声明,一个源文件game.c用来写函数的实现,最后用一个源文件test.c来作主函数的测试运行。
二、菜单的创作
框架(test.c)
我们写一个基础的框架,将头文件都放在game.h里面,就需要包含头文件。
注意,需要在game.c和text.c中包含一下头文件,要注意自己写的头文件要用双引号引用如下:
接着定义一个主函数main,为了避免代码的混乱,我不想把所以函数写到一个主函数里,所以我定义一个test函数来完成游戏的测试逻辑,在函数test中实现。
//主函数
int main() {
test();
return 0;
}
void test()
{
//游戏逻辑的实现在test函数中完成,避免主函数的代码混乱
}
为了让玩家有好的游戏体验,我们得建立一个游戏菜单供玩家选择是否开始游戏,所以打印菜单menu(),让玩家进行选择。
void menu()
{
printf("*******扫雷游戏*******\n");
printf("****** 1. play *******\n");
printf("****** 0. exit *******\n");
printf("**********************\n"