1.上期答案
接上期博客
在Getminenum中为什么不多设置一个参数char show[Row][Col],代码改成show[x][y]=代码改前return的值?
让我们对比下这两个代码
1
2.
第一种写法(正确写法)返回一个int型的雷的数目,用一个int型变量num接收,接着用字符0加上num,使得雷的数目由int型转变为char型(因为show数组是char类型),最后将更新后的数据打印出来
第二种写法(错误写法)直接将show数组的值改变为雷的数目,看起来也可以,为什么会出现以下情况呢?
先猜测接下来程序运行结果,也许你会有更深的体会
运行结果如下
所以第二种写法计算的结果会以%c的形式打印,例如计算的结果是两个雷,以%c打印会返回2的ascll码(不可见),所以会打印出如此奇怪的字符
2.提示行列
我们不难发现随着行列的增加不利于玩家判断坐标,因此我们更改showboard()函数可以增加行列提示
效果如下
3.递归实现
每当我们输入一个坐标,只能查看当前这个坐标的周围雷的个数,不能像扫雷一样一次开辟一片区域,因此我们要实现这个功能
1.主要思想
1.判断周围雷的个数是否为0,如果为0,计算并显示四个方向所在位置雷的个数,如果周围的位置雷的个数为0,继续递归下去,知道超出x和y的范围
2.代码实现
我们可以分装一个函数Caculate()来实现递归功能,然后递归完成后showboard()来显示到屏幕上
关键便是递归功能的实现
当我们运行起来时,并没有达到我们的预期
程序似乎崩了,让我们调试一下
编译器给出stack overflow(栈溢出)的报错信息,让我们想一下哪里学到过这个知识?对了在递归部分学到过,这恰巧说明我们调用函数的次数太多了
想象一下在理想情况下假设四个方向都能递归成功,那么第n次递归一共需要调用pow(4,n)次函数,而每次调用函数都将向栈区申请空间,调用次数过多后栈区空间不足,便报出相应错误
3.递归改进
按照我们的设想,如果没有递归,我们需要Row*Col-number次输入坐标才能达到游戏胜利,因此最多只需要调用函数Row*Col-number-1次就能达到游戏胜利,那么如何减少递归次数呢?
很显然需要满足一定条件才能递归,因此我们可以实现逻辑:如果没有递归过,进行递归,否则不进行递归,代码如下:
这么做大大减少了递归的次数,使得程序得以运行
4.胜利条件改进
之前我们每输入一个坐标,如果没被雷炸死,win--,直到win=0跳出while循环,因为现在实现了递归功能,现在的逻辑应是每递归一次win--
经过多次尝试,因为c语言编译器是自上而下逐语句进行的,递归有先后顺序,递归传参以及返回值的确定变得不确定,难以达到想要的结果,因此我们可以对胜利条件进行改进
不难发现雷的个数加上显示出来的数字个数就是Row*Col,因此我们可以定义一个Check_win函数遍历数组来判断是否达到胜利条件
并完善Findmine中的代码
这样就避免了在复杂的一次又一次递归中迷失了方向
5.结语
我很高兴用将近三千多字将c语言扫雷大致描绘清楚,由于作者知识水平的浅薄,文中相关内容可能不够专业,甚至存在错误,欢迎大家批评指正!
在近两个星期的探索中,在编译器疯狂报错中,在一次次的调试中,我深刻感受到了什么是痛苦,但最终看着自己亲手做出来的作品,一切都是值得的!
最后作者制作不易,希望大家积极点赞评论转发,如果喜欢作者的作品,可以点点关注,你的鼓励将是我创作的最大动力!