前面的博文中介绍了如何从“扫雷”游戏中获取数据、并输出数据,现在就来讲解数据的分析:如何在程序中实现雷块的判定。从前言中可知,“扫雷”游戏的分析,可分为四种模型,这里介绍前面三种模型的分析。
数据要比编程逻辑更容易驾驭。在此,先介绍“自动扫雷”所定义的有关数据结构。
Blog类表示游戏场景中的一个小方块。其类图如下所示:
m_isHide表示其是否隐藏;m_aroundMineCount表示m_isHide为false时(即方块显示出来时),方块上显示的数字;m_mineState表示m_isHide为true时,程序判断出这个块是雷、还是非雷(刚开始扫雷时都为UnKown)。
用TwoDimesionArray<Block> m_blocks表示由Block组成的两维游戏场景。
由上面的数据即可对付第一、二种模型。在utility.h中分别提供两个函数calMine(),calHide(),分别用来求某个块周围已经判断出雷的数目,以及某个块周围未显示的块。如果周围有雷的个数等于m_aroundMineCount则其它未判断的块就都不是雷;如果周围未显示的个数等于雷数,则这些就都是雷。
下面介绍第三种模型的分析:
先来简单回顾下——(详细先见前言)
如果出现以下的情况:
可以得出下面的数学式子:
a+b=1 (1)
d+e=1 (2)
a+b+c+d+e=2 (3)
在程序中,为了表示这个的式子,本人定义了ProbableMine类,其类图如下:
points表示所以可能出现雷块的坐标,mineCount表示在这个块中雷的总数。上面三个式子得用三个ProbableMine对象表示,其mineCount分别为1,1,2。points分别为a,b;d,e ;a,b,c,d,e的坐标。
SurAnalyse负责第三种模型算法的实现。类图如下:
其中probables为所有的可能情况,m_notMines,m_Mines用来记录分析过程中的结果。
在分析时,两两比较每个ProbableMine对象,如果其中一个points是另一个的子集,则可由它们差集生成另一个ProbableMine对象。如果这个新ProbableMine对象中的mineCount==0,则可以判断其points都不是雷;而如果mineCount==points.size(),则可以判断其points都是雷;如果两种情况都不满足则加入到probables中,参加下一轮的运算。直到数据都不再变化为止。
至此,前三种模型的分析都已结束,可以看出算法并不复杂。最有挑战的还是在第四种模型的分析,本系列的下一篇将会仔细分析(不过最近在研究第四种情况时,发现了这么一个数学题,有兴趣的朋友可以思考下,一个排列组合题)。
现在将C++项目源码公开出来: https://files.cnblogs.com/xiangism/mineTerminator_src.rar ,现在只实现前三种模型,第四种模型的代码还不完善。 (再次强调,为了专注,本人只研究XP系统下的自动扫雷。如果是WIN7系统,则需要拷贝XP下扫雷游戏,下面提供其下载地址)
32位XP系统下的扫雷游戏:winmine_32cn
自动扫雷的EXE下载地址为:https://files.cnblogs.com/xiangism/mineTerminator.rar
下面是本人用自动扫雷完成的游戏界面