本项目部分思路参考了王桂林老师的项目课程,在此表示感谢。
1、开发工具:Qt5.6.1
2、开发语言:C++
1.1 由于数据在全局只有唯一一份,故设计为单例模式。默认布局也在这里设置(宽20,高15,雷数50)。
1.2 关于布雷:随机算法,注意判断边界,如果确定此位置布雷(我用-1表示),其周围8个方向的数据均加1;
1.3 关于游戏设置:
1.3.1 游戏支持自己配置宽度和高度以及地雷数目,这里用到了两套数据,一个为配置数据域,一个为基本数据域,当我们设置成功后,需要转场,这时先删除旧的场景(这时用的是基本数据域),再创建新的场景(这时把配置数据传给基本数据域,就把基本数据域更新了),再把视图设置为当前场景即可;这里的数据传递很巧妙,注意体会;
1.3.2 数据有效性检查利用QIntValidator类自动检查,省去不少功夫(我当前限制宽为1~30,高为1~19,雷数不能超过“宽*高”的一半);
2.1 QGraphicsPixmapItem负责生成每个格子元素item;
2.2 利用格子元素生成场景Scene;
2.3 将Scene装进QGraphicsView视图中;
2.4 注意坐标处理:
2.4.1 视图和场景的坐标由框架自动处理,保证整体视图位于中心位置;
2.4.2 鼠标点击寻找对应的格子元素,利用itemAt函数(注意此函数参数为int,因此无法做到太高精度,这也是整体画面限制大小的一个原因,另外一个原因是视觉的美观性);
3.1 如果点击的格子周围没有地雷,需要自动扩展,需要考虑两方面因素:一个是底层数据的扩展,一个是视图的扩展;
3.2 两者均利用队列的思想实现,探寻周围8个方向的格子元素(底层数据)是否周围没有地雷,如果是的话就将其加入队列,不是的话翻开;需要加上标记表示其是否被翻开过,如果已经被访问过就不需要再加进队列了;
3.3 根据基本数据的寻找方向,同步扩展指针坐标(相当于自动鼠标点击),找到对应的格子元素,再根据底层数据做相应操作;我当初想直接基于当前格子元素获取其周围的格子元素,但是没有找到方法,然后就模拟鼠标自动扩展了,欢迎指教;
3.4 注意这里可能会出现画面缩放(虽然我最后限制了画面扩展减轻了负担),缩放时需要同步考虑鼠标指针的变换,必须是高精度(int不行,可以用double,但是经过测试雷数太多(大概50*30)的时候double也不够用,因为上层的itemAt函数参数为int);
4.1 我们知道,游戏中有旗子,问号等标记,因此需要单独处理;自动寻路扩展时不会考虑旗子,但是会考虑问号,只要查询其状态再对应处理即可;
5.1 输比较好判断,只要点击到地雷,直接判输;
5.2 判赢方式:用两个变量分别表示目前还没有被翻开的格子和目前已经标记的地雷数目,如果某时刻两个变量相等,则判赢;注意每次翻格子的时候检查一次即可(不用开多线程进行全局判断);
6.1 我们的格子元素大小应该根据画面大小自动调整,但是我还没做这一点,初步想法是可以添加窗口变化事件,进行处理。现在为了美观,直接最大化了;
1. 源码可以在github下载(里面包含了windows版程序)。
2. windows执行程序以动态链接库的方式给出。程序本身只有78k,dll就有十几M。一定注意验证校验码。
MD5: 91A4699F89F275B14E9CB90D721409EE
SHA1: AA72FC1C154198CE36276741D96B9729D5BF8281
3. 如果需要在linux上面玩儿,重新编译一下即可;
欢迎提出意见或者改进。