文 章
21-05
30
俄罗斯方块游戏-基于贪心策略的简易AI实现
分类: 小游戏
本网站的项目列表中有一个在线俄罗斯方块小游戏,可以直接看游戏AI的运行效果,也可以自己玩。该网页游戏是使用HTML5和Javascript编写,代码是开源的(直接浏览器查看源代码或者保存网页即可),欢迎探讨与改进。
下面就聊聊这个俄罗斯方块游戏以及AI的机制。
1. 游戏元素构成
地图(背景):18x12个格子的二维数组(可按照需求进行调整),由(行,列)坐标来定位任意一个格子。
每个形态的方块都是一个4x4个格子的二维数组,数组中为0的部分对应空白格子,而非0的部分对应非空的格子。比如T型方块的4种形态用二维数组表示如下(从左至右):
颜色:为了丰富游戏的视觉效果,每种方块都被赋予一种随机生成的颜色(红黄蓝绿),相比之下地图中的空白格子就是固定的灰色。这样就能通过不同的颜色值来区分方块与地图中的空白与非空格子。
2. 游戏控制逻辑
游戏的基本控制流程如图3所示:
各个步骤实现思路如下:
3. 游戏AI的设计
AI就是代替人,由程序自动去玩游戏,目的当然是为了学习(装x)。
这里选择以贪心策略来设计俄罗斯方块游戏的AI。贪心策略的思想是分几个阶段求解一个问题,在每个阶段都做出在当前看来是最好的选择。简单地说就是只考虑局部最优,而不一定能够达到整体最优。
之所以选择这种方法,是因为它简单且有效。由于方块是随机产生的,这种情况下“走一步看一步”也比较符合人玩游戏时的情形。但是本文所讨论的贪心策略比较简单,它故意忽略一些信息来简化需要考量的指标:
基于这种简化,贪心策略的考量指标包括以下4点:
1. 增加饱和行数量
需要注意的是,有时在产生饱和行的同时,也会产生坏格子(如图b),因此还需要进一步对比。
2. 增加行平均非空格子数量
这个应该是最普遍的放置方块情形,也是最核心的目标。按照这种策略,方块会往非空格子数量多的行处聚集,从而更快产生饱和行。方块也会倾向于以“躺平”的形态落地,从而降低块堆积高度。
3. 减少坏格子数量
4. 降低块堆积高度
这个很容易理解:地图上块堆积得越高,也就越容易导致Game Over。由于方块在落到一个地点时,最多只会影响它所占据的地图上的几列,因此只需要计算该列范围内的块堆积高度,高度越小越好。
以上4个目标中,除了第1个目标(增加饱和行数量)的优先级永远最高以外,其余的3个目标(增加行平均非空格子数量、减少坏格子数量、降低块堆积高度)之间的优先级,是根据地图上已有的块堆积高度来动态调整的:
计算开销:该AI在决策过程,需要对比方块的所有形态和落地位置组合。对于一个给定类型的方块,它的形态最多有4种,落地位置最多有M种(M是地图的列格子数量)。于是总共的判断组合就有4xM种,这种计算开销对于本游戏中设置的M=12是完全可以接受的。
有了AI,人机大战也可以有了,不同AI之间的PK也可以安排上,坑好像越来越大了,好像越来越有意思了。
地图(背景):18x12个格子的二维数组(可按照需求进行调整),由(行,列)坐标来定位任意一个格子。
方块类型:方块是游戏操控的基本单元,总共有7种类型,分别是I、J、L、O、S、T、Z型,如图1所示。
图1. 俄罗斯方块游戏的7种方块类型
方块形态:每种类型的方块还能以顺时针方向旋转。每次旋转90度,因此每种方块共有4种形态(不考虑重复)。图2展示了T型方块的4种旋转形态。
图2. T型方块的4种旋转形态
每个形态的方块都是一个4x4个格子的二维数组,数组中为0的部分对应空白格子,而非0的部分对应非空的格子。比如T型方块的4种形态用二维数组表示如下(从左至右):
[[0, 0, 0, 0], [[0, 1, 0, 0], [[0, 0, 0, 0], [[0, 0, 0, 0],
[0, 1, 0, 0], [0, 1, 1, 0], [0, 1, 1, 1], [0, 0, 1, 0],
[1, 1, 1, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 1, 1, 0],
[0, 0, 0, 0]] [0, 0, 0, 0]] [0, 0, 0, 0]] [0, 0, 1, 0]]
[0, 1, 0, 0], [0, 1, 1, 0], [0, 1, 1, 1], [0, 0, 1, 0],
[1, 1, 1, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 1, 1, 0],
[0, 0, 0, 0]] [0, 0, 0, 0]] [0, 0, 0, 0]] [0, 0, 1, 0]]
颜色:为了丰富游戏的视觉效果,每种方块都被赋予一种随机生成的颜色(红黄蓝绿),相比之下地图中的空白格子就是固定的灰色。这样就能通过不同的颜色值来区分方块与地图中的空白与非空格子。
2. 游戏控制逻辑
游戏的基本控制流程如图3所示:
图3. 俄罗斯方块游戏基本处理流程(绿色部分由玩家操控)
各个步骤实现思路如下:
- 画格子:利用HTML5 Canvas在指定位置画矩形并填充颜色。
- 生成新方块:随机选择一种类型和形态的方块,然后进行绘图。
- 旋转与移动方块:键盘←→键左右移动方块,↓键让方块加速下落,↑键让方块以顺时针方向旋转。每个方块都会以其左上角的格子在地图中的行列值来确定其位置,据此来进行方块的绘制。在一次方块移动或旋转的过程中,是先在其旧位置的非空格子处画上背景(擦除),然后在新位置的非空格子处画上自身的颜色(显现),由于该过程非常快,在肉眼看来方块就按照指示实现了位置或形态变换。
- 方块定期自动下落:使用setInterval(drop_func, interval_msec)实现以interval毫秒为周期来调用下落函数drop_func()。
- 方块停止下落:当方块停止下落后,其中非空的格子就会成为地图背景的一部分,这是通过将相应格子的颜色值赋值给地图上的相应格子实现的。这样,后续判断方块是否允许下落就要通过方块的非空格子是否与地图上已有的非空格子重叠来实现。
- 消除饱和行:当地图上的某一行全部被非空格子占据后(饱和),该行就可以被消除。由于一个方块停止下落后,它只会影响自身所在行的非空格子数量。因此在判断哪些行应该被消除时,只需要扫描方块所在区域的所有行。每消除一行,就将其上方的所有行向下移动一行,并根据它们的新位置重新绘图。
- 方块堆积高度:地图上未能及时消除的方块格子会堆积起来,逐渐挤占新方块的移动空间。当方块的堆积高度接近最高点时,新的方块将无下落空间,游戏便会结束。
3. 游戏AI的设计
AI就是代替人,由程序自动去玩游戏,目的当然是为了学习(装x)。
这里选择以贪心策略来设计俄罗斯方块游戏的AI。贪心策略的思想是分几个阶段求解一个问题,在每个阶段都做出在当前看来是最好的选择。简单地说就是只考虑局部最优,而不一定能够达到整体最优。
之所以选择这种方法,是因为它简单且有效。由于方块是随机产生的,这种情况下“走一步看一步”也比较符合人玩游戏时的情形。但是本文所讨论的贪心策略比较简单,它故意忽略一些信息来简化需要考量的指标:
- 不考虑下一个方块的信息,而只利用当前的方块和地图信息。
- 在方块开始垂直下落后就不再允许左右移动,也就是不允许如下的操作:
图4. 人为填补坏格子(上方有非空格子的空白格子)的操作
基于这种简化,贪心策略的考量指标包括以下4点:
1. 增加饱和行数量
饱和行是可以被立即消除的,这也是游戏得分的关键。因此放置方块使地图上产生最多饱和行是最为优先的目标。
图5. 优先产生更多饱和行
需要注意的是,有时在产生饱和行的同时,也会产生坏格子(如图b),因此还需要进一步对比。
2. 增加行平均非空格子数量
如果无法产生饱和行,那就尽可能增加行的平均非空格子数量。它是计算方块落地点中,方块所影响的所有行的平均非空格子数量。
图6. 优先产生平均非空格子数更多的行
这个应该是最普遍的放置方块情形,也是最核心的目标。按照这种策略,方块会往非空格子数量多的行处聚集,从而更快产生饱和行。方块也会倾向于以“躺平”的形态落地,从而降低块堆积高度。
3. 减少坏格子数量
坏格子会增加块的堆积高度且填补难度较大,因此应该尽量避免在放置方块时产生新的坏格子。除此以外,对于地图上已经存在的坏格子,也应该尽量避免将方块堆积在它的上方,这样会增加后期填补坏格子的难度。
图7. 优先减少坏格子数量
4. 降低块堆积高度
这个很容易理解:地图上块堆积得越高,也就越容易导致Game Over。由于方块在落到一个地点时,最多只会影响它所占据的地图上的几列,因此只需要计算该列范围内的块堆积高度,高度越小越好。
以上4个目标中,除了第1个目标(增加饱和行数量)的优先级永远最高以外,其余的3个目标(增加行平均非空格子数量、减少坏格子数量、降低块堆积高度)之间的优先级,是根据地图上已有的块堆积高度来动态调整的:
- 块堆积高度较低时,以减少坏格子数量为最优先。此时不用担心块堆积高度过高的问题,而是应该尽量将坏格子的产生扼杀在萌芽之中。
- 块堆积高度中等时,以增加行平均非空格子数量为最优先。这样一方面可以加快产生饱和行,另一方面可以降低块堆积高度。
- 块堆积高度较高时,以降低块堆积高度为最优先。此时的主要目的是多“存活”一段时间,因此应该优先保证较低的块堆积高度。
计算开销:该AI在决策过程,需要对比方块的所有形态和落地位置组合。对于一个给定类型的方块,它的形态最多有4种,落地位置最多有M种(M是地图的列格子数量)。于是总共的判断组合就有4xM种,这种计算开销对于本游戏中设置的M=12是完全可以接受的。
运行结果:图8中的结果是目前已知的最好运行结果,其中最多消除了275行。如果按照1秒钟产生与处理完一个方块来计算,该AI总共坚持了30分钟。
图8. 基于贪心策略的俄罗斯方块AI的最好运行结果
有了AI,人机大战也可以有了,不同AI之间的PK也可以安排上,坑好像越来越大了,好像越来越有意思了。
(转载本站文章,请注明出处)
«上一篇:
八年后,LeftGeek的(短暂)回归
下一篇:
GitHub Pages - leftgeek.com的归宿
»
暂无评论