基于QT的扫雷游戏开发

代码路径:
github: [email protected]:flybird-jun/QT-project.git
****:https://download.****.net/download/xujun3132008/12090066
一、设计思想
1.将每一个格子作为一个对象Item,继承QWidget
2.格子对象有tip(提示,就是右键点击有一个旗子显示)、normal(正常,没有进行过点击)、open(左键点击)态,open状态根据格子是数字还是地雷就行显示。状态类:ItemState,类型类:ItemType。采用桥接模式+状态模式进行设计,类图如下:
基于QT的扫雷游戏开发
其中,因为numItem、mineItem、zeroItem被点击要发送的信号不同,所以采用类似于template method方法。openItem中show函数直接调用ItemType::show().
3.事件的传递。Item::mousePressEvent接收鼠标点击事件左键状态变为openItem,右键根据RTTI时转换tip和normal状态。(PS:本来是想在ItemState中定义virtual void changeState(),然后在右键中调用,但是后面发现openItem是不需要转换状态的,因为openItem不能在转成其他状态。) 左键时根据ItemType实际类发送信号,Chess类(我将所有的格子放在这个QWidget子类中管理)接收处理。Chess类根据接收的信号,处理后发送GameLoss和GameWin信号给MainWindow(继承于QMainWindow)
二、遇到的问题
1.最开始设计的时候是将ItemType基类中的num放到派生类numItem中,这样本身是没什么问题的,但是后来加入了showAround算法(扫雷中打开数字0会显示一大片的效果)之后就有问题了,因为showAround要判断数字是不是0,这样的话就必须判断数字是不是0,解决的方案要么是在ItemType中加入virtual int GetNum()=0函数(但是在MineItem中没有数字,所以返回-1),要么是在showAround算法中利用RTTI机制将对象转换为NumItem.于是采用了上述的方案。每个ItemType派生类发送的信号不一样,从而不需要判断。
三、算法部分
showAround算法:
算法实现点击到数字0,打开上下左右非雷item,如果item是0,继续打开这个item上下左右非雷item。
流程图:
基于QT的扫雷游戏开发这里做一点注释,coordinate是chess的一个数据成员,emitSignal函数会根据不同的派生类发射不同的信号,chess根据接收的信号判断要不要运行showAround函数
flag也是在slot里面设置为true。
四、未解决的问题
点击雷失败后弹窗点击新游戏会崩溃。找了两天没找到,有大牛找到和我说下,不胜感激。