U07 · 不看页面,也能知道游戏是否结束
v0.4 · 先修:数组、模块、手册 22 的测试基础;工作台。选题参考:Odin Battleship。本节规则为原创缩小版。
先做一个 5×5 的练习棋盘,放若干占一格的目标,点击格子判断是否命中。第一版只有单人清除全部目标,之后再增加两人轮流攻击;不同时做拖拽、联网和电脑策略。
动手路线:每一步都有文件和结果
先完成 统一启动与恢复手册 的首次准备。以下命令均在自己的练习根目录执行;原文中的 api/web/desktop 概念对应本节列出的现成文件,不需要猜测如何搭空项目。
- 打开
u07/starter/model.ts,按 createBoard → fire 的顺序逐个实现。下面第1节起解释规则;每完成一个函数就重跑样例/测试。 - 执行以下三条,分别核对样例、行为和类型。未完成的 TODO 应失败,全部实现后测试应为
fail 0:
node tools/try.mjs u07
node tools/check.mjs u07
npm run check
-
打开
runtime/web/u07.js,找到对自己规则函数的调用。先用一句话记录输入从哪里来、结果写到哪里;读不懂的语法回到本节先修对应章节。 -
构建并启动自己的作品:
node tools/build-app.mjs u07
node tools/lab.mjs start u07
-
实际操作:两人轮流操作同一页面。玩家1打0,0,玩家2打1,1,玩家1打1,1,玩家2打2,1;玩家2获胜,所有格子禁用;开始新局恢复25格。
-
解释与再做一次:命中后回合怎样改变?为何既要按钮禁用,也要规则拒绝重复和结束后攻击? 在自己的 LEARNING.md 先写答案,再选本节末尾的变式,列一个新失败例子后修改。保持原用例通过。仅跑通配套界面、没有完成规则与解释,记录为“参考演示已观察”,不记录为自己完成作品。
卡在规则时按“函数输入→分支条件→返回值→参考实现”逐级看提示;卡在运行时按 故障表 定位。若想单独观察参考成品,在构建命令后加 --reference;页面会明确标出参考演示。观察完再去掉该参数重建,继续自己的 starter。
1. 用坐标描述棋盘
打开 u07/starter/model.ts,Board 保存 size、ships、shots。坐标从 0 开始,5×5 的合法范围是 0–4。先在纸上画出 (1,1) 与 (2,1),预测 (5,0) 为什么不在棋盘内。字符串 x,y 只是内部索引,界面可以显示更友好的名称。
完成 createBoard:边长限 1–20 的整数,目标不能为空,坐标必须是范围内整数且不重叠。运行 node tools/try.mjs u07,得到两个目标与空攻击记录。创建棋盘不应偷偷发起一次攻击。
2. 一次攻击只改变一份状态
完成 fire:先检查越界、游戏是否已结束和是否重复攻击,再返回新棋盘、hit、over。命中数不用另存一份计数,可从目标与攻击集合判断。保留旧棋盘,方便比较前后差异。
执行 node tools/check.mjs u07。先读未命中→命中→全部击中的顺序,再主动在 sample.json 改成错误坐标。重复点已经攻击的格子必须拒绝,不能让一次命中累加成“击沉更多目标”。
3. 写一个最小页面
按手册 13/14 建页面,把 25 个 button 放在网格中,每个按钮保存坐标并有可读标签,例如“第 2 行第 3 列,未攻击”。点击后只调用 fire,再按新状态渲染。TS 规则接原生页面时先按工作台转为 JS,或使用手册 Vue/TS 工具链。
未攻击、未命中、命中除了颜色还要有文字或符号。键盘能到达每个可操作格子;已经攻击的按钮可禁用,但服务规则仍要能拒绝重复调用。胜利时显示结果并停止继续攻击。
4. 加回合时,先定义非法动作是否消耗回合
第二版准备两个独立棋盘和 currentPlayer。规定只有有效攻击才交换回合,重复/越界不消耗回合;结束以后不能再交换。先写一个不涉及页面的 nextTurn 测试,再接界面。
本机双人轮流时增加交接屏,交接前不展示对方目标位置。固定目标用于验证,随机放置作为后续功能,不让随机性影响基础测试。
5. 排错与自检
| 现象 | 优先检查 |
|---|---|
| 同一格两次都算命中 | shots 是否在判断前已经检查;是否重复追加 |
| 边角格不可点或越界 | 页面行列编号是否与 0 起点模型一致 |
| 颜色变了但刷新渲染恢复 | 是否只改 DOM,未更新模型 |
| 输赢后仍可攻击 | 规则是否检查结束状态,而不只禁用按钮 |
完整检查需覆盖边界格、非整数、目标重叠、重复攻击、全部命中、结束后操作、双人合法/非法回合和键盘。核心测试只覆盖单棋盘规则,不覆盖第二版回合与页面。
6. 独立变式与停靠点
增加“重开一局”:目标布局相同,攻击历史和回合重置,原局记录可以作为只读复盘保留。先预测重开后再打同一格应允许,再实现。以后扩成长船时另定义连续性、方向与整船击沉,不能把本节单格目标直接冒称完整海战规则。
暂停时保存代码和测试,关闭页面即可。完成者可走 U08 学习另一种状态:随时间失效的缓存。