贪吃蛇游戏详解:历史、策略、计分数学,以及我们如何为现代网络重建它
读到这里的几乎每个人都玩过贪吃蛇。在等公交时用诺基亚手机玩过。在一节早已失去意义的课上用图形计算器玩过。在一个本该是电子表格的浏览器标签页里玩过。它是极少数真正跨越世代的电子游戏之一,而且它几乎不向你索取任何东西:四个方向、一条不断变长的线、一块食物。
这种表面上的简单是个陷阱,也正是我们花了这么多时间重建它的原因。贪吃蛇看起来像个新手项目。其实不是。一款手感良好的贪吃蛇——从不吞掉一次指令、从不因为一次执行正确的转向而害死你、从不卡顿、从不因为你屏幕的刷新率而变得更容易或更困难——是一件真正考验功力的工程作品。你在网上找到的大多数版本,至少会在这几点里失手两点。
这篇文章是我们所学一切的详尽版本。它涵盖贪吃蛇的由来、规则的真正含义、我们这个版本背后精确的计分数学、玩得好所需的时序表格、区分 200 分与 2000 分的策略、藏在 21×21 网格里出人意料的计算机科学,以及那些让一个玩具与一件工具产生分野的工程决策。如果你只想把游戏玩得更好,请直接跳到策略部分。如果你想真正理解它,那就从头开始。
在你的网站嵌入贪吃蛇游戏的代码:
你刚刚读完了这款游戏的全部架构:让分数在各种屏幕尺寸下都可比较的固定 21×21 网格;三种截然不同的模式(墙壁、传送门,以及带五种轮换布局的迷宫);五档速度,每一档都有自己的加速曲线和下限;带连击倍率、奖励进攻性的计分系统;七秒后过期的金色浆果;每五颗浆果就改变一次局面的升级时刻;以及那些让这个版本感觉灵敏而非仅仅能用的微妙工程决策。你看过策略表格、时序数学,以及关于尾部释放规则为何重要的诚实解释。现在到了实用的部分:把同一个引擎放到你自己的网站上,让你的访客无需离开你的页面就能畅玩。
你可以复制下面的代码并把它嵌入你的网站——放进文章、侧边栏、页脚,或任何你希望访客体验一段专注而讲究策略的游戏时光的地方。游戏完全在浏览器中运行,位于一个隔离容器内,无法读取或触碰周围的页面。没有任何游戏数据被传输、存储或记录。网格计算在本地进行,分数存在访客自己浏览器的存储里,键盘与触摸操作全程无需向服务器往返一次。关闭标签页,整个会话就此蒸发。访客所玩的一切都留在他们那里,而这正是贪吃蛇一贯的运作方式:重要的不是那张网格,而是注视着它的人内心所做的决定。
嵌入代码提供六种界面语言以匹配你的受众:英语 - 西班牙语 - 法语 - 阿拉伯语 - 中文 - 印地语。语言设置控制工具中的标签、按钮与说明,也决定游戏界面以哪种语言显示。游戏本身对世界上每一位访客都是一样的,但它以哪种语言呈现完全取决于访客的选择——在首次访问时从其浏览器自动检测,此后予以记住。对于阿拉伯语,整个版面会切换为从右到左,将界面镜像,让体验显得原生自然。
通过修改网址中的参数来更改界面语言:?lang=zh
可用语言:en - es - fr - ar - zh - hi
1- 隔离式 iFrame 代码(适合文章与页面):
如果你正在发布一篇指南、一份策略分析,或一篇关于游戏设计、压力下决策、最优玩法数学的深度文章——就像你此刻正在读的这一篇——这个方法会把功能完整的游戏直接放进你内容的正文中。隔离式 iFrame 把工具限制在框内,因此你的版面保持整洁,读者无需重新加载页面就能玩上一局。所有功能都会完全按照描述运作:三种模式(墙壁、传送门、迷宫)、五档速度(悠闲、经典、迅捷、狂热,外加一个额外档位)、带连击倍率的计分系统、金色浆果、升级时刻,以及键盘与触摸操作,全都装在你网站上一间小小的、自成一体的房间里。
<iframe data-tooliqo src="https://tools.tooliqo.co/snake-game/?lang=zh"
title="Tooliqo — snake-game"
style="width:100%;border:0;height:720px" height="720" loading="lazy" scrolling="no"
allowfullscreen allow="fullscreen; clipboard-write"></iframe>
<script src="https://tools.tooliqo.co/embed.js" async></script>
2- 灵活脚本(适合侧边栏与模板):
对于侧边栏、页脚或小工具区域,这个更轻量的嵌入方式会按需加载游戏并适配它所在的容器。这是同一个引擎、同样的三种模式、同样的五档速度、同样对六种语言的支持、同样的计分系统、同样的金色浆果、同样的升级机制;只是打包成适合那些 iFrame 可能显得笨重的位置。把它放进你的模板,游戏就会在你想要的地方、在你想要的时候出现。你的访客可以追逐高分、精通迷宫模式,或只是玩上快快一局,全程都不必离开你的网站。
<div class="tooliqo-tool" data-tool="snake-game" data-lang="zh"
data-height="720"></div> <script src="https://tools.tooliqo.co/embed.js" async></script>
说明:两种方法加载的是同一款游戏,也就是你刚刚读到其三种模式、五档速度、连击计分、金色浆果、升级时刻与六种语言的那一款。工具会尊重访客设备上的深色模式与减弱动态效果设置。没有水印,没有每日限额,不收集数据。只有游戏,做它该做的事,就在你的网站上。而如果某位访客玩了一局、败给了自己的尾巴、再试一次,并最终打破了自己的纪录,那么这个工具就完成了它被打造出来的使命。剩下的事取决于他,而这一直都是目的所在。
本指南涵盖哪些内容
- 贪吃蛇的规则,以及它们为何设计得如此精妙
- 一部完整的历史:从 1976 年的 Blockade 到 slither.io 及以后
- 我们贪吃蛇游戏的幕后:我们做了什么,以及为什么
- 完整的计分参考,含全部公式与表格
- 速度、时序与反应窗口换算表
- 三种模式:墙壁、传送门与迷宫
- 策略:如何真正把贪吃蛇玩得更好
- 贪吃蛇的数学,包括我们的棋盘为何没有完美回路
- 深入底层:如何打造一款不欺骗玩家的贪吃蛇
- 语言、无障碍,以及在任何屏幕上游玩
- 完整操作参考
- 常见问题
- 贪吃蛇术语表
贪吃蛇的规则,以及它们为何设计得如此精妙
贪吃蛇的完整规则可以用四句话说完。你控制一条由相连格子组成的线。蛇头一次前进一格,从不停下。你可以把它导向上、下、左、右,但绝不能直接向后掉进自己的脖子里。当蛇头够到一块食物,蛇就长一格,另一处会出现一块新食物;当蛇头撞到墙或撞到自己身体的任何部分,这一局就结束。
让这成为伟大设计、而不仅仅是简单设计的,是那条反馈回路。在几乎所有其他街机游戏里,玩得越好,游戏就越容易。而在贪吃蛇里,每一次成功都让下一刻更艰难,因为奖励就是障碍。你三分钟前吃掉的那颗苹果,如今成了要绕开的一堵墙。早期游戏设计中,再没有别的东西能把风险与奖励如此干净利落地压进同一个物体。
这里还有第二处更微妙的设计在起作用。由于蛇从不停下,你无法在游戏世界内部停下来思考。每一秒的犹豫,都是一格你未曾计划的前进移动。因此贪吃蛇并不是一款伪装成解谜的反应游戏;它是一款以固定节奏进行的解谜游戏,而后者要罕见和有趣得多。
最后,贪吃蛇有一条几近完美的技巧曲线。一个完完全全的新手可以存活三十秒、吃掉三颗苹果。一个有经验的玩家可以填满棋盘的三分之一。一个理解几何的玩家,原则上可以填满整个棋盘。这些结果之间的差距完全在于知识与规划,而非硬件、运气或金钱。
贪吃蛇的完整历史:从 Blockade 到现代浏览器
1976 年:Blockade,那个没人称之为贪吃蛇的始祖
这一游戏类型始于 1976 年 11 月的一台名为 Blockade 的街机,由圣迭戈的 Gremlin Industries 开发,Lane Hauck 设计,Ago Kiss 负责编程工作。它是黑白的、双人的,而"蛇"这个词在其中任何地方都没有出现。每位玩家用四个方向按钮操纵屏幕上的一个标记;标记身后会留下一道实心轨迹,先撞上墙或轨迹的一方就是输家。
据说这个点子源于 Hauck 用汇编语言对一个简单概念的试验:一个移动的物体,永远无法重新访问它去过的地方。Gremlin 在 1976 年芝加哥的美国音乐操作员协会展会上展出了它,反响极其热烈——热烈到在 Gremlin 能够大批量交付之前,好几家其他厂商就已经把自己的版本推向了市场。第一款重要的贪吃蛇游戏,在发布之前就被克隆了。
1977 至 1982 年:克隆浪潮与单人贪吃蛇的诞生
Atari 于 1977 年为 Atari 2600 主机发行了 Surround,作为该主机的首发作品之一;Sears 以 Chase 之名销售了同一款游戏。在家用电脑上,一个名为 Worm 的版本于 1978 年出现在 TRS-80 上,由 P. Trefonas 编写,通过 CLOAD 杂志发行,随后又有面向 Commodore PET 和 Apple II 的版本。
决定性的转变发生在 1982 年 12 月,Rock-Ola 发行了 Nibbler。那是这一类型变成我们所认识的这款游戏的时刻。Nibbler 是单人的,有三十二个各异的迷宫,而且至关重要的是,它有食物:蛇之所以变长,是因为你在喂它,而不是因为时间流逝。此后几乎所有贪吃蛇游戏都是 Nibbler 的后代,而非 Blockade 的。
Nibbler 还催生了街机史上最伟大的故事之一。它是第一款配备九位数计分器的街机游戏,这意味着十亿分在理论上是可能的,而 Rock-Ola 会向第一位跑到这个分数的玩家赠送一台免费机器。Tom Asaki 在爱荷华州奥图姆瓦的 Twin Galaxies 街机厅逼近了这一目标,一度达到 7.93 亿分,随后摇杆竟被实际玩坏了。1984 年 1 月,Tim McVey 用一枚硬币玩了四十多个小时,最终以 1,000,042,270 分收场:这是电子游戏史上第一个十亿分。奥图姆瓦市将 1984 年 1 月 28 日定为"Tim McVey 日",使他成为第一位拥有以自己名字命名的市政纪念日的电子游戏玩家。整段传奇后来被记录在纪录片 Man vs Snake 中。
1991 年:贪吃蛇逃进了操作系统
当微软于 1991 年发布 MS-DOS 5.0 时,它内含 QBasic,而 QBasic 附带一个名为 NIBBLES.BAS 的示例程序。对于后来成为程序员的极多数人来说,那是他们读到源代码的第一款游戏。这件事的重要性怎么强调都不为过:贪吃蛇不仅成了一款游戏,更成了那个典范式的"第一个真正的程序",是你为了向自己证明你能构建东西而去构建的那样东西。
大约在同一时期,贪吃蛇在图形计算器上蔓延开来。当时主导课堂的德州仪器机器,恰好有足够的屏幕和足够的处理器来运行它,又没有任何会让更雄心勃勃的东西值得一玩的干扰。
1997 年:诺基亚 6110,以及一款游戏有史以来最庞大的受众
1997 年 12 月,诺基亚推出了 6110,一款商务手机,屏幕仅为 84×48 像素的单色屏。诺基亚的市场团队曾请一位名叫 Taneli Armanto 的软件工程师为它做几个小游戏。他做出了三个:Memory、Logic 和 Snake。
Armanto 是在残酷的约束下进行设计的——两种色调、偏绿的 LCD 屏上的深色像素、用数字键盘代替摇杆,以及一颗毫无余裕的处理器。这些约束恰恰是这款游戏得以流传的原因。没有任何东西可以再拿掉了。据估计,最初的贪吃蛇进入了约 3.5 亿台设备;在 1997 至 2007 年间,诺基亚出货了超过 4 亿台预装该游戏的手机。在千禧年之初的一段时间里,地球上在任何一天玩贪吃蛇的人数,都超过了玩任何其他电子游戏的人数。
Armanto 设计中有一处细节值得被更多人知晓,因为我们借用了它的理念。他刻意在撞毁之前引入了一个极小的延迟——短短几毫秒,在这段时间里一个迟来的指令仍能救你一命。这是一处小小的、充满人性的设计,它悄悄承认玩家是一个拥有神经系统的人类,而非一台状态机。
Snake II 于 2000 年登上诺基亚 3310,这款手机售出了超过 1.26 亿部。它加入了大多数现代版本至今仍在照抄的三项功能:一片环绕式的场地,你从一条边出去就会从对面那条边回来;场内的迷宫障碍;以及有时限、值额外分数的奖励食物。我们的传送门模式、迷宫模式与金色浆果,都是 Snake II 的直系后代,我们乐于这样说。
2016 年起:slither.io 与浏览器时代
2016 年 3 月,一位自学成才的开发者 Steve Howse 为浏览器、iOS 和 Android 发布了 slither.io。他取用贪吃蛇的概念,将其做成大型多人对战,把蛇做成平滑弯曲而非锁死在网格上,并且颠覆了核心规则:当你的头撞上别的玩家时你会死,但你可以自由地与自己交叉。在各大 YouTube 频道的强力推广下,它登顶了应用商店,成为那个夏天访问量最高的网站之一,仅在 Android 上就突破了一亿次下载。
slither.io 证明了关于这一类型的一件要事。贪吃蛇不是一款确定的游戏;它是一种机制——一条不断变长、不得切到任何东西的线——而这种机制能够承载极其多样的设计。经典的网格版本并未消失;它只是变成了那个"典范"版本,是所有浏览器游戏网站、所有搜索引擎彩蛋、所有学编程的教程都会回归的那一个。
时间线一览
| 年份 | 作品或事件 | 平台 | 为何重要 |
|---|---|---|---|
| 1976 | Blockade(Gremlin Industries,Lane Hauck 设计) | 街机 | 创造了会致命的轨迹机制;仅限双人 |
| 1977 | Surround(也以 Chase 之名销售) | Atari 2600 | 作为首发作品把概念带进家庭 |
| 1978 | Worm,P. Trefonas 作 | TRS-80 | 第一个广泛流传的家用电脑版本 |
| 1982 | Nibbler(Rock-Ola) | 街机 | 单人、靠食物成长、32 个迷宫;真正的范本 |
| 1984 | Tim McVey 在 Nibbler 上跑出 1,000,042,270 | 街机 | 电子游戏史上第一个十亿分 |
| 1991 | NIBBLES.BAS 随 MS-DOS 5.0 中的 QBasic 附送 | 个人电脑 | 成为一代人读到的第一份游戏源代码 |
| 1997 | Snake,Taneli Armanto 作 | 诺基亚 6110 | 约 3.5 亿台设备;开启了手机游戏 |
| 2000 | Snake II | 诺基亚 3310 | 加入了环绕边界、迷宫与奖励食物 |
| 2016 | slither.io,Steve Howse 作 | 浏览器、iOS、Android | 大型多人对战的再创造;全球现象级 |
| 今天 | 像这款一样的浏览器原生版本 | 任何设备 | 无需安装、无需账号、即时游玩、完整无障碍 |
我们贪吃蛇游戏的幕后:我们做了什么,以及为什么
我们的版本从零开始,构建成一个自成一体的单一文件,没有外部库、没有网络字体、没有网络请求。这个约束是刻意的。嵌入在文章内部的游戏必须瞬间加载,绝不能拖慢承载它的页面,也绝不能因为某个第三方服务器过得不顺就崩掉。
在视觉上,我们走了一条大多数贪吃蛇游戏不会走的方向。这一类型的默认外观是黑底霓虹绿——一个容易照搬、却难以做得有深度的街机陈词滥调。我们转而构建了一个"生态缸":一片温暖沙色的场地,装在一层深孔雀绿的外壳里,配上一条身躯逐渐收细的翡翠色蛇,它有真正的头、会跟随移动方向的双眼,以及时不时颤动的舌头。食物是一颗带梗、带高光的浆果,而非一个方块。
然而,最大的视觉决策不是颜色,而是移动。在大多数贪吃蛇实现里,蛇会从一格瞬移到另一格,因为渲染器画的正是游戏状态,而游戏状态是一串网格坐标。我们的版本则做了插值:在一次逻辑移动与下一次之间,每一节身体都从它所在之处平滑滑向它将去之处。游戏逻辑仍是严格的网格——这对公平性很重要——但呈现是连续的。这就是原型与成品之间的区别,而它大概只花了三十行代码。
功能概览
| 领域 | 细节 |
|---|---|
| 棋盘 | 在任何屏幕尺寸下都固定为 21 × 21(441 格),让分数保持可比 |
| 模式 | 墙壁、传送门、迷宫(五种轮换的迷宫布局) |
| 速度 | 悠闲、经典、迅捷、狂热;每一档都有自己的加速曲线与下限 |
| 计分 | 等级奖励、最高五倍的连击倍率、值三倍的金色浆果 |
| 纪录 | 为每一种模式与速度的组合分别保存最高分 |
| 统计 | 已玩局数、已吃浆果数、最长的蛇、总游玩时间 |
| 操作 | 方向键、WASD、AZERTY 键位、屏上方向盘与滑动手势 |
| 显示 | 浅色与深色两种主题,真正的全屏,在宽屏上采用双栏布局 |
| 语言 | 英语、法语、西班牙语、中文、印地语与支持从右到左的阿拉伯语 |
| 音频 | 在浏览器中生成的合成音,默认静音,移动端配有触觉反馈 |
| 无障碍 | 可用键盘操作、面向屏幕阅读器的播报、支持减弱动态效果 |
为什么网格从不改变大小
这是我们争论最多的设计决策,因此值得解释。许多浏览器贪吃蛇游戏会让网格随窗口缩放:更大的屏幕就得到更多格子。这看起来很慷慨。而它实际上并不公平,因为这意味着手机上的 500 分与电脑上的 500 分度量的是不同的游戏。更大的棋盘更容易——腾挪空间更多,在你自己的尾巴变成问题之前的跑道也更长。
我们把网格固定为 21×21,转而缩放格子的大小。在手机上,每一格可能是十六像素;在大显示器上全屏时,每一格可以接近五十。棋盘会占满可用空间,但游戏在任何地方都相同。你的个人纪录在你拥有的每一台设备上都意味着同一件事。
选 21 而非 20 同样是刻意的:奇数的行与列会带来一个真正的中心格,使起始位置对称。而正如我们稍后会看到的,这还有一个相当有趣的数学后果。
完整的计分参考
计分系统中的一切都使用整数运算,这意味着每一个分数都精确可复现,也没有任何浮点意外。以下是整个系统,全部写明。
核心方程
| 量 | 方程 | 说明 |
|---|---|---|
| 等级 | 等级 = 1 + ⌊浆果数 ÷ 5⌋ | 浆果自本局开始起计 |
| 浆果基础值 | 基础 = 10 + 2 × (等级 − 1) | 每级增加 2 分,无上限 |
| 连击倍率 | 倍率 = min(5, 1 + ⌊连击 ÷ 3⌋) | 若两颗浆果间隔超过 5 秒,连击清零 |
| 所得分数 | 所得 = 基础 × 倍率 × 金色 | 金色浆果为 3,否则为 1 |
| 移动间隔 | 步长 = max(下限, 起始 − (等级 − 1) × 递减) | 两次逻辑移动之间的毫秒数 |
| 蛇的速度 | 格/秒 = 1000 ÷ 步长 | 直接由移动间隔换算 |
| 穿越棋盘用时 | 秒 = 21 × 步长 ÷ 1000 | 横穿整片棋盘宽度所需的时间 |
| 反应距离 | 格 = 反应时间 ÷ 步长 | 你反应时蛇前进了多少 |
| 蛇的长度 | 长度 = 3 + 浆果数 | 蛇总是以三格开始 |
常量一览
| 常量 | 值 | 作用 |
|---|---|---|
| 网格大小 | 21 × 21 = 441 格 | 完整的游戏场地 |
| 起始长度 | 3 格 | 头部加两节身体 |
| 基础分 | 10 | 1 级无连击时一颗浆果的价值 |
| 等级奖励 | 每级 +2 分 | 与倍率复合叠加 |
| 每级浆果数 | 5 | 每 5 颗浆果,等级升 1 |
| 连击窗口 | 5000 毫秒 | 保持连击所允许的两颗浆果间最大间隔 |
| 连击步进 | 3 颗浆果 | 每连吃 3 颗,倍率升 1 |
| 连击上限 | ×5 | 倍率永不超过五 |
| 金色浆果加成 | ×3 | 叠加在连击倍率之上 |
| 金色浆果寿命 | 7000 毫秒 | 随后淡出并消失 |
| 金色浆果频率 | 每 4 颗浆果 | 仅当棋盘上尚无金色浆果时 |
等级进程
| 等级 | 已吃浆果 | 蛇长 | 浆果基础值 | ×5 连击时的价值 | ×5 时的金色浆果 |
|---|---|---|---|---|---|
| 1 | 0–4 | 3–7 | 10 | 50 | 150 |
| 2 | 5–9 | 8–12 | 12 | 60 | 180 |
| 3 | 10–14 | 13–17 | 14 | 70 | 210 |
| 4 | 15–19 | 18–22 | 16 | 80 | 240 |
| 5 | 20–24 | 23–27 | 18 | 90 | 270 |
| 6 | 25–29 | 28–32 | 20 | 100 | 300 |
| 7 | 30–34 | 33–37 | 22 | 110 | 330 |
| 8 | 35–39 | 38–42 | 24 | 120 | 360 |
| 9 | 40–44 | 43–47 | 26 | 130 | 390 |
| 10 | 45–49 | 48–52 | 28 | 140 | 420 |
| 15 | 70–74 | 73–77 | 38 | 190 | 570 |
| 20 | 95–99 | 98–102 | 48 | 240 | 720 |
| 30 | 145–149 | 148–152 | 68 | 340 | 1020 |
连击倍率
连击是大多数玩家忽视的那部分分数,而它比其余所有部分加起来还值钱。每一颗在前一颗之后五秒内吃下的浆果都会延续你的连击。连击中每第三颗浆果都会把倍率提高一,直到五。
| 当前连击中的浆果数 | 倍率 | 1 级时浆果价值 | 10 级时浆果价值 |
|---|---|---|---|
| 第 1 至 3 颗 | ×1 | 10 | 28 |
| 第 4 至 6 颗 | ×2 | 20 | 56 |
| 第 7 至 9 颗 | ×3 | 30 | 84 |
| 第 10 至 12 颗 | ×4 | 40 | 112 |
| 第 13 颗及以后 | ×5 | 50 | 140 |
完整的每颗浆果得分矩阵
| 等级 | ×1 | ×2 | ×3 | ×4 | ×5 |
|---|---|---|---|---|---|
| 1 | 10 | 20 | 30 | 40 | 50 |
| 2 | 12 | 24 | 36 | 48 | 60 |
| 3 | 14 | 28 | 42 | 56 | 70 |
| 4 | 16 | 32 | 48 | 64 | 80 |
| 5 | 18 | 36 | 54 | 72 | 90 |
| 6 | 20 | 40 | 60 | 80 | 100 |
| 7 | 22 | 44 | 66 | 88 | 110 |
| 8 | 24 | 48 | 72 | 96 | 120 |
| 9 | 26 | 52 | 78 | 104 | 130 |
| 10 | 28 | 56 | 84 | 112 | 140 |
一个来自真实对局的算例
在测试完成的游戏时,我们写了一个自动玩家,它直接从渲染出的画面中读取浆果的位置并朝它前进。在一局记录里,它吃了五颗浆果,最终得分恰好是 70,长度为 8,等级为 2。这个数字值得驻足,因为它在一行之内展示了整个系统。
- 浆果 1:1 级,连击第 1 位,倍率 ×1 → 10 分(累计 10)
- 浆果 2:1 级,连击第 2 位,倍率 ×1 → 10 分(累计 20)
- 浆果 3:1 级,连击第 3 位,倍率 ×1 → 10 分(累计 30)
- 浆果 4:1 级,连击第 4 位,倍率 ×2 → 20 分(累计 50)
- 浆果 5:1 级,连击第 5 位,倍率 ×2 → 20 分(累计 70),随后等级升到 2
注意第四颗浆果的价值是第一颗的两倍,而棋盘上什么都没变。这就是进攻性玩法的全部策略论据:犹豫不仅浪费时间,还会主动把你的收入清零。
分数标杆与理论最大值
下表显示的是:如果你不建立任何连击,一定数量的浆果值多少分——把它们当作下限,而非目标。一个在大半局里都保持五倍倍率的玩家,会达到这些数字的约五倍。
| 已吃浆果 | 蛇长 | 达到等级 | 无连击得分 | 持续 ×5 得分 |
|---|---|---|---|---|
| 10 | 13 | 3 | 110 | 550 |
| 25 | 28 | 6 | 350 | 1750 |
| 50 | 53 | 11 | 950 | 4750 |
| 100 | 103 | 21 | 2900 | 14500 |
| 200 | 203 | 41 | 9800 | 49000 |
| 438(完美一局) | 441(棋盘填满) | 88 | 42312 | 211560 |
最后这一行就是上限。棋盘有 441 格,蛇以 3 格起始,所以完美的一局要吃 438 颗浆果,并以蛇占满每一格告终。到那一刻,等级是 88,每颗浆果在倍率之前值 184 分。没有人做到过。如果你哪天做到了,你纪录面板上的"最长"数字会显示 441,而再也没有可以移动的地方了。
速度、时序与反应窗口
每一个难度设置都由三个数字定义:1 级时两次移动之间的间隔、这个间隔每级缩短多少毫秒,以及它永不低于的下限。
| 设置 | 起始间隔 | 每级缩短 | 最快间隔 | 达到最高速的等级 |
|---|---|---|---|---|
| 悠闲 | 170 毫秒 | 6 毫秒 | 110 毫秒 | 11 |
| 经典 | 130 毫秒 | 6 毫秒 | 80 毫秒 | 10 |
| 迅捷 | 100 毫秒 | 5 毫秒 | 60 毫秒 | 9 |
| 狂热 | 78 毫秒 | 4 毫秒 | 45 毫秒 | 10 |
各等级的移动间隔
| 等级 | 悠闲 | 经典 | 迅捷 | 狂热 |
|---|---|---|---|---|
| 1 | 170 | 130 | 100 | 78 |
| 2 | 164 | 124 | 95 | 74 |
| 3 | 158 | 118 | 90 | 70 |
| 4 | 152 | 112 | 85 | 66 |
| 5 | 146 | 106 | 80 | 62 |
| 6 | 140 | 100 | 75 | 58 |
| 7 | 134 | 94 | 70 | 54 |
| 8 | 128 | 88 | 65 | 50 |
| 9 | 122 | 82 | 60 | 46 |
| 10 及以后 | 116 然后 110 | 80 | 60 | 45 |
把毫秒换算成你能感受到的东西
像"每次移动 80 毫秒"这样的数字,在你把它换算成格每秒和穿越棋盘的用时之前,毫无意义。这张表做了这件事,然后又做了更有用的一件事:它显示在一次典型的人类反应期间,蛇前进了多少。成年人的简单视觉反应时间通常在 200 到 250 毫秒左右。我们采用 250 毫秒作为保守数字。
| 设置与等级 | 间隔 | 格每秒 | 穿越棋盘用时(秒) | 你反应时移动的格数 |
|---|---|---|---|---|
| 悠闲,1 级 | 170 毫秒 | 5.9 | 3.57 | 1.5 |
| 悠闲,最高速 | 110 毫秒 | 9.1 | 2.31 | 2.3 |
| 经典,1 级 | 130 毫秒 | 7.7 | 2.73 | 1.9 |
| 经典,最高速 | 80 毫秒 | 12.5 | 1.68 | 3.1 |
| 迅捷,1 级 | 100 毫秒 | 10.0 | 2.10 | 2.5 |
| 迅捷,最高速 | 60 毫秒 | 16.7 | 1.26 | 4.2 |
| 狂热,1 级 | 78 毫秒 | 12.8 | 1.64 | 3.2 |
| 狂热,最高速 | 45 毫秒 | 22.2 | 0.95 | 5.6 |
请仔细读最后一列,因为它包含了整篇文章最重要的想法。在狂热的最高速下,等到你看见了一个问题并动了手指,蛇已经前进了五格多——棋盘宽度的四分之一。你无法靠反应从一条快速的蛇里脱身。你只能靠规划从中脱身。每一个好玩家实际上都在提前两三秒游玩,而可见的当下只是用来确认计划仍然成立。
金色浆果窗口
一颗金色浆果正好活七秒。你能否够到它,完全取决于你当前的移动间隔。在 21×21 的棋盘上,最坏情况是从一角到另一角的行程,即 40 格的曼哈顿距离。
| 设置与等级 | 间隔 | 7 秒内可用移动次数 | 最坏情况 40 格——够得到吗? |
|---|---|---|---|
| 悠闲,1 级 | 170 毫秒 | 41 | 勉强,需要一条完全畅通的路 |
| 悠闲,最高速 | 110 毫秒 | 63 | 从容 |
| 经典,1 级 | 130 毫秒 | 53 | 可以,还留有绕行余地 |
| 经典,最高速 | 80 毫秒 | 87 | 轻松 |
| 迅捷,1 级 | 100 毫秒 | 70 | 轻松 |
| 狂热,最高速 | 45 毫秒 | 155 | 几乎总能 |
这引出了一个相当反直觉的结论:金色浆果在最慢的设置下最难拿到。悠闲让你每次移动有更多思考时间,但在固定的七秒计时里给你的移动次数更少。如果你追逐的是奖励分而非生存,那么经典或迅捷是比悠闲更好的猎场。
以移动次数、而非秒数计的连击窗口
同样的逻辑也适用于五秒的连击窗口,而且效应更强。在 21×21 的棋盘上,任取两格之间的平均曼哈顿距离几乎正好是 14 格,所以这就是从一颗浆果到下一颗的典型行程。
| 设置与等级 | 间隔 | 5 秒窗口内的移动次数 | 相对 14 格平均行程的余量 |
|---|---|---|---|
| 悠闲,1 级 | 170 毫秒 | 29 | 约 2.1 倍 |
| 经典,1 级 | 130 毫秒 | 38 | 约 2.7 倍 |
| 迅捷,1 级 | 100 毫秒 | 50 | 约 3.6 倍 |
| 狂热,1 级 | 78 毫秒 | 64 | 约 4.6 倍 |
| 狂热,最高速 | 45 毫秒 | 111 | 约 7.9 倍 |
换句话说,快速的设置不仅更冒险——它们也是最高分所在之处,因为它们让持续的五倍倍率变得现实。悠闲是用来学习的设置。它不是用来创纪录的设置。
三种模式
墙壁
1997 年的原始规则集。边界是实心的;碰它就结束这一局。这是这款游戏最纯粹的版本,如果你想与经典作对比,你的分数就应当在这上面度量。墙壁模式惩罚漂移:由于边缘没有逃生口,周界成了棋盘上最危险的地方,而非最安全的。
传送门
承袭自诺基亚 3310 上的 Snake II。从任何一条边出去,你就会从对面那条边回来。这看似让游戏更容易,而在最初的三十秒里,确实如此。随后它会让游戏难上许多,原因是大多数玩家从不曾说清的:在墙壁模式里,你自己的身体和边界构成一道相连的屏障,因此棋盘有一个简单的内部和外部。在传送门模式里,棋盘在拓扑上是一个环面,你的身体可以绕着它缠一圈,而你把自己困住的那个区域要不明显得多。漫长的传送门对局需要真正的空间想象力。
传送门模式也是理论上最高分可能出现的地方,因为边缘不再是危险,而且每颗浆果都可经由两条路线、而非一条到达——有时绕过去的那条路比直行的那条更短,这对保持连击存活至关重要。
迷宫
五种石块布局会随你升级而轮换,排布每五颗浆果就在你脚下变一次。这些布局是对称且确定的——同一等级总是产生同样的墙——因此它们可以被学习,而不只是被承受。有两条规则保护你:石块绝不会被放在棋盘边缘上,而蛇出生的那一中心行始终保持畅通。
迷宫模式改变了受考验的核心技巧。墙壁与传送门关乎管理你自己身体所消耗的空间。迷宫关乎在时间压力下寻找路径,这远比诺基亚在 1997 年所做的,更接近 Nibbler 在 1982 年所做的。
| 模式 | 边缘 | 障碍 | 最适合 | 主要风险 |
|---|---|---|---|---|
| 墙壁 | 致命 | 无 | 学习并公平地对比分数 | 被卡在边界上 |
| 传送门 | 环绕 | 无 | 漫长对局与高分 | 弄丢自己所在区域的头绪 |
| 迷宫 | 致命 | 五种轮换布局 | 路径规划与多样性 | 棋盘在对局中途改变形状 |
策略:如何真正把贪吃蛇玩得更好
网上大多数贪吃蛇建议归结起来就是"小心点"和"别撞上"。这里有更有用的东西。它们大致按照在你成长的哪个阶段开始变得重要来排序。
1. 别再追着浆果跑
新手会把蛇直直地导向食物。这在蛇约十格长之前有效,然后就开始害死你,因为一条直接路线为当前这颗浆果作了优化,却忽略了你的尾巴接下来会在哪里。中级玩家会问一个不同的问题:不是"我怎么到那里?",而是"等我到了那里,棋盘会是什么样?"。
这条规则的实用版本很简单。在你投入一条路线之前,先确认存在一条能从浆果所在位置出去的路。在死胡同里吃掉一颗浆果,正是好对局收场的方式。
2. 让你的身体贴着边缘
贪吃蛇里的空间不可互换。散落成一个个口袋的一百个空格一文不值;而位于单一开阔区域里的一百个空格,就是一整局。让你的空闲空间保持成一整块的办法,是让你的身体沿着周界、把中心留空,而不是反过来。一条绕着棋盘外围盘起来的蛇,会留下一个大大的洞。一条在中心游荡的蛇,会把棋盘切成碎片。
3. 学会走"之"字
经典的填充空间模式——有时被称为牛耕式转行,源自希腊语"如牛耕地"——是指走完一整行的长度,下移一行,折回来,再重复。它看起来慢,也确实慢,但它保证你能扫过一个区域里的每一格,且永不切断自己的去路。当一颗浆果出现在远处而你的蛇很长时,走"之"字朝它去,几乎总是比走直线更安全。
4. 跟着你自己的尾巴
如果你实在不知道该怎么办,就去追你自己的尾巴。由于每当蛇头移动,尾巴就退开一格,一条跟着自己尾巴的蛇可以无限存活下去。这是应急招法:当棋盘看起来很糟、你又看不到计划时,排到你尾巴后面,在一颗新浆果出现在更好位置之前争取时间。
5. 理解尾部释放规则
这里有一条大多数实现都处理不当、因而大多数玩家从不学会利用的规则。当蛇移动而没有进食时,尾巴会在蛇头进入新格的同一瞬间离开它的格子。这意味着你尾巴末端当前所占的那一格可以安全进入:等你到那里时,它将是空的。
我们的版本正确地实现了这一点。其结果是,你可以完成一些看似不可能的极紧转向,紧贴自己身后一格跟着自己的身体走。但请注意那个例外:如果你在同一次移动中吃了一颗浆果,蛇就会变长,尾巴不会释放。进食时进入你尾巴的那一格是致命的。有经验的玩家把它内化为"紧转向是安全的,除非路上有食物"。
6. 玩连击,而非玩浆果
鉴于上面的表格,算术是残酷的。一个每八秒吃一颗浆果的悠闲谨慎玩家,会永远以 ×1 计分。而一个每三秒吃一颗的进攻型玩家,在十三颗浆果内就到 ×5,并从那时起每颗浆果多赚五倍。进攻型玩家会更早死。但他也会以数倍之高的分数收场。
实用法则:一颗浆果一出现,就开始朝它移动。别先兜完你当前那一圈。也别等着看它会去哪里:它哪儿也不去。
7. 顺路带走金色浆果,别为它绕道
一颗金色浆果值三颗普通浆果,这很棒,但它出现在一个随机格里,并在七秒后过期。如果它大致在你的路上,就带走它。如果去拿它会打断你在普通浆果上的连击,就放掉它。三倍的一颗浆果,比不上你会失去的那个五倍倍率。
8. 管理好升级时刻
每五颗浆果,游戏就会加速——而在迷宫模式里,墙也会改变。这一刻是任何对局中最危险的时刻。如果你正接近你的第五、第十或第十五颗浆果,务必让自己抵达时前方有开阔空间,而不是身处一个逼仄的角落。
常见错误及其纠正
| 错误 | 它为何害死你 | 纠正 |
|---|---|---|
| 直线冲向每一颗浆果 | 让你的身体散落在棋盘中心 | 沿周界规划路线,只为收取才进入中心 |
| 在一次移动间隔内转两次向 | 第二次转向才是实际发生的;第一次被丢弃 | 每次移动一个果断指令,而非一连串敲击 |
| 蛇变长时惊慌 | 惊慌产生短视决策,把棋盘弄碎 | 回退到跟着自己尾巴,直到计划浮现 |
| 在角落里吃浆果 | 你抵达时只有一个出口,而你的新身体节堵住了它 | 沿着墙、而非垂直于墙地接近角落 |
| 为拿高分而玩悠闲 | 每秒移动更少,意味着连击窗口内的移动更少 | 在悠闲上学习,在经典或迅捷上拿分 |
| 忽视升级时刻 | 你正处于机动之中,速度却变了 | 数你的浆果;在开阔空间里抵达每第五颗 |
贪吃蛇的数学
贪吃蛇看起来像一款反应游戏,行为却像一道图论问题。这一节是可选的,但它包含一个关于我们这块具体棋盘的事实,我们在任何地方都没见过它被讨论,而它会改变一局完美对局应当怎么打。
把贪吃蛇看作网格图
把棋盘建模为一张图:每一格是一个顶点,若两格正交相邻,则两个顶点相连。蛇是穿过这张图的一条路径,每回合前进一步,不能掉头,且每当落在食物上就增长一个顶点。几乎所有关于贪吃蛇的有趣问题,都会变成关于网格图中路径与回路的问题。
为什么"只管跟着一条回路走"是标准的完美策略
保证一条蛇永不死亡的最著名办法,是找到一条哈密顿回路——一条恰好访问每一格一次的闭合环——然后就永远跟着它走。由于这条环覆盖每一格,所有食物最终都会落到你前方;由于它是单一的闭合环,而蛇比这条环短,你永远无法撞到自己。这是完美的,也是慢得让人受不了的,但它总能赢。
为什么我们的 21×21 棋盘没有这样一条回路
这就是有趣的部分。把棋盘像棋盘格那样着色。每一次移动都把蛇从一个浅色格带到一个深色格,或反过来,所以任何闭合环都必须交替颜色——这意味着,只有当浅色格的数目等于深色格的数目时,哈密顿回路才可能存在。
在 21×21 的棋盘上,共有 441 格:一种颜色 221 格,另一种 220 格。它们并不相等,也不可能相等,因为 441 是奇数。因此,在我们的棋盘上根本不存在哈密顿回路。经典的"安全环"策略在这里在数学上是不可能的。
存在的是一条哈密顿路径:一条穿过全部 441 格的开放路线。所以完美的一局仍然可能,但它不可能是一条不动脑的环。任何试图填满棋盘的玩家或算法,要么必须在一块 20×21、共 420 格的子区域内作业(它是偶数,确实容许一条回路),并单独处理剩下那一行;要么规划一条开放路径,并在结尾重新定位。这不是我们设计上的意外;这是任何奇数乘奇数尺寸的贪吃蛇棋盘的性质,包括你在网上会找到的许多棋盘。
| 棋盘 | 总格数 | 颜色分布 | 哈密顿回路可能吗? |
|---|---|---|---|
| 20 × 20 | 400 | 200 / 200 | 可能 |
| 21 × 21(这款游戏) | 441 | 221 / 220 | 不——只有开放路径 |
| 20 × 21 子棋盘 | 420 | 210 / 210 | 可能 |
| 任何奇 × 奇棋盘 | 奇数 | 相差一 | 不 |
正式地说,贪吃蛇有多难?
难到足以让计算机科学家为它发表论文。2016 年,Marzio De Biasi 与 Tim Ophelders 在"趣味算法国际会议"上提交了一篇题为《The Complexity of Snake》的论文,后来在 Theoretical Computer Science 上作了扩展。他们证明,判定一条蛇能否在一张填满的网格图上收取全部食物是 NP 困难的,而在一般网格图上,这个问题是 PSPACE 完全的——就和那个更简单的问题一样,即在棋盘上根本没有食物的情况下,判定一条蛇能否从一种构形转移到另一种构形。
简单地说:没有已知的高效算法能把贪吃蛇玩到最优,而且有充分理由相信没有这样的算法。当你觉得某个局面无解时,你也许在客观上是对的。这个问题还吸引了机器人研究者,因为一条不得撞到自己身体的蛇,是蛇形铰接机器人运动规划的一个合理模型。
关于棋盘的一些数字
| 量 | 值 |
|---|---|
| 总格数 | 441 |
| 周界格数 | 80 |
| 内部格数 | 361(一块 19 × 19 的区域) |
| 一局开始时的空格数 | 437(441 减去 3 节蛇身与 1 颗浆果) |
| 两格间的最大曼哈顿距离 | 40 |
| 任取两格间的平均曼哈顿距离 | 约 14.0 |
| 蛇的最大长度 | 441 |
| 完美一局中的浆果数 | 438 |
| 完美一局中的最终等级 | 88 |
深入底层:打造一款不欺骗玩家的贪吃蛇
这一节是给开发者的,也是给任何好奇为什么有些浏览器贪吃蛇手感良好、有些却显得廉价的人的。下面每一点都是一个我们要么修复、要么在设计上刻意规避的问题。
用固定时间步长,而非 setInterval
运行一款贪吃蛇的幼稚做法,是用一个定时器来调用移动函数。它看起来有效。而它错在三处:浏览器定时器会漂移,在后台标签页里会被节流,而且这个间隔从不与屏幕刷新对齐,于是动画会卡顿。
正确的做法是一个固定时间步长的累加器。在每一动画帧,测量流逝了多少真实时间,把它加进一个累加器,然后执行这段时间所包含的那么多次逻辑移动。游戏逻辑以精确、相同的增量推进,无论帧率如何;只有绘制跟随屏幕。还有两道防护很重要:给流逝时间设上界,好让后台标签页不会在切回来时把蛇加速撞墙;再给每帧的追赶移动次数设上限,好让一台慢设备不会失控狂奔。
| 方式 | 在 144 Hz 显示器上的表现 | 在后台标签页里的表现 | 公平性 |
|---|---|---|---|
| setInterval | 卡顿;移动时序偏离屏幕时序 | 以不可预测的方式被节流 | 速度因设备而异 |
| 每帧一次移动 | 以每秒 144 次移动运行 | 完全停止 | 完全不公平 |
| 固定时间步长累加器 | 流畅,且移动节奏精确无误 | 受上界约束,随后干净地恢复 | 在任何地方都相同 |
输入队列,以及那个害死每一次初次尝试的问题
几乎每一款自制的贪吃蛇都含有同一个致命问题。玩家正向右移动,飞快地按上、再按左,于是这两个输入都在下一次移动之前被应用——蛇便掉头钻进自己的脖子,毫无可见缘由地死去。这是"这游戏坏了"这类抱怨最常见的来源,而它并不是玩家的错。
纠正之道是把输入排进队列,而不是立即应用它们。每一次逻辑移动至多从队列里取用一个方向,并拒绝任何与当前方向恰好相反的方向。玩家可以稍微提前缓冲一个转向——这感觉很灵敏——但永远无法意外地把蛇对折。
精确实现的碰撞
正如策略一节所述,在任何不使蛇变长的移动中,尾巴都会释放它的格子。正确的实现会把蛇头的目标与除最后一节之外的所有身体节比较,除非这是一次进食移动,那时每一节都要计入。任一方向弄错,都会产生一款要么显得不公平地苛刻、要么可疑地宽容的游戏。我们在发布前用自动化测试验证了这一行为。
在离散网格上作插值渲染
逻辑在整数格坐标上运行;绘制在分数位置上运行。在两次移动之间,每一节都被画在它曾在之处与它将去之处的一个混合位置上,权重由我们在当前间隔中推进了多少决定。结果是一条滑动而非跳跃的蛇,而对底层网格的公平性毫无妥协。
有一处微妙之处:在传送门模式里,一节身体可能从棋盘的一条边缠绕到另一条,而对这一过渡作插值会在屏幕上画出一道笔直的拖影。纠正之道是检测任何长于一格的跳跃,此时对齐而非混合,并在该处断开所绘身体的描画。
不靠拒绝采样来放置食物
常见做法是随机挑一格,检查它是否被占用,若被占用就重试。这在开始时运作良好,到后期却变得病态:当蛇几乎填满棋盘时,这个循环可能空转数百次,而如果棋盘被完全填满,它永远不会结束。我们会构建实际空闲格子的列表,并从中均匀地挑选。这在最坏情况下既更快,又可证明会终止。
不破坏它所寄居的页面
一款嵌入的游戏对它的宿主负有义务。我们的游戏绝不注册一个会从页面偷走方向键的全局键盘处理器:只有在你确实与游戏交互期间,输入才被捕获,而一旦你点到别处,它就被释放,并在此过程中暂停。当标签页被隐藏、以及当它因滚动而离开视野时,它都会暂停。它所有的样式都被隔离,好让它不会泄漏进周围的文章,而周围网站的任何东西也无法泄漏进来。
我们在测试中发现的两个真实问题
我们会诚实地说说它们,因为像这样的文章通常会假装开发是毫无摩擦地进行的。在最终测试中,一个自动化浏览器发现了两个手动游玩漏掉的问题。
第一个是变量名冲突:一个新加的、指向棋盘元素的引用,遮蔽了同名的渲染循环函数,于是悄无声息地令整个游戏失效。它抛出一条控制台错误,然后什么都不动。这个教训并不光彩,却是普适的:给东西起名要小心,并且要运行你发布出去的那份东西。
第二个更微妙,也更有教益。为了给棋盘定尺寸,我们去测量的,正是我们在设定其宽度的那个元素,这制造出一条反馈回路:棋盘可以收缩,却永远无法再变大。纠正是结构性的:一个元素测量可用空间,且从不被设定尺寸;它内部一个单独的元素才是棋盘,并以像素来定尺寸。如果你从这篇文章里只记住一条架构思想,那就让它是这一条:永远不要去测量一个你自己在控制其尺寸的盒子。
语言、无障碍,以及在任何屏幕上游玩
游戏以六种语言提供,英语为源语言。它会按以下顺序检查来自动检测正确的那一种:页面地址中的一个显式语言参数、游戏元素本身上的一个属性、页面所声明的语言、页面社交元数据中的地区设置、内容的语言声明,以及最后浏览器自己的偏好。如果这些都没能给出一种受支持的语言,它就退回到英语。你随时可以用角落里的选择器覆盖这个结果。
| 语言 | 代码 | 该语言中的标题 | 文字方向 |
|---|---|---|---|
| 英语 | en | Snake | 从左到右 |
| 法语 | fr | Snake | 从左到右 |
| 西班牙语 | es | Snake | 从左到右 |
| 中文 | zh | 贪吃蛇 | 从左到右 |
| 印地语 | hi | स्नेक | 从左到右 |
| 阿拉伯语 | ar | لعبة الثعبان | 从右到左 |
阿拉伯语会把整个界面切换为从右到左,但有一个刻意的例外:方向盘保持它的物理排布,因为在游戏手柄上,"左"就意味着屏幕上的左,无论你用哪种语言阅读。
在无障碍方面,游戏完全可用键盘操作,每一个操作都是一个带恰当标签的真正按钮,而分数变化与一局结束都会通过一个活动区域向屏幕阅读器播报。如果你的系统被设为减弱动态效果,那么装饰性动画、撞毁抖动与脉动效果都会被关闭,而游戏本身保持完好。
在响应式方面,版面会适配游戏的宽度,而非浏览器的宽度——这很重要,因为一款嵌入在狭窄文章栏里的游戏,即便在一台大显示器上,也应当表现得像一款狭窄的游戏。在横向屏幕上全屏时,它会切换为双栏布局,棋盘在一侧、操作在另一侧,而棋盘可以增大到超过一千像素宽。
完整操作参考
| 输入 | 动作 | 说明 |
|---|---|---|
| 方向键 | 转向 | 标准布局 |
| W、A、S、D | 转向 | 用于 QWERTY 键盘 |
| Z、Q、S、D | 转向 | 用于 AZERTY 键盘 |
| 空格 | 暂停或继续 | 也可从标题画面开始一局 |
| R | 重开 | 立即开始新的一局 |
| F | 全屏 | 开启与关闭 |
| M | 静音 | 声音默认为静音 |
| Enter | 确认 | 激活当前卡片的按钮 |
| Esc | 退出全屏 | 浏览器的标准行为 |
| 在棋盘上滑动 | 转向 | 连续滑动无需抬指即可识别 |
| 轻触棋盘 | 开始或继续 | 就像往街机里投一枚硬币 |
| 屏上方向盘 | 转向 | 在触摸设备上自动出现 |
常见问题
谁发明了贪吃蛇游戏?
没有任何一个人独自发明,而这正是这个问题不断得到不同答案的原因。这套机制由 Lane Hauck 在 Gremlin Industries 为 1976 年的街机 Blockade 创造。我们如今称为贪吃蛇的那种单人、吃食物的形式,由 Rock-Ola 的 Nibbler 在 1982 年确立。让它闻名全球的那个版本,由 Taneli Armanto 在诺基亚为 1997 年的 6110 编写。这三个答案都站得住脚;它们是对不同问题的回答。
这款游戏里可能的最高分是多少?
211560,通过吃掉全部 438 颗可用浆果、同时自始至终保持五倍倍率、并无视金色浆果达成。实际上,金色浆果会把一局理论上完美的对局推得更高。一局非常出色的人类对局在经典模式下通常落在 2000 到 10000 之间的某处。
游戏会永远加速吗?
不会。每一种难度都有下限。经典模式在 10 级达到每次移动 80 毫秒的最小值,此后不再更快;狂热模式的最小值是 45 毫秒。此后到来的一切之所以更难,纯粹是因为你的蛇更长了,而这是诚实的那种难度。
更长的蛇值更多分吗?
间接地值。长度本身不计分,但长度跟随已吃浆果,已吃浆果决定你的等级,而等级会把此后每颗浆果的基础值抬高两分。至于倍率,则与长度毫无关系:它纯粹关乎你吃得有多快。
为什么我在悠闲上的分数比在经典上低?
因为连击窗口是以秒、而非以移动次数来度量的。更慢的蛇在五秒内覆盖的地面更少,所以连击链断得更频繁。悠闲更容易存活,也更难拿分。这几乎让所有人都感到意外。
我的分数与统计会被发送到某处吗?
不会。一切——各模式的最高分、已玩局数、已吃浆果、最长的蛇、总时间——都存储在你自己的浏览器本地。没有账号、没有服务器、没有排行榜,也没有追踪。清除你浏览器的数据会清掉你的纪录,而纪录面板上的重置按钮也刻意做同样的事。
我能在手机上用键盘玩,或在笔记本上用触摸玩吗?
两者都能。方向盘会在触摸设备上自动出现,但只要连着一个键盘,键盘就保持有效,而带触摸屏的笔记本可以在棋盘上滑动。
为什么我点击页面别处时游戏会暂停?
这是刻意的。一款在你已转去阅读文章之后仍继续消耗你方向键的嵌入游戏,是一种滋扰。当你与游戏之外的东西交互时,游戏会释放键盘并暂停,好让你不会回到一条死掉的蛇跟前。
变强最快的办法是什么?
在墙壁模式下用经典速度玩二十局,并在每一局里强迫自己沿周界、而非穿中心地规划路线。这会感觉更慢,你最初的分数也会下降。到第十局时,它们会比之前更高,因为你已经不再把棋盘弄碎了。
术语表
| 术语 | 含义 |
|---|---|
| 刻(Tick) | 蛇的一次逻辑移动,向前一格 |
| 移动间隔 | 两刻之间以毫秒计的时间 |
| 固定时间步长 | 以精确、相同的时间增量运行游戏逻辑,无论帧率如何 |
| 插值 | 把一节身体画在它上一格与当前格之间的中途处,以获得流畅移动 |
| 输入队列 | 一小段待处理转向变更的缓冲,每刻取用一个 |
| 尾部释放 | 那条规则:在任何不是进食的移动中,最后一节都离开它的格子 |
| 连击链 | 在五秒窗口内接连吃下的浆果 |
| 传送门或环绕模式 | 一片场地,从一条边出去会把你从对面那条边带回来 |
| 网格图 | 顶点为网格格子、边连接相邻格子的图 |
| 哈密顿回路 | 恰好访问每一格一次的闭合路线 |
| 哈密顿路径 | 恰好访问每一格一次的开放路线 |
| 牛耕式转行(Boustrophedon) | 一种来回扫掠的模式,填满一个区域而不困住自己 |
| 曼哈顿距离 | 两格之间水平步数加垂直步数之和 |
| NP 困难 | 至少与那些可在多项式时间内验证的最难问题一样难 |
| PSPACE 完全 | 可用多项式量级内存求解的最难问题之列 |
我们为何仍在打造这样的东西
这篇文章有一个以怀旧作结的版本,而它不会是错的。贪吃蛇在这个十年里满五十岁。极多数人都有一段与它相连的具体记忆:一部具体的手机、一间具体的教室、一块具体的偏绿屏幕。
但怀旧并不是这款游戏至今仍值得被好好打造的原因。贪吃蛇之所以留存,是因为它是极少数规则完全可见、而深度完全隐藏的游戏之一。没有任何东西对你隐瞒。没有解锁,没有元进程,没有一项没给你看过的统计。抵达一局完美对局所需的一切,从第一秒起就在屏幕上——而你依然做不到,因为难度从来不在信息里,它在规划里。
这是一种罕见而诚实的游戏设计,它值得一个固定时间步长、一条正确的碰撞规则、一个尊重玩家的输入队列,以及一条滑动而非跳跃的蛇所付出的努力。这篇文章里的一切——每一张表、每一个公式、每一毫秒——之所以存在,是为了让你在输的时候,知道是你的决定输了。
现在,去在经典模式里突破 2000 分吧。沿着边缘规划路线。别为金色浆果停下来。
