一、游戏简介
虽然说是一个基本上大家都听过,并且大多数人都玩过的一个小游戏,但是其实很多人当时都是瞎玩的。所以呢,我们先来介绍一下游戏规则。这个游戏,我们可以直接在电脑上搜索到,打开浏览器直接搜索扫雷。我们使用如下图所示的游戏
点击9*9棋盘,如下图所示,每一行是9个元素,每一列也是9
我们随机点开其中的一个方格,他会进行展开,其中白色方格代表这块没有雷。有数字的方格代表其周围一圈的八个格子里面有雷的个数 。我们就是根据这些提示进行排雷
而一旦踩中了雷以后,就会失败
二、游戏的基本设计
1.游戏基本思路
1.布置雷:创建一个二维数组,随机生成十个坐标放到位置上
2.排查雷:选择一个坐标,判断是否是雷,如果是,则爆炸,如果不是则遍历以他为中心的9个元素,并显示一个周围雷的个数。
2.游戏基本框架
在我们前面讲解了三子棋还有猜数字小游戏后,相信大家已经对这个思路很熟悉了,我们还是采用分文件的形式写代码,创建test.c,game.h,game.c三个文件。
这里就不在赘述了,直接给出代码,以下都是test.c文件中的代码
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> void meau() { printf("*************************\n"); printf("******* 1. 开始扫雷 ******\n"); printf("******* 0. 退出游戏 ******\n"); printf("*************************\n"); } void game() { printf("开始扫雷\n"); } void test() { meau(); int input = 0; do { printf("请输入选项>:\n"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏\n"); break; default: printf("输入错误,请重新输入\n"); break; } } while (input); } int main() { test(); return 0; }
当然还是需要测试的,我们进行一次测试,结果符合我们的预期
3.如何设计布置雷与排查雷?
我们的目标是布置雷与排查雷,那么这个时候有一个问题了,我们如果使用一个数组来记录布置雷的话,假如说我们记作,有雷是1,无雷是0。那么未来我开始排查雷的时候,想要扫雷,扫的这个位置是需要显示出周围有几个雷的。那这样的话,加入说我周围只有一个雷,那么打印出来的就只有1。可是这样子的话,我们这个位置就相当于被修改了,莫名奇妙的多出了一个雷,这就导致了一些混乱,产生了大量的bug。所以说这样的方法不太合理,我们需要进行优化。
那么如何进行优化呢?我们想到,既然只使用一个数组会乱,那么我们使用两个数组呢?一个数组仅仅用来放雷,一个数组用来打印出来让人来看。并且要记录这个周围有多少个雷。所以说,这样做的话就是可行的。程序就不会乱套了。
对于我们那个需要让人看的数组而言,我们一开始人是看不见雷的,所以说我们需要一开始打印的全是*号这个字符,为了方便起见,我们显示出周围有几个雷的时候也是使用字符数字来显示出周围有多少个雷。那么这样的话,不妨统一一下,两个数组都是字符数组。
4.数组的大小如何设置
有很多人不经思考的直接回答说9*9即可,可是当我们在排查雷的时候,遇到边界的坐标如何排查呢,我们如果想要排查他的一圈的话,那么毫无疑问越界了。所以这不是明智之举。我们应当进行在这个数组上加上一圈,所以行和列都应该加上2。这样就不会越界访问了,当然为了统一一下,我们两个数组都是这样加上一圈。
5.数组的定义代码展示
有了前面那么多代码的思考,那么我们能不能实现一下呢。我们先定义一下数组吧。如下图所示,我们为了方便起见我们直接在game.h中define一下,然后我们想要在test.c文件中使用这个define定义常量。就得引入这个game.h这个头文件。然后就可以定义字符数组了。当然我们是要使用行和列都+2的那个define定义的常量。
三、游戏具体功能详解
1.初始化数组(InitBoard)
(1)函数的声明和定义
很显然,我们要初始化数组两次,所以说,我们除了传数组名,行和列以外,需要传一个初始化成什么样子的一个字符。需要注意的是,这里传的是字符0,字符0和数字0是不一样的,字符0的ASCII值是48。'\0'的ASCII值是0,而如果传一个0的话,那么他最终打印出来的就是一堆'\0'也就是什么都没有。
//初始化数组 void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
(2)初始化数组代码展示
这块还是比较简单的,我们用两层循环即可
注意:此图中出现了一个经典的错误,标准的零分
在第12行中,这个set不应该带有单引号,因为我们set他本身是一个变量,对变量带一个单引号,那么就势必导致一些不可预料的错误。
这也是很多人都喜欢犯的一个错误!!!
(3)初始化数组代码如下
//初始化数组 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; } } }
2.打印数组(DisplayBoard)
我们初始化好数组以后,我们肯定希望我们现在就能看到这个数组。这也是方便我们后续进行测试的一个重要步骤,不过需要注意的是,我们打印肯定不是打印这个11*11的数组,而是只打印9*9的数组即可,因为这个人只需要看到9*9的就可以了
(1)打印数组的定义和声明
这里唯一需要注意的是,我们定义和声明函数的时候,数组的大小可千万不要写错了,写出了ROW,注意,我们这里数组的大小仍然是11*11的,只不过因为我只需要9*9就足够了。
//打印数组 void DisplayBoard(char board[ROWS][COLS], int row, int col);
(2)代码的实现
对于这个代码,其实也不是很难,同样两个for循环解决
(3)测试代码
同样的,写一点,测一点,好在结果也确实符合我们的预期,需要注意的是,有的人可能注意到了printf为什么有绿色警告,其实这是因为我们的game.c文件中还没有<stdio.h>这个头文件。为了方便,我们直接把test.c中的<stdio.h>挪到game.h文件中,就可以解决了
(4)更进一步优化
当然,我们此时打印出来的数组还不够完美,因为打印出来的数组密密麻麻,我们无法识别坐标,所以我们最好能把行标和列表打印出来就更加完美了。
(5)运行测试
这样一来就完美了
(6)更进一步的优化界面
这样可以使得测试更好看