把 2048 的移动规则写清楚:合并、方向与撤销

举报
yd_242486459 发表于 2026/10/22 10:06:44 2026/10/22
【摘要】 一个 4×4 网格看起来简单,边界却集中在“每块每步只能合并一次”、无效移动不应改变局面,以及四个方向如何复用同一套规则。本文记录一个浏览器版 2048 的实现思路、现有验证脚本覆盖点和本地复核方法。

2048 的界面很直观,真正容易出错的是移动规则。向左推一行时,先忽略空格,再从左到右扫描:相邻且相同的数字合并成一个翻倍数字,合并后的新数字本轮不再参与下一次合并,最后补足空格。比如 [2,2,2,2] 应得到 [4,4,0,0],本次得分增加 8;[4,4,8,0] 得到 [8,8,0,0],不能把刚产生的 8 再立刻合成 16。

实现时把规则拆成两层。slideLine 只处理一条线并返回新线与得分,moveBoard 负责从棋盘取行或列、调用它,再把结果写回。这样合并逻辑不必为上下左右各写一遍。向右或向下时,将取出的线反转后沿同一方向扫描,写回前再反转;横向读取行,纵向读取列。核心片段如下:

if (i + 1 < values.length && values[i] === values[i + 1]) {
  const merged = values[i] * 2;
  out.push(merged);
  score += merged;
  i++; // 跳过被合并的下一块
} else {
  out.push(values[i]);
}

另一个重要边界是“按键了”不等于“局面变了”。如果朝左移动时棋盘本来已经贴左,程序应直接结束这次操作,不增加分数、不生成新块,也不覆盖撤销记录。这里先比较移动前后的棋盘,只有 changed 为真才进入状态更新:保存旧棋盘、分数和胜利标记,应用新棋盘与合并分数,随后生成新块。撤销则恢复这份快照并清空撤销入口,因此当前实现提供的是一步撤销。最高分单独写入浏览器本地存储,撤销恢复当前分数,但不会把最高分降回去,这符合“历史最佳”的含义。

方向处理采用归一化思路:水平与垂直只决定如何抽取、写回;左右或上下决定是否反转。统一核心减少重复代码,也让测试能用同一组小棋盘检查四个方向的落点。结束判定则先检查是否还有空格,再检查每个格子的右邻和下邻;只要存在空位或相邻同值,就仍有移动机会。达到 2048 后设置胜利状态并显示提示,玩家仍可继续合并。

本地验证无需安装依赖。在项目目录运行:

node verify-2048.js

现有脚本从 HTML 中提取纯函数区,在 Node 的 VM 环境运行,并断言合并计分、单次合并限制、无效移动的 changed 标记、四方向映射和游戏结束判定;它还检查无效移动的提前返回出现在 spawn() 之前。运行结果为 PASS。这不是完整浏览器端到端测试:撤销按钮、触摸滑动、键盘事件和本地存储目前由源码实现,脚本没有在真实浏览器中模拟这些交互。实际复核时可以打开 index.html,分别用方向键、WASD、方向按钮和滑动操作,并观察分数、撤销与重新开始。

这个小项目昨天已部署到华为云 AI 开发者空间并获得沙箱积分;那只能说明作品提交与积分流程已完成,不能据此推断线上性能或真实用户数据。本文关注的是代码规则和本地验证。实现过程中使用了 AI 协助整理代码与验证思路,规则边界、脚本结果及文中关于覆盖范围的说明均依据当前源码和已有脚本复核。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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