2048的撤销键:快照、分数与随机状态的边界

举报
yd_298688312 发表于 2026/10/23 10:12:02 2026/10/23
【摘要】 以2048·数字漫游的实际代码说明单步撤销的保存范围:旧棋盘与本局分数、最佳纪录、无效操作和随机过程。六项浏览器检查验证当前行为,并说明单步撤销与确定性回放的区别。

给2048加一个“撤销一步”按钮,看起来只需要保存旧棋盘。但实现时很快会遇到几个问题:得分要不要恢复,最佳纪录要不要回退,无效按键会不会覆盖记录,撤销后再次移动会不会生成同一个方块?

我以《2048·数字漫游》的现有代码为例,检查了这几项行为,并用固定随机数的浏览器测试验证了六个场景。这里讨论的是单步撤销,不是可以反复向前回退的完整历史系统。

保存一次有效移动之前的快照

程序用长度为16的数字数组表示棋盘,用一个数值保存本局分数。有效移动的入口如下:

function move(direction) {
  const result = nextBoard(board, direction);
  if (!result.changed) return;
  previous = { board: board.slice(), score };
  board = result.board;
  score += result.gained;
  spawn();
  render();
}

快照保存的是“这次操作之前”的棋盘和分数。计算移动结果时先不修改当前状态,确认发生变化后,才保存快照、应用结果、累加分数并生成新方块。

棋盘元素都是数字,因此这里用 slice() 复制一层数组就足够了。若后续把格子改成包含位置、动画或其他可变数据的对象,就需要重新检查这份复制能否隔离修改。

本局分数恢复,最佳纪录保留

撤销处理只恢复两个字段,然后消耗这份记录:

if (previous) {
  board = previous.board;
  score = previous.score;
  previous = null;
  render();
}

例如把两个2合并成4,本局增加4分。撤销后,两个2和原本的本局分数都恢复。最佳纪录则保留这次曾经达到的分数,因为它表示历史达到的最高值,未放进单局快照。

这种区分需要在产品规则中说清楚:撤销恢复当前局面,最佳纪录仍是历史记录。如果希望连最佳纪录一起回退,就要调整保存范围和持久化规则,不能只改界面上的数字。

无效按键不消耗撤销机会

如果棋盘已经贴在左侧,又没有能够合并的数字,再按左键不会产生有效移动。代码在保存快照之前检查 changed,因此不会把旧快照覆盖成当前棋盘,也不会额外生成方块。

测试这条规则时,输入局面必须确实不能继续合并。例如固定随机生成2后,一行已经是 [4, 2, 0, 0],向左无变化;若一行是 [2, 2, 0, 0],再次向左就会合并,它不能用作“无效移动”的测试样例。

撤销不等于重放随机过程

现有快照只包含棋盘和本局分数,没有保存随机数生成器状态。撤销后再次选择同一个方向,随机方块的位置或数值可能改变。

如果产品需要确定性的回放,就要把随机过程纳入设计,例如保存随机种子和生成器状态,或者记录每一步生成的方块。本版本没有实现这些能力,不能把它描述成完整回放。

六项实际检查

我在独立浏览器测试页中加载实际HTML,把随机函数固定为零,以便重复比较局面。检查结果如下:

场景 实际结果
两个2合并 保存旧棋盘和旧分数,本局增加4分
点击撤销 恢复原棋盘,本局分数回到原值
撤销产生历史最高分的一步 最佳纪录保留
已经撤销一次 快照清空,撤销按钮禁用
在有效移动后执行一次无效移动 棋盘和原撤销记录都不改变
开始新的一局 清空快照、本局分数归零并生成两块

六项均符合当前设计。固定随机数用于控制测试局面,不表示验证了生产环境的随机分布。

单步撤销最关键的设计工作,是先决定什么属于当前局面、什么属于历史纪录,以及哪些状态根本没有保存。明确边界后,按钮、快照和测试才能对应到同一套规则。

作品展示:https://gallery.developer.huaweicloud.cn/gallery/0068d35937000000

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。