
作为入门学校的学生,您会构建许多较小的项目,以测试您对某些课程主题的知识。 他们很有帮助,常常会激发他们的动力,但它们并不会激发真正的附带项目的乐趣:您对此感到兴奋并且几乎太热情了。 因此,在圣诞节放假期间,我发现自己有一段安静的日子-进行此类辅助项目的好时机!
我最初的灵感来自“代码问世”竞赛,该竞赛每年举办一次,提供24个编码难题,用于测试您的问题解决能力和算法思维。 我特别喜欢两个谜题:一个是处理细胞自动机的谜题,另一个是模拟洞穴中精灵与妖精之间回合制战斗的方法(是的,这些谜题通常都有一些荒谬的背景故事)。
蜂窝自动机:一种简单而又聪明的算法
在解决了特定的代码出现难题之后,我阅读了Cellular Automata 。 蜂窝自动机最流行的变体之一是康威的《生命游戏》 。 它模拟了带有根据一组规则进化的活细胞的网格。
阅读Wikipedia页面之后,我在Ruby中构建了自己的实现,并且比预期的要容易,因为它实际上没有太多的复杂性。 您可以看到我的《人生游戏》的运用:

那么, 细胞自动机到底是什么? 通常,它通过一组规则描述了二维结构的转换。 听起来太抽象了? 让我们看看“人生游戏”意味着什么。
我们从一个空的网格开始。 理想情况下,它会无限大,但是我们可以通过定义一个简单的二维单元格数组来限制它,如下所示:
行,cols = x,y
Array.new(rows){Array.new(cols)}
然后,我们需要一个初始配置 。 也就是说,我们随机分配该网格中的每个单元两个状态之一,例如“生命游戏”中的 死亡或存活状态。 在下面的草图中,浅灰色的单元格还活着,而深色的单元格则死了。

元胞自动机的核心是确定下一个进化步骤网格中每个单元的命运的转换规则。 这些规则着眼于每个单元的邻居。

每个单元正好有八个邻居。 邻居的数量可以用邻接矩阵确定:
相邻= [
[-1,-1],[0,-1],[1,-1],
[-1,0],[1,0],
[-1,1],[0,1],[1,1]
]
查看每个细胞的相对位置,我们可以简单地计算出活细胞的数量。 然后,我们应用四个简单的规则来查看细胞是在下一代中存活还是死亡。 这些规则是:
- 少于两个邻居的活细胞在下一代中死亡。 这称为饥饿 。
- 当一个活细胞恰好有两个或三个邻居时,它会保留在下一代中。
- 如果具有三个以上的邻居,那么下一代的活细胞就会死亡。 这称为人口过剩 。
- 如果一个死细胞正好有三个邻居,那么它将在下一代中重生。

例如,在此配置中,所有活细胞(灰色)将在下一代中生活,因为它们每个细胞都恰好具有两个或三个邻居。 这种配置将产生稳定的细胞生物,该生物不会在模拟过程中发生变化,除非另一个生物过于靠近并破坏平衡。

但是,在这种设置中,孵化的活细胞将在下一代中死于种群过多,因为它们具有三个以上的邻居。
就是这样,将这四个规则转换为代码就可以实现Conway的《人生游戏》 。
从“生命游戏”到生成地牢
如果几天后不是另一个Advent of Code难题,那我就留给它了。 这个难题本身涉及一堆地精和小精灵的模拟,但它具有一个复杂的环境,该环境是为每个Code Advent参与者唯一生成的。 它使我想起了我喜欢的某种类型的电子游戏:所谓的Rogue-likes 。

类Rogue游戏以其最古老的祖先命名:一款名为Rogue的游戏。 在其中,您可以控制英雄角色(通常在游戏中以@符号表示),并探索地牢和洞穴,杀死怪物并在途中寻宝。 所有类似Rogue的游戏都有一个重要的核心原则(除了非常艰苦):程序的大部分内容是程序生成的 ,例如,这意味着每个级别图都可以通过算法随机创建。 最终结果通常以简单的ASCII字符显示。 这些美学使我想起了《生命游戏》的实现,我开始怀疑:通过对《生命游戏》算法进行一些修改,我还能生成随机的地牢和洞穴吗? 如果是这样,我可以自己编写一个类似于Rogue的小型游戏吗?

我想在制定任何重大计划之前先验证一下自己的假设,因此我修改了《人生游戏》算法。 我删除了人口过剩的规则,因为我想获得带有壁的大型结构,而不是微小的漂浮细胞生物。 然后,我根据其余可以调整的规则创建了一组参数,并查看结果是否接近我的想象:
WALL_CHANCE = 0.25#初始墙壁的几率
ITERATIONS = 7#不。 代模拟
WALL_EVOLUTION = 5#最少的邻居壁可以长出新的
WALL_STARVE = 2#最小邻居墙不消失
这些参数中的大多数都是一个最佳选择,并且不需要太多调整就可以得到惊人的结果:

那些看起来确实像洞穴地图! 生成的地图种类繁多。 我很高兴,并且我的辅助项目构想得以形成。
后来我发现, Cellular Automata在游戏开发中的用途非常相似(尽管通常以更精致和巧妙的方式)。 另外,它们还用于模拟某些生物学或化学模型中的自然行为,因此它们用途广泛。
好吧,现在我有了一张很酷的地图,但仅此而已。 如何将其变成完整的游戏体验?
继续第2部分,或查看项目的GitHub存储库 (可以在lib / cavegen.rb文件中找到我的洞穴生成算法)。 只需按照自述文件中的说明进行安装和播放。