什么是游戏2048的最佳算法

问题

我最近偶然发现一款叫2048的游戏。你需要通过上、下、左、右的方向移动来合并值相同的方块(Title)。每一次移动之后,一个新的值为2或者4的方块会随机的出现在某个空的位置。所有位置都塞满方块,并且没有值相同的方块可以移动的时候,游戏结束。游戏的目标是构造一个值为2048的方块。

我需要遵循一套定义良好的策略来实现这个目标。所以我想到写个程序来实现。我当前的算法如下:

while(!game_over)
{
    for each possible move:
        count_no_of_merges_for_2-tiles and 4-tiles
    choose the move with large number of merges
}

我所做的是,在任何时点,我都尝试合并值为2或者4的方块,也就是我会尝试让值为2和4的方块越少越好。如果我尝试那么做,其它的方块会自动的合并,看起来像是个好策略。

但是当我真正使用这套算法的时候,我大概只能得到4000分,游戏就结束了。游戏的最高分应该是20000多点,远超我当前的分数。有比上面策略更好的算法吗?

最佳回答

我是AI程序的作者,前面也有人提到AI程序。你可以看AI的运用或者直接阅读源代码

当前,这套运行在我笔记本浏览器的javascript程序能够达到90%左右的胜率,每次移动的思考时间是100毫秒。尽管不是最完美,但干得还不赖。

既然这个游戏是一个离散状态空间,信息完备的回合制游戏,类似于象棋和国际跳棋,那么我就使用了针对这些游戏的证明过的行之有效的方法。一套叫minimax search的算法,结合了alpha-beta pruning。既然已经有很多信息解释了这套算法,那么我就仅谈谈我在static evaluation function中使用到的两个重要概念。这将会把一些人在这里表达的直觉形式化。

单调性(Monotonicity)

这个概念保证方块的值沿着上下左右方向的,要么增加,要么减少。这个概念单独地解释了一个大家提到的直觉,值较大的方块应该聚集到某一个角落。这将有助于阻止值小的方块被孤立起来,也将让面板保持良好的组织结构,使得值小的方块渐进层叠式的并逐步合并为值大的方块。

下图是一个有完美单调性格子的截屏。我通过运行eval函数被设置为忽略其它概念的算法获得,仅仅考虑单调性。


平滑性(Smoothness)

上面的概念倾向于构造值递减的结构,但如要合并,相邻的方格值必须相同。因此,平滑性衡量相邻方格值的差,并尝试减少差。

Hacker News上的一个评论者用图论给出了一个平滑性的有趣解释。来源于2048的一个优秀分支

下图是个有完美单平滑性的截屏。


空闲方块(Free Tiles)

最后,有一个针对空闲格子过少的惩罚。毕竟面板过于拥挤的时候,选择受限且很快会被用完。

就是这样。扫描游戏格子,同时优化以上标准,这会产生相当好的表现。与明确硬编码的移动策略相比,这种使用通用性的方法有一个优点,这种算法可以找到有趣且难以预料的解决方案。如果你观察它运行,它经常会做出一些惊奇但有效的移动,比如突然转向一个相反的墙或者角落。

修改

这是该方法强大能力的一个展示。我拿掉了方格值大小的限制(到2048之后还可以继续运行,下图是8次尝试中最好一次的截屏,是的,那可是一个4096外加一个2048),那意味着在同一个面板上它完成了3次困难的2048。


原文地址

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值