2048合并规则通过了,胜利按钮为什么仍然错:一次单文件游戏的独立验收
为了准备华为云开放能力2048闯关活动,我用码道网页版辅助生成了一份单文件小游戏。页面不依赖npm、构建工具或CDN,键盘、触屏滑动和方向按钮共用一套移动逻辑。它有计分、最高分、撤销、游戏结束提示,以及合成2048之后的继续挑战。
这次最值得记录的结果,不是又做出一个2048,而是独立测试找到了一个容易被“算法测试全过”掩盖的问题:胜利弹窗里的“结束本局”按钮,实际上也在继续游戏。
本文只讨论本机取得的源码、实际测试和浏览器验证。写作时尚未创建活动沙箱或ECS,不能把本地能玩、AI总结完成、云端部署成功以及活动积分到账混成一个结论。
一、先明确一次移动到底发生什么
2048的一步可以拆成三个阶段:按方向压紧非零方块,相邻同值方块各合并一次,最后在有效移动后生成一个新方块。合并的顺序是规则,不只是实现细节。
例如左移一行:
| 移动前 | 移动后,不含随机新方块 | 本步得分 |
|---|---|---|
| 2,2,2,2 | 4,4,0,0 | 8 |
| 2,2,4,0 | 4,4,0,0 | 4 |
| 4,4,4,0 | 8,4,0,0 | 8 |
| 2,0,2,2 | 4,2,0,0 | 4 |
第二行尤其重要:两个2刚合成的4,不能在同一步又和原来的4合成8。只检查数字总和守恒,抓不住这种“同一步连续合并”错误,所以明确的规则样例与不变量检查缺一不可。
二、不要只测试另一份核心算法文件
生成的项目同时包含算法文件、测试脚本与内联HTML。如果测试只导入算法文件,即使全部通过,也不能证明网页内联的那份代码完全一致,更不能证明页面按钮接到了正确的状态转换上。
这次独立验收直接读取实际发布用的index.html,提取其中的内联脚本,在Node的vm隔离上下文中运行。测试提供最小DOM和本地存储替身,让脚本真实注册键盘、按钮与触屏事件,然后触发这些已经注册的回调。
为了构造接近胜利的棋盘,测试运行时向闭包注入一个只存在于测试中的夹具。它用于设置合成棋盘和读取状态,不写回HTML,也不把测试状态入口放进生产页面。这样可以把“最后一步合成2048”的验收稳定下来,不需要用几千次随机按键碰运气。
这里的DOM替身有明确边界:它能验证事件与状态逻辑,却不能证明浏览器布局、真实触屏手势或所有手机都正常。因此后面仍需用真实浏览器做单独检查。
三、失败证据是2048不等于0
回归用例先设置第一行1024、1024,其余位置为空,然后通过真正注册的ArrowLeft事件合成2048。确认胜利状态出现之后,再触发弹窗的备选按钮。
预期是新局:本局分数归零、胜利标记清除、棋盘只保留两个初始方块。实际测试却失败:
AssertionError: new round must reset the score
2048 !== 0
查到对应事件后,原因很清楚:两个选择最后都走向了继续游戏。备选按钮原来执行的是:
keepGoing = true;
render();
这段代码能正确关闭胜利遮罩,也不会抛异常。如果验收只看“点了以后弹窗消失”,很容易误判成功。但它没有清空分数,也没有重新生成棋盘,行为与文案不一致。
四、修正要小,对照要保留
修正没有重写合并算法,只把备选按钮文案改成“新开一局”,点击时调用已有的newGame()。主按钮仍然叫“继续挑战”,继续保留当前棋盘和分数。
测试也同时保留两条路径:备选按钮必须重置,主按钮必须不重置。如果只检查新局分数为零,却漏掉继续按钮,后续很可能把两个按钮一起接到newGame(),从一个错误变成另一个错误。
修正后的独立测试共8组,全通过。除胜利后的两条分支,还检查了单步合并、四方向映射、输入棋盘不被修改、无效移动不消耗随机数也不增加撤销记录、有效移动只加一个方块、撤销恢复棋盘和分数,以及触屏和屏幕方向按钮的事件接线。
其中一组枚举了由0、2、4、8、16组成的全部625种四格行,在四个方向上分别检查移动前后数字总和不变。它能覆盖很多压紧和方向转换错误,但不能替代前面的明确合并样例,也不能证明整个界面已经验收完毕。
五、再用真实浏览器补上界面这一层
在实际浏览器打开修正后的单文件页面,初始棋盘渲染16个格子和两个数字方块。通过方向键进行有效移动后,实际分数从0变为4;点击撤销后,本局分数恢复0,棋盘仍为16格。
这层检查证明了真实页面能加载、键盘能控制、分数能更新、撤销按钮能工作。它不等于已经在所有手机上测试,也不等于已经达到活动沙箱的公网部署要求。
一个有用的验收顺序是:先用确定性样例固定规则,再用不变量扩大输入覆盖,接着验证事件与状态转换,最后用真实浏览器确认界面和交互。每一层只回答自己的问题,不把上一层的绿色结果自动延伸成下一层的完成证明。
这份2048仍保留了最高分本地保存、最多20步撤销和继续挑战等功能;真正改进的是交付的可信度:一个“看起来完成”的按钮,现在有失败证据、最小修正和可重复运行的回归用例。
- 点赞
- 收藏
- 关注作者
评论(0)