吴昊品游戏核心算法(新年特别篇)—— (转载自Github)(前篇)扫雷AI(概率预测+坦克算法+JAVA实现)

经典游戏有经典游戏的魅力啊!不要说扫雷是20多年以前的游戏或者扫雷已经过时,经典的游戏之所以经典,是因为当时的游戏相当少,所以每做出一款游戏出来 都需要颇为精心的构思。正如中国60年代拍摄的一些抗日电影,例如《地道战》和《地雷战》,虽然剧情比较单调,将日本的军队模拟成SB,但是,还是有许多 人愿意看这些老电影,至少,他们做得很认真。如图所示,这是经过一番修改之后的扫雷游戏,左边这一款是在IOS上运行的扫雷游戏,而那个Nuclear Bomb则是《扫雷行动》。

  

 

 

 在Github上有个人无私地奉献了自己的作品——扫雷AI,并且给出了策略,原著为英文版的,某位网友将其翻译为中文版之后,发布到开源中国(OsChina)中。以下给出他的策略:

 

 如何玩扫雷:

 

 如果你是一个玩过扫雷的有经验玩家,你完全可以跳过这个部分。如果你没有玩过扫雷,我将会给一个快速简单的介绍,讲解一下一些我们可以用来解决简单扫雷游戏的基础攻略。

我们从10X10的新手网格开始,然后点击中间的方块:

 

  我们可以快速地标记一些地雷。当数字“1”在一个空的方块周围时,我们可以知道这周围有一个地雷。

让我们继续标记这些地雷:

 

 下一个攻略:如果有一个地雷与“1”相邻,那么我们可以知道与“1”相邻的其他方块都不可能是地雷。

所以,我们可以继续点击我们知道不可能是地雷的方块:

 

 按相同做法如下做下去。在这种情况下,这两个策略足以解决新手(初级)的格子了:

 

  AI何以实现?

   所有这些看起来足够简单。这是我们接下来需要做的:

1.读取板块。如果我们用一个截屏函数,我们可以获取到在板块上所有像素的一个位图。我们仅仅需要从屏幕中去“读取”那个数字。幸运的是,数字都有不同的颜色:1是蓝色,2是绿色,3是红色等等。

2.计算。运行计算,计算出那些地雷在哪里。这里不重复说了。

3.点击板块。这个步骤比较简单。在JAVA中,我们可以用标准类库中的Robot类去发送鼠标点击事件给屏幕。

 区域识别与OCR技术

 

 这里没有太多的步骤,所以我们将快速地过一下。

在运行之前,当我们有一个完整的空格子的时候,我们调用了一个校准程序-一个可以截屏和寻找看起来像地雷格子的程序。使用启发式,糨将可以定位格子的位置和方块格子的大小,在板块的坐标等等类似的信息。

 现在我们知道方块在哪里了,如果我们想读取方块的,我们剪切截屏的一小部分然后把它传到检测程序,检测程序将在这些少数的像素中计算广场中的是什么数字。

与此同时在检测中存在一些缺陷:

  //这里主要是判断该格子所标注的数字,这里可以不用管的啦!具体的说明我会在《吴昊品工程级别项目中介绍OCR识别技术》。

1.数字“1”的颜色与一个没有打开的方块的颜色非常相近:都是深蓝色。为了区分他们,我对比了斑点颜色与平均斑点颜色之间的“差异”。

2.数字3与数字7的颜色完全一样。在这里,我使用了一个简单的边缘检测程序。

 单一方块分析与多方块分析:

 

单一方块分析

示例2


ab必为地雷,因为达到3还差2颗地雷,只有ab能补上空缺

示例1


ab没有地雷,可轻易点开,因为已有3颗地雷满足数字3

以下两种情况是使用单一数字方块分析,可以轻易找出地雷[1]

  • 如果未开的方块等于数字,那么未开的方块都是地雷
  • 如果已找到的地雷数和数字符合,那么未开的方块都是安全的

多方块分析

解多数字方块时,必须得用其他与上述不同的策略,其策略如下:

示例图标


以图标中3个数字方块来看,我们可以推断a到e这5个方块有不同的地雷配置方式:\{a,b,c,d,e\} = \{1,0,1,0,0\}\{0,1,1,0,0\}\{1,0,0,1,0\}\{0,1,0,1,0\}(1代表地雷)。从这几种配置方式当中,不难发现e不带有地雷,是安全的方块。

我们也可以用代数的方式来解,变量一样维持{0,1}这两种。从示例中可得知a+b=1、c+d=1和a+b+c+d+e=2,第三个等式套上第一跟二的条件后可得到1+1+e=2,所以e=0,代表不是地雷。

   

 算法所基于的“获胜”理念:

 普通的简单算法实际上已经http://blog.renren.com/blog/0/addBlog?bfrom=011200091可以在很短的时间内很好地去解决初始难度和中级难度的关卡。有时候,如果我们幸运的话,这个算法也可以用来解决一些高级的关卡。

当人们玩扫雷的时候,我们会尽可能最快地去完成扫雷。所以我们不介意为了每个游戏的胜利而失败了20次游戏:只有胜利的才算。

 扫雷定式:

   寻找常见的数字组合(定式),这有助于判雷,减少思考的时间[8]。例如,在一组未挖开的方块的边上出现相邻的三个数字 2-3-2 表示这三个数旁边都是地雷,若出现1-2-2-1则两个2上有雷而两个1上无雷。

两个1夹一个2【-1-2-1-】,两个1处必有雷,2必无雷[9]

两个2夹一个1【-2-2-1-2-2-】,中心的1必有雷;

