当前位置: 首页 > 科技观察

用 90 行 Haskell 代码实现 2048 游戏

时间:2023-03-17 13:04:31 科技观察

用90行Haskell代码实现2048游戏中的交互编程。瑕疵,我觉得2048不是特别好玩。首先,你无法在某个地方赢得比赛。其次,最有前途的游戏策略玩起来比较乏味,乐趣不是自己的游戏技巧,而是随机数发生器创造的连胜。就个人而言,我更喜欢有时被称为“理论***”的东西,即游戏的一种属性,它使玩它的人可以取得一定的胜利。2048的游戏结果对我没有吸引力,但我明白为什么有人喜欢让方块四处滑动。为游戏逻辑编写代码非常简单。由于使用Python作为教学语言的计算原理课程,如果我的原始版本中的错误是由于python的更改引起的,我不会感到惊讶。我认为用Haskell编写它可能更有趣,然后着手用这种语言编写2048的完整实现,包括I/O处理。整个代码可以在我的git帐户上找到。事实证明,一个更完整的Haskell解决方案需要的代码比Python中的程序逻辑更少的行数。请注意,如果您在此页面上寻找计算规则课程的Python作业的解决方案,那您就是在浪费时间。Haskell的实现与Python的实现有很大的不同,使用的编程语言构造在Python上也不可用。换句话说,如果您正在努力完成这项任务,Haskell源代码将无济于事。在本文中,我只想强调游戏逻辑的核心部分,因为它很好地展示了函数式编程的强大。首先,我定义了一个数据类型来显示网格中数字移动的方向,并定义了一个整数列表的类型同义词以提高类型特征的可读性。从函数'move'的命名就可以清楚的看出函数的作用;下一步,输入一个网格的个数和移动方向,生成一个新的网格。dataMove=Up|Down|Left|RighttypeGrid=[[Int]]2048游戏在4x4棋盘上进行。起始位置在我的实现中是固定的:start::Gridstart=[[0,0,0,0],[0,0,0,0],[0,0,0,2],[0,0,0,2]]棋盘上的数字可以向4个方向移动,即所有的数字都会向指定的方向移动。如果有2个数,向同一个方向移动,彼此相邻,最后合并在一起。例如,在下图的起始位置,移动方向为‘Up’,则结果板变为:[[0,0,0,4],[0,0,0,0],[0,0,0,0],[0,0,0,0]]如果将网格中的起始位置向右移动,则不会发生变化。如果格子发生变化,在任何一个空格子中都会产生一个新的数字,这个数字可能是2,也可能是4。我们看这个方法,问题是如何更有效地建模。网格中的任何行和列都可以理解为一个列表。行和列表之间的关系很简单。必须再次提取、修改或插入列。或者他们不需要?我写了一个函数来合并一行或一列,表示为一个列表。首先,移动所有的零,然后处理列表,如果相邻元素包含相同的数字则合并它们,然后在必要时用0填充结果。merge::[Int]->[Int]mergexs=merged++paddingwherepadding=replicate(lengthxs-lengthmerged)0merged=combine$filter(/=0)xscombine(x:y:xs)|x==y=x*2:combinexs|否则=x:combine(y:xs)combinex=x当棋盘中的移动中心离开时,可以立即应用此组合功能。然而,如果要保持代码干净,则转向其他方向需要一些考虑。将网格向右移动是通过在将其提交给函数合并之前获取反转它的每一行来完成的,然后再次反转结果:move::Grid->Move->GridmovegridLeft=mapmergegridmovegridRight=map(reverse.merge.reverse)gridmovegridUp=transpose$move(transposegrid)LeftmovegridDown=transpose$move(transposegrid)Right用于上下移动网格,如果要提取列,对其应用合并功能,并生成新网格进行列插入非常痛苦。相反,只要对线性代数有一点了解,就会得出更优雅的解决方案。如果您不是很清楚换位是如何产生预期结果的,请查看下图。inputtransposemovetranspose00022022220220002220020000200222我的Haskell实现使用终端作为输出。它不像GabrieleCirulli的JavaScript前端版本那样令人印象深刻,但它是可维护的,如以下两个屏幕截图所示:总的来说,我对原型很满意。当然有几个可能的改进。添加一个分数跟踪器将是微不足道的,尽管GUI将是一项更耗时的工作。如果有一个程序可以立即响应键盘输入,我会觉得这很有趣。目前,通过WASD进行的每个输入都需要使用Enter键进行确认。如果只按一个键会触发程序执行的下一步,游戏过程会快得多。在研究这个时,我没有找到任何快速修复。尽管Haskell库NCurses包含键盘事件。如果我用ASCII图形对其进行编程以使其成为“独立”游戏,我可能会更深入地挖掘。如果您觉得这篇文章有趣,请随时查看我的Haskell实现2048的源代码。英文原文:Implementingthegame2048inlessthan90linesofHaskell翻译自:http://www.oschina.net/translate/2048-in-90-lines-haskell