状态与异常:补齐体验的另一半
只有正常截图的需求,就像只定义了 200 返回的接口。真正上线后,加载、失败、取消和恢复都会发生,玩家需要在每一种情况下知道还能做什么。
状态描述“此时系统允许什么”
不要把弹窗是否可见当成整个功能状态。失败弹窗关闭了,不代表游戏已重新开始;暂停界面隐藏了,也不代表后台计时和输入已经恢复。
这是教学状态机。正式版本还要给 WIN、LOSE 等事件添加前置条件,并定义数据更新、保存和反馈等动作。
交互实验正在准备…请启用 JavaScript。

给每次转移补一行说明
| 当前状态 + 事件 | 条件 | 动作 | 玩家反馈 |
|---|---|---|---|
| ready + START | 棋盘已准备好 | 创建唯一当前局 | 显示目标并允许操作 |
| playing + HIDE | 当前仍在局内 | 暂停,补充检查点 | 返回后说明进度 |
| playing + WIN | 目标已达成 | 锁定结算,确认进度 | 显示完成与下一关 |
| lost + RETRY | 未在重新初始化 | 重置当前关的一局 | 新棋盘就绪后可操作 |
| paused + WIN | 不允许 | 拒绝或排队,按正式规则定义 | 不出现意外结算 |
同一个事件可能来自不同地方。动画结束、服务器返回、按钮点击,都不应绕过状态约束直接修改最终结果。
先列出四类容易遗漏的事件
重复:开始连点、奖励回调重放、页面重复挂载。
乱序:较旧的请求结果晚到,覆盖了玩家已经开始的新一局。
中断:切后台、断网、取消、组件卸载或进程结束。
恢复:读取旧存档、版本不兼容、记录损坏或权威数据冲突。
每类都至少写一个具体事件序列,比笼统写“处理异常”更容易实现。
旧局请求开始 → 玩家退出 → 开新局 → 旧请求返回
期望:旧结果不能覆盖新局;日志能解释为什么被忽略。
状态数量不是越多越好
如果两个状态允许的事件、数据约束和玩家反馈完全相同,可能不需要拆开。反过来,若“显示成功但等待确认”与“最终确认成功”有不同恢复规则,就不能只用一个 success 掩盖差别。
发给 AI 的要求
请先给状态转移表,再实现界面。
包含当前状态、事件、条件、数据变化、进入/退出动作、玩家反馈。
对重复、乱序和中断各给一个反例测试。
无法接受的事件保持一致状态,并留下必要诊断信息。
动手练习
选一个功能,暂时不画 UI,只写状态表。再逐项检查:每个状态是否有明确出口?每个异步结果是否属于当前操作?每个“成功”是否真的达到你承诺的确认程度?
本章状态机与实验为原创教学模型。错误应被明确识别和解释的网页无障碍原则,可参见 W3C:错误识别;游戏中的异常范围还需要结合实际规则扩展。