两个2夹n个3【-2-3-3-2-】,2和3边上全是雷;

连续的两个2靠边【|2-2-】,2边上都是雷;

连续的三个1靠边【|1-1-1-】,远离边的那个1无雷; 

连续的三个1被夹在中间【|1-1-1|】,中间的1有雷,两边的1无雷;

连续的四个1被夹在中间【|1-1-1-1|】,两边的1有雷,中间的1无雷。

说 明:方括号中的“|”表示边或已打开的方块,数字为未知方块正下方的数字。定式需要灵活运用,这里的数字都没有考 虑周围已标记地雷,如果已经标记了地雷,则需要先用数字减去周围雷数,再应用定式(比如出现【-2-4-2-】,但是已知两个2周围已经各有一个雷,4周 围已经有两个雷,则可以简化成【-1-2-1-】)。这些原则若能熟练掌握,能大大缩短扫雷时间并提高完成率。 

 

 标雷与局部优化策略:

 

 在扫雷的过程中,对同一特定局部的处理,不同的玩家会有不同的选择,但所耗费的时间却不相同。为了缩短整局完成的时间,我们有必要在每一个局部对操作进行优化,避免无效的点击和移动。这样积累下来的时间节省十分可观[10]

 一些玩家从不标雷,因为花费在插旗上的时间可以直接用来单击打开更多的格子,这种风格叫做盲扫。盲扫适用于3BV较低的地图,但对于一些局面,特别是地雷分布比较均匀的局面并不能实现局部最优化操作。实际上,标雷和盲扫这两种技术组合后才能对每一个局部使用最有效的解决方法[8]

 

 

 简单算法的局限:

 到此为止,每当我们标记一个方块为有雷或者安全的时候,我们只需要考虑一个3X3的大方块。这个攻略使我们失败在这里:解决窍门是使用多方块算法---一次可以读取多个不同的方块。

 简单(朴素)算法被卡住的地方:

 

 

 

 一个问题刚解决,另外一个问题又来了:

 从最下面的2,我们可以知道在红色圈圈中的两个方块中有一个是地雷,其中一个不是地雷。我们只是不知道哪个是地雷而已:

 

 

 

 此刻,虽然不能告诉我们什么,我们可以结合此信息下一步:我们可以推断出这两个黄色的方块是空的。(表示没有地雷)

 

 让我们可以肯定的点击他们。

 

 看吧, 他们是空的(没有地雷)。 这个难题迎刃而解,我们已经做了推论,这两个方块是空的。

 坦克算法:

  我们很难可以让计算机像我们一样去推测。但这里有一个方法,可以不用推论思考也可以达到同样的效果。

 坦克算法的思想是枚举所有可能的地雷位置的组合,然后看看在这些位置组合中有什么共同点。

 举例说明什么是坦克算法:

 在这个例子中,这里有两个可能的组合:

 

 你可以为自己检查一下,这里没有别的组合可以行得通了。我们可以推测:那些有X的方块肯定有地雷,其他3个白色阴影部分的肯定没有地雷:

 

 优化坦克算法(回溯):

 我们总是最先尝试去用简单算法,只有当我们被卡住了,我们才会使用坦克算法。

为了实现坦克算法,我们首先要做一个镶边瓷砖列表:所有我们不确定但有部分信息的方块列表。

现在我们有一个列表T。如果我们考虑到每个组合的可能性,这里有个组合。利用回溯法,这些数字可以减得足够少可以为这个算法变得有实用性,但我们可以弄一个重要的最优化。

 不相交区域:

 

 如果你看得很细心,不管发在绿色区域发什么什么都对粉红色的区域发生什么没有任何影响---我们可以有效地把他们分开考虑。

 优化之后的效果:

  我们得到了多少的速度提升呢?在这个种情况下,绿色区域有10个方块,粉红色的有7个。把他们结合起来,我们需要搜索 组合。在分离开的情况下,我们只需要 次:大约提升了100倍的速度。

事实上,最优化使算法暂停了几秒的时间(有时候几分钟)去思考,然后马上给出解决方案。

 扫雷游戏中的概率论:

  扫雷过程中可能会遇到一些没有确定解,必须要猜的情况。人脑能快速定性分析,但不擅长于定量分析,所以正常操作下玩家的胜率远低于扫雷游戏的极限胜率。在扫雷过程中,每一步中每个位置是雷的概率都可以基于

 扫雷局部示例

代数方法得到[30]

以右图为例:6*6个格子中包含11个雷,打开了3个格子之后,求其周边的格子X1~X12是雷的概率[31]

首先是3个数字产生的约束条(这里写成方程组的形式,也可写成矩阵相乘的形式):

① X1 + X2 + X3 + X4 + X5 + X7 = 1

② X4 + X5 + X7 + X9 + X10 + X11 = 3

③ X5 + X6 + X8 + X10 + X11 + X12 = 2

  解方程组得到的19组解

方 程组共有19组解(见上图图示),其中的4组对应X1~X12中有3个雷,剩下的15组对应X1~X12中有4个雷。结合总雷数和未打开格子数的限制条 件,总共可能的变化数为 T=4*C(21,8)+15*C(21,7)=2,558,160 。以此求出的各个位置是雷的概率。

 

P(X1)=P(X2)=P(X3)=0.0454;

P(X6)=P(X8)=P(X12)=0.182;

P(X4)=0.352; P(X5)=0.159; P(X7)=0.352;

P(X9)=0.841; P(X10)=0.648; P(X11)=0.648.

 

posted on 2013-02-28 12:04  吴昊系列  阅读(783)  评论(0编辑  收藏  举报

导航