# 基于QT实现的扫雷小游戏
# 一、需求和规格说明
本题目做一个N x M 的扫雷游戏,每个方格包含两种状态:关闭(closed)和打开(opened),初始化时每个方格都是关闭的,一个打开的方格也会包含两种状态:一个数字(clue)和一个雷(bomb)。你可以打开(open)一个方格,如果你打开的是一个bomb,那么就失败;否则就会打开一个数字,该数字是位于[0,8]的一个整数,该数字表示其所有邻居方格(neighboring squares)所包含的雷数,应用该信息可以帮助你扫雷。
![](http://www.writebug.com/myres/static/uploads/2021/10/19/16b8204f32f9e72338bf564a91388dea.writebug)
## 1.1 具体实现要求的细节
- 能够打开一个方格,一个已打开的方格不能再关闭
- 能够标记一个方格,标记方格的含义是对该方格有雷的预测(并不表示真的一定有雷),当一个方格标记后该方格不能被打开,只能执行取消标记的操作,只能在取消后才能打开一个方格
- 合理分配各个操作的按键,以及各方格各种状态如何合理显示
## 1.2 课程设计目的
掌握线性结构的应用,并体会如何用计算机程序完成一个有趣的游戏。
## 1.3 基本要求
- 能够给出游戏结果(输、赢、剩余的雷数、用掉的时间按妙计)
- 游戏界面最好图形化,否则一定要清楚的字符界面
## 1.4 实现提示
用二维数组表示N x M 区间,要仔细考虑如何初始的布置各个雷以及各个方格的状态及变化。
# 二、设计
根据上述需求,利用QT完成图形化界面的制作。从QT的函数库继承QMainWindow类,构造主界面类mainWindow,在其中定义paintEvent函数用于不断刷新界面,mousePressEvent用来定义鼠标点击事件。定义私有对象CDrawmap对象drawMap;定义对象offsetx与offsety表示界面偏移距离;QTimer类的对象runtime用来计时;Dialog类的对象message来定义对话框。
另外定义槽函数, updatetime()用来更新函数,on_actionRestart_triggered()用来重启,on_actionEasy_triggered()表示简单难度,on_actionMedium_triggered(表示中等难度,on_actionHard_triggered()表示困难难度,on_actionSuper_triggered()表示超级困难难度。更设置了on_actionExit_triggered()表示退出游戏,on_actionAbout_triggered()来介绍游戏,BGM1-4添加了音乐模块。
由此需要构建CDrawMap类用来画图,有Create来创建图,Restart来重新启动图,定义了获取map\[m]\[n]点周围格子数的函数num(),然后构造画图部分:\*\*Map用来定义格子,存储一个数字(0-8表示周围雷数,-1为雷,且已经被点开,49-59表示被右键插上红旗,99-109表示还未被点开),max_x,max_y分别表示图最大行数和列数,nMine表示总共布的雷,rMine表示当前的雷,用于显示,timer表示计时器,winf用来记录当前游戏情况,0表示未知,1表示点到雷,2表示赢。iswin()函数用来测试是否赢。然后就是定义按键功能,Onrbtdown(int m, int n)用来定义右键插小红旗事件,Onlrbtdown(int m, int n)定义左键点击事件, Onlbtup(int m, int n)用来定义递归DFS点击格子事件。
## 2.1 系统类图
![](http://www.writebug.com/myres/static/uploads/2021/10/19/fdb42b0eb00af0eb16c234c740b0148c.writebug)
## 2.2 属性和方法定义
**MainWindow**
![](http://www.writebug.com/myres/static/uploads/2021/10/19/aac8b9290733d8d7ce7a7dc81fb23f38.writebug)
**CDrawMap**
![](http://www.writebug.com/myres/static/uploads/2021/10/19/dadef4e63019d098bd95b1c8bb54f8a3.writebug)
# 三、用户手册
- 点击空格,若为雷,失败。不含雷的空格点开后的数据表示该格周围8个格子中含雷的个数
- 右键可以插小旗标注雷,标注错误结束时会显示带叉的雷,游戏直至所有的雷被标记或者所有的不是雷的空格被点开为胜利
- 游戏有四个难度模式,其中super为恶搞,屏幕显示不下qwq。。。
- 游戏框界面会记雷的个数,和游戏的时间计时。此外,表情处,游戏进行中为笑脸,失败为沮丧脸,胜利为夏娜,失败点击沮丧脸可以实现Restart功能
- 游戏菜单略简,只有信息About和宣难度,和重启、退出,实现不了保存名次等高级功能
# 四、调试及测试
添加对话框需要将其与主窗口信息连接,另外调用函数时需要包含相应的头文件,还有类的继承与声明时需要搞清楚相互之间的关系,还有按键与函数之间信号槽之间的关联也是十分重要,可以在UI界面设置,也可以直接用connect函数关联。还有调试时候可以考虑在函数中加入输出信息的形式来测试该函数是否被执行。
# 五、运行实例
![](http://www.writebug.com/myres/static/uploads/2021/10/19/b86789f3b5af702cda47d46493f8d66f.writebug)
# 六、进一步改进
- 程序中应该设置一个自由模式,由用户来输入想要绘制的地图的行列和雷数
- 该游戏应该设置一个可以保存游戏高分记录的数据库,以便玩家来保存自己的光辉历史
- 该游戏配的背景音乐太过简略
# 七、心得体会
开始时候是无从下手的,于是先去玩了扫雷游戏,以前都是瞎玩的,现在才彻底了解其规则。然后我又在网上搜寻了相应的代码来学习,不过网上的东西太繁杂,我选取了其中利用数字来判断格子情况的方式,然后用QT做了UI设计,不能不佩服QT的强大,同时它也很复杂,于是我只是对其进行了框架式的了解之后,只是把我要用的函数搞懂就没有继续学习了,也很惭愧,还被老师批评了一下,没有扎好基础。然后就是构造主界面,一步步完善,然后添加一些Windnows上本来就有的功能,再加上了一个介绍游戏的对话框,又加了几个BGM进去,中间各种BUG真是令我欲仙欲死,搞得我连续好几天开夜车作战。