对于《编程之美》上没有提供答案和提示的1.18和4.11两节,本文将综合网络上已有的部分资料,深入挖掘解题思路,并对目前尚未找到满意答案的1.18节问题2给出算法解答。阅读本文需要了解古典概型(百度 /维基)和组合数(百度 / 维基)的含义,以及扫雷游戏中的各种符号。
《编程之美》上关于扫雷的概率有两道题:1.18挖雷游戏和4.11扫雷游戏的概率。后者在网上已经有了令人满意的解答,前者我还没发现,相关内容也很少。经过近一天的研究,提出了一个自己的解法。这篇博文的写作过程,同时也是我整理思路的过程。可能有的读者还没有看过这两道题,或者看了之后记不大清楚了,先把两个问题贴在下面:
1.18 挖雷游戏
问题1:如果想给游戏增加一个功能键,点击就能查看剩余所有未标识的方块是否有地雷的概率。如何实现?
问题2:如果上一个问题太难了,可以先让程序先标识所有有地雷的方块。
4.11 扫雷游戏的概率
在一个16*16的地雷阵中,有40个地雷。用户点击了两下,出现如图4-21的局面。分析图4-22所示的这个局部。
问题1:当游戏中有40个地雷没有发现时,A、B、C三个方块有地雷的概率(P(A),P(B),P(C))各是多少?
问题2:这个局面共有16*16=256个方块,P(A)、P(B)、P(C)的相互大小关系和当前局面中总雷数有关系么?比如从10个逐渐变化到240个,三者曲线如何变化、会不会相交?(建议用Matlab做解)
1.18节的问题2比较好解,而且可以同时标记必然没有地雷的方块;但问题1就困难了,暂且放一边;读了4.11节之后,会发现解4.11节的方法是可以用来理解1.18节的问题的。本文的主要方法就是使用网络上对4.11节提供的解法和1.18节问题2的辅助功能,来完成问题1的解答。
先要明确地强调一点,1.18节的问题1、2与一些所谓的自动扫雷算法是不同的:对于确定为无雷的方块,并不做点击动作;也即仅作概率分析,而不实际地翻开来确认并获得更多信息。因此,有的自动扫雷算法可能每次并不是选择无雷概率最大的方块,包含了一些启发式的尝试。而这里将会对当前状态的所有方块是否有雷的概率进行分析。比如http://www.verydemo.com/demo_c173_i10167.html,我觉得这就是个似是而非的自动扫雷解法,要保持当前状态来标注概率,又没让你挖开看看,你知道的太多了,不对,应该是你做的太过火了。
为了便于阅读,我将一些定义(包括我自己的定义)做成了锚点,如果阅读时忘记了前面的含义可以点击链接来查看。
这里先引入“8邻接”的定义。这个定义来源于图形学,如下图,像素P周围的这8个像素就是P的8邻接像素。对应于扫雷问题,同样的可以对一个方块定义它的8邻接方块。
分析:
待标识概率的方块可以根据是否与已经标识的方块是