前言:
上一篇博客我们写了三子棋小游戏,紧着这我们趁热打铁,继续巩固知识点,再来写一个更有意思的扫雷吧,想必扫雷大家都玩过,我就不做介绍了。
概述:
我们一样将代码分为三部分来写,主函数main.c(在course-9.c中),游戏函数game.c,函数声明game.h,其中最核心的还是游戏函数game.c,game.c中包括大量主题函数的书写,有初始化函数,打印棋盘函数,布置雷函数,计算雷函数,标记坐标函数(选择拓展),扫雷函数(重点)
演示说明:
由于界面不是我们学习的重点,我们只需要掌握核心的代码即可,所以我们还是通过控制台来使用输入坐标来操作游戏
很不幸我们排的第一个雷就被炸死了,大家感受即可
程序主函数course-9.c
这里我们先做好函数的整体框架,在添加相应的功能
main主函数
同样我们先从主函数main入手,main是程序执行的入口,我们首先调用test函数,在test函数中做相应工作
test函数
test的函数主演是接收用户选择输入,导入菜单函数,srand((unsigned int)time(NULL));这个介绍过很多次了,时间戳用来辅助生成随机数的,我们的游戏菜单界面一般都是用do……while()循环来写再结合switch……case语句细化
menu函数(菜单)
game游戏函数
我们的游戏函数大概框架如下:我们一共准备两个棋盘,一个系统布置雷的棋盘,一个玩家扫雷的棋盘,进入函数我们首先定义布置雷棋盘和扫雷棋盘,然后进行初始化(初始化目的是将棋盘数据统一,防止出错,布置雷棋盘:0代表没雷,1代表有雷,起开始全部初始化为 0,后面在单独布置雷,扫雷棋盘:起开始全部初始化为 * 号),初始化结束我们打印棋盘,紧接着进行布置雷,排雷操作(这里解释:为什么我们在show排雷棋盘没有布置雷只有*号还能踩到雷,虽然雷在mine棋盘,但是我们在排雷时,玩家输入坐标后,我们是同时在两张棋盘进行验证(两张棋盘结构一样雷在mine,而玩家只能看到show可以理解为mine是show的内核棋盘),一旦mine棋盘踩雷就结束游戏)
程序的头文件即函数声明game.h
这里代码很简单,主要用到了宏定义,之所以用宏定义是因为其可变性强,我们可以随时改变棋盘大小和雷的个数,我们将棋盘定义为99大小,布置10颗雷,重点:我们需要的是99的棋盘为什么定义棋盘偏要1111的棋盘呢,以为后期我们在遍历棋盘时,比如统计雷的个数当雷处在边界时,可能会产生数组越界,所以大一圈定义为1111的棋盘,只要我们不打印出来1111的棋盘就好啦,把雷也布置进99的棋盘内(特别注意哦,数组下标是从0开始的,只要我们控制好1-9的坐标范围,雷就一定能布置进9*9的棋盘)
函数声明
函数部分game.c
初始化函数initboard
这里我们接收埋雷棋盘,和排雷棋盘进行初始化,将埋雷棋盘初始化为字符0,将排雷棋盘初始化为 * 号
打印棋盘函数displayboard
很简单的一个函数只是做了序号的标注,方便用户写出坐标,不做过多解释
布置雷函数setmine
EASY_COUNT是宏定义的雷的个数为10个,利用一个while循环,以count雷的个数为循环条件,因为c语言中0可以作为假结束循环,rand() % row + 1设置随机数,保证生成的数字在[1-9]之间,然后根据生成的坐标设置雷,直到10颗雷全部设置完成,结束while循环
统计雷的个数函数get_mine_count
这里统计雷的个数,运用了一个技巧,就是运用ASCII码计算数值,比如字符3的ascii码减去字符0ascii码等于数字3ascii码 即'3' - '0' = 3,正因如此,我们的埋雷棋盘中的雷是字符1,只要统计出一个坐标周围有多少个字符1再减去字符0就是相应的雷的个数了
排雷函数findmine
这个是核心
99一共81个棋格,当所有非雷棋格(71个)被排尽停止进入循环游戏结束,因此需要一个变量win统计扫雷进度,show[x][y] == '' && x >= 1 && x <= row && y >= 1 && y <= col这句判断条件,因为我们在show棋盘扫雷所以玩家输入坐标必须是 * 号即没有被排过区域,还需满足9*9的棋盘坐标合法,不合法会被强制重新输入
,进入扫雷判断(这是判断是否是雷则在mine棋盘判断),如果是雷直接打印埋雷棋盘,break结束游戏,否则进入无雷区域合并函数get_around,然后打印棋盘然后记录下来排雷进度,另外如果玩家输入的是0 0坐标,则进入标雷函数(这个作为拓展),如果win==71则游戏胜利,排雷成功
无雷区域合并函数get_around
核心中的核心
这里主要利用递归算法,首先将传来的坐标进行计算周围雷的个数,如果类个数不为0,则将计算结果以字符形式赋值给该坐标,并将win++,因为这也算排雷进度的一部分,否则进行无雷区域合并,首先将该坐标置为空,win++,然后进入递归 递归条件是一起中一个为例show[x - 1][y] == '*' && x - 1 >= 1 && x - 1 <= ROWS - 2 && y >= 1 && y <= COLS - 2,要满足是未被排过的坐标且在9*9棋盘内方可进入递归,这块递归很复杂需要仔细琢磨
演示当输入一个坐标 9 9 周围没有雷,就会将没雷的坐标置空,和扫雷游戏一样的效果
标雷函数biao_lei 拓展
就是插扫雷中的小红旗,我们用@代替,因为我是通过输入0 0坐标进入,想退出输入10 10坐标,因为这两个坐标不会影响棋盘,用别的方式字符进入也可以
完整代码
course-9.c
game.h
game.c
留言:
欢迎评论区交流探讨哦!