2048这个游戏相信大家都不陌生吧
游戏的规则很简单,你需要控制所有方块向上下左右的某一方向运动,方向上两个相同数字合并会相加,每次移动后在空白处生成一个2或者4,最终得到一个“2048”的方块就算胜利了。
虽然简单但却虐心,今天我们就来分析这个游戏的算法原理,并用python把这个游戏写出来。
ok,我们分析的思路就是给这个游戏来一个二向箔,降维打击,如何做,可以往下看。
首先我们把游戏4*4的方格,称之为棋盘,然后忽略棋盘的背景和颜色,使之变成4*4的田字格,田字格里是对应的数字,空白的方格用0填充,如下图
图变成了一个4*4的方格,接下来去除方格,把每一行提取出来写到python的列表里,比如第一行变成 [2, 0, 2, 0], 那么这个4*4的方格,就变成了一个4*4的二维矩阵
抽象成python的数据格式之后,我们看数字移动和数字加减的操作。
以向左移动为例,移动的结果,第一行会变成[4, 0, 0, 0 ], 第三行会变成[8, 0, 0, 0],即
可以想象每一行计算的方法是一致的,只要搞定了一行数字的移动算法,那么整体4行就是把这个算法执行4遍即可。所以我们就完成了初步的降维,把4*4的计算,变成了4*1的计算。
那么接下来我们以第一行的数字的移动为例,介绍数字该怎么移动。
还看移动之前该矩阵的第一行 [2, 0, 2, 0], 向左移动时,需要把不为零的数字,一起向左移动,第一位的2不需要移动,第二位是0,不看,第三位的2,需要往左一位。那么我们换个思路,2向左移动,是不是可以看成是第二位的0向后移动,如果我们把第二位的0先删掉,[2, 0, 2, 0] 变成 [2, 2, 0], 然后再把0在最后添加进去,[2, 2, 0]变成[2, 2, 0, 0],这样2就向左移动了,神奇不神奇?
那我们完成了移动,怎么完成相同的数字相加呢?
其实只要从行的第一位开始,比较它和它后边的那一位,如果一样,就把它乘以2,然后把它后边的那一位删掉,最后在行的末尾添加一个0,保证矩阵的shape一直是 4*4。
操作可以看下图
ok,到这里完成了一行的向左移并相加的算法,那么四行的算法是一致的,也就完成了整个4*4矩阵左移并相加的操作。
那么问题来了,向右移该怎么做呢?
其实右移和左移的操作很相似,只在行的方位上移动数字,行与行之间没有什么直接操作,那么在右移时,先把每一行逆序一下,也就是 [2, 0, 2, 0]变成 [0, 2, 0, 2], 再做左移的操作,完成之后,把结果再逆序一下,是不是就ok了呢?
我们来看一下
再问你一遍,神奇不神奇?
更神奇的还在后边呢,目前完成了左移和右移的操作,那么上移和下移呢?接下来我们要给这个游戏来第二次降维打击。
这里要用到一个我们学过的线代的知识,矩阵的转置,什么?你说不知道。ok,意思就是行转列,列转行的操作。
什么?还不知道?看图理解
这下清楚了吧。
细心观察之后,你会发现,原本矩阵数字上移的操作,经过转置之后就变成了左移的操作。又可以用我们之前的算法了。(鼓掌)
那么上移的操作就变成了 转置-->左移-->再转置。
那么下移呢,聪明的你肯定已经猜出来了。
没错下移就是 转置-->右移-->再转置。
ok,至此,2048游戏核心逻辑,分析完毕,来个总结:
1. 以左移为基础,把4行的操作看成1行的操作。
2. 左移的操作,先把0全部移到行的末尾
3. 然后从行第一位开始,判断与后一位是否相等且不等0,若相等该位乘以2,删除后一位,末尾添加0
4. 右移操作是 行逆序--左移--再逆序
5. 上移操作是 矩阵转置--左移--再转置
6. 下移操作是 矩阵转置--右移--再转置
下边开始撸代码,let's go。
这里只展示核心逻辑的代码实现,其余代码就不一一展示了,有兴趣的私信回复 2048 即可获取完整的源代码。
效果展示:
好的,装x完毕,撤(完)。