一、思考
通过数组来储存哪些位置有雷还是无雷,有雷存1,无雷存0,再通过写各类函数来初始化表格、打印表格、布置雷、查找雷等。
我们需要一个表格来布置雷,但是这个表格对用户是不可见的,然后还需要一个对用户可见的全是'*'的表格,让用户猜哪里有雷,所以就需要两个表格。
我们可以用三个文件:game.c,test.c,game.h分别来书写函数,测试函数,存放头文件及宏定义等。
二、开始写代码
2.1 定义game.h头文件
首先确定是一个9*9的棋盘,行列分别为9,先定义一个ROW 为9,COL0也为9,用来存放数据,但是想到,如果用户猜的坐标不是雷,我们就需要计算出周围8个格子中的雷的数目。若标为是位于9*9棋盘的边界处,那么有的格子就会跨出这个边界,那我们可以采用一个11*11的棋盘,并将其全部初始化为0,到时候计算的时候就不会造成麻烦。因此,再定义一个ROWS为ROW +2,COLS为COL+2.
2.2 定义game.c文件
思考好棋盘初始化的逻辑之后,我们需要先定义一个函数,用来打印菜单,让用户选择下一步的进程。定义函数时需要先在game.h中进行声明。
声明后在game.c文件中进行函数定义。
因为不需要返回值,所以用void前缀。(如果需要使用game.h中的宏定义常量,需要添加#include"game.h")
在写好函数后,我们就在test.c文件中测试函数。
2.3 定义test.c文件
通过menu()测试函数,测试结果如下
2.4 循环输入
打印之后,很显然我们需要用户输入来进行选择,那我们就定义一个input让用户输入,再用switch —case语句判断下一步进程。
如果用户玩完一次后还想玩怎么办?或者输错了怎么办?这时候就要想到循环,因为至少要打印一次菜单,我们直接使用do-while循环,如何将input作为判断循环的条件,当输入为1时,进入游戏环节,当输入为0时,退出循环,当输入为其他不为0的值时,进行循环,让用户再进行输入。
运行起来结果:
2.5 game函数
在输入为1时,就需要进入游戏环节,我们可以先在test.c中写一个game()。game()作为整个游戏逻辑的集合,其中包含了很多函数,不必定义参数。
在game引用后,我们需要在game.c中定义game函数。因为不需要返回值,所以还是用void.
开始说的两个棋盘表格我们需要在函数中率先定义,因为在后面的函数中,都会用到。
2.5.1 初始化函数
通过宏定义定义两个11*11的棋盘。定义好了之后就要考虑初始化了,初始化需要什么参数呢?首先是11*11的棋盘,然后是想初始化的字符。因为*是字符,所以棋盘需要定义为char 类型,还需要代表行和列的参数,为了与宏定义区别开来,参数我们采用小写,带入的时候再输入大写。
初始化的逻辑就是for循环的嵌套,将每个数组中的位置都设置为set
代码实现如下
2.5.2 打印函数
如何判断我们的初始化函数是否正确,我们就需要一个打印函数,将初始化的表格打印出来,逻辑跟初始化函数大同小异,唯一的不同是,我们只需要打印下标为1-9的数组,其他的两行两列不用打印出来。
代码实现如下
看一下结果:
打是打印出来了,但是用户找行列数会不会非常费劲啊?所以我们可以在最上面输出一行0-9,列输出1-9,那不就可以轻而易举找出来了嘛?
代码实现如下
看看结果
完全符合心意。
2.5.3 布置函数
棋盘都画好了,我们是不是该放雷了呀,放雷的过程需要做到完全随机,而不是伪随机。(关于rand函数是伪随机函数,可以搜一下),这里我们调用srand函数,与time函数制造一个完全随机的值,然后坐标x,y用rand函数表示,并且都是完全随机的,在坐标(x,y)处放置雷。放多少个呢?那我们再定义一个宏定义 easy_count 为10,意思是放置10个雷。因为是完全随机的 ,所以可能位置重叠,因此我们十次放雷就可以用whilex循环来实现,将easy_count作为循环条件,当(x,y)的坐标不为1的时候,就在这放置一个雷,然后easy_count--;如果为1,就不进行操作,返回循环。
代码实现如下
再将棋盘打印出来看看
刚好十个雷,没有问题。
温馨提示:每写完一个函数就要将其写入game()里面哦,并且在game.h里面定义,像这样
2.5.4 得到数量函数
当用户猜的坐标位置不是1时,我们就需要将这个坐标周围八个位置的雷的总数量计算出来。我们这里需要雷的总数量,因此需要返回一个数字,所以需要int类型的返回值。还因为需要坐标x,y,所以需要把x,y也作为参数。那怎么计算呢?有两种方法。
1.我们可以直接一个一个写,将[x-1][y-1],[x1][y]等八个坐标加起来,再减去8*'0'。为什么要减去'0',因为我们开始设置的是char类型的数组,所以需要将其变成int 类型的值。由ASCII码表,我们可以知道,将字符数字转换为整型数字,可以通过减去'0',因此我们最后减去8*'0'。
代码如图
2.从图我们可以知道,x与y的变化范围都在-1,0,1,因此我们可以直接用for循环的嵌套将坐标加起来,然后再减去'0',最后相加。这里不用担心坐标中心的位置加多了,因为本身就是'0',所以减去之后还是0,不造成影响。
代码如图
2.5.5查找函数
布置好了雷之后,就需要用户输入坐标,开始排查。当排查到的位置是'1'时,很显然,直接结束游戏,可以提示用户:“您被炸死啦”,然后显示一下雷图,让用户知晓。当不是1的时候,就需要从布置雷的棋盘查找其周围的雷的数量,然后将数量传给另外一张显示给用户的表,然后将这个表显示出来让用户看周围有多少雷。当然,这种情况也需要停止,即胜利。因此,我们可以设置一个win=0,作为胜利的标识,当每次排查到不为1时,win++;当win == row*col-easy_count时,全部雷被排查完,显示胜利,再显示一下雷图
代码实现如下