作者 | Ahab

责编 | 仲培艺

人工智能大火的本日,如果还是自己玩俄罗斯方块难免不免显得太 LOW,为什么不对游戏升级,让机器自己去玩俄罗斯方块呢?有了这个想法之后,我用了两天韶光去搜集了大量资料,在电脑去世机好多次之后终于将 AI 俄罗斯方块实现了。

程序先容

让 AI 教机械自己玩俄罗斯方块

所谓让机器自己去玩俄罗斯方块,便是让机器打算当前方块的所有形态可放置的所有位置,然后根据统一的评价标准,打算出最优的位置进行放置。
这个评价的标准大略的来说便是:板块放置的位置越靠下越好,方块之间越紧密越好,自身对肃清行的方块贡献数量越多越好,但是这里还要把稳的是不可为了追求肃清行数,而去造成过多的空洞,这样也是不合理的。

关于 AI 算法紧张有两种:一种是经典的 Pierre Dellacherie 算法,一种基于基于深度搜索的算法。
深度搜索须要优化的地方很多,如果打算的层数不足、没有高效剪枝,一欠妥心随意马虎写成人工智障,韶光繁芜度也不好。
Pierre Dellacherie 算法更加清晰,繁芜度更低。
但是该算法只考虑当前,不对未来的情形进行打算,看重的是“不去世性”,追求方块的“密集”,有时就算可以一次性肃清 3 行,却会使全局方块更加“疏”,即过多的空洞。

代码由 Tetris.py、AI.py 和 Utils.py 三部分组成,游戏的紧张逻辑由 Tetis 掌握,Utils 定义了方块的样式,AI 顾名思义实现了紧张的 AI 算法。

详细先容

Pierre Dellacherie 算法

只考虑当前方块,不对未来的情形进行打算,看重的是“不去世性”,算法每次天生一个方块,便穷举该方块所有旋转的落点。
一种方块最多有 4 种旋转,并且由于游戏界面是 1020 的,以是对付每个旋转形状,只须要考虑 10 种落点。
算法的核心是一个评估函数,对穷举出的每一种着落情形,打算 6 个参数值,用评估函数加权求和得到一个值,该值最大的情形便是目前方块的最优着落位置,六个参数分别是:

1. 着落高度(Landing Height)

当前方块落下去之后,方块中点距底部的方格数(事实上,不求中点也是可以的)。

2. 消行数(Rows eliminated)

消行层数与当前方块贡献出的方格数乘积。

3. 行变换(Row Transitions)

从左到右(或者反过来)检测一行,当该行中某个方格从有方块到无方块(或无方块到有方块),视为一次变换。
游戏池边界算作有方块。
行变换从一定程度上反响出一行的平整程度,越平整值越小;该指标为所有行的变换数之和;如图: 表示有方块,□ 表示空格(游戏池边界未画出)□□□□□□ 变换数为 6□□□□□□□□ 变换数为 9□□□□□□ 变换数为 2 变换数为 0

4. 列变换(Column Transitions)

大意同上,列变换从一定程度上反响出一列中空洞的集中程度,空洞越集中值越小。

5. 空洞数(Number of Holes)

6. 井的总和(Well Sums)

井指两边皆有方块的空列。
该指标为所有井的深度连加到 1 再求总和。

把稳一列中可能有多个井,如图:

□□

□ □ □ □ □

中间一列为井,深度连加到一的和为 (2+1)+(3+2+1)=9

评估函数如下 (首字母简写):

关于方块形态

这里对 AI 俄罗斯方块的形态做一下特殊解释,各个方块都是根据中央点的坐标来天生的,以(0,0)为中央点,在 x、y 轴加减 1 则是其他方格的坐标,这样的好处便是只要确定中央点坐标,其他的方格位置就能随即天生。

看图就懂:

1# 每种块包含的四个小方块相对坐标分布 2 self.shapes_relative_coords = [ 3 [[0, 0], [0, 0], [0, 0], [0, 0]], 4 [[0, -1], [0, 0], [0, 1], [0, 2]], 5 [[0, -1], [0, 0], [0, 1], [1, 1]], 6 [[0, -1], [0, 0], [0, 1], [-1, 1]], 7 [[0, -1], [0, 0], [0, 1], [1, 0]], 8 [[0, 0], [0, -1], [1, 0], [1, -1]], 9 [[0, 0], [0, -1], [-1, 0], [1, -1]],10 [[0, 0], [0, -1], [1, 0], [-1, -1]]11 ]

基于深度搜索的方法暂不先容。

收成成果

以上,感兴趣的同学可通过网盘获取源代码:https://pan.baidu.com/s/1gC6sF62Pz5D6rh6eicOZUw,提取码: k17b。

作者简介:"大众年夜众号【Ahab杂货铺】号主,在校学生沉迷于Python编程。