题目重点:设计好友对战、走棋与允许窗口内undo,核对悔棋和对手新落子的并发竞争。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练象棋/国际象棋规则由独立engine验证,系统题关注会话状态与接口。只允许撤销自己的最近一步且对手尚未完成下一步。
- 对局完成才形成计分事实,global ranking读取可有界延迟;分数规则/和棋/超时需明确。
解题路线
- game记录players/board/turn/status/revision,move带moveId/expectedRevision。服务器验证玩家身份、turn和棋规后原子提交事件与新board,客户端只是预测显示。
- 每game串行或事务CAS revision,undo同样带expectedRevision,并核对lastMoveOwner与没有对手后续move。move/undo哪个先提交决定结果;不能让双方客户端各自认定允许。
- 事件流保存MOVE/UNDO/RESIGN/TIMEOUT及version,undo追加逆向事件与恢复state,不直接删日志导致重连失去解释。快照加events恢复,重复moveId不重复走棋。
- 推送带revision,客户端缺序重读snapshot或replay;断线不自动取消比赛,clock与超时在服务端,离线迟到move不使用客户端时间绕过。
- 结束CAS只一次创建resultId,rating/rank consumer按resultId幂等。撤销对局结果的政策必须版本化并可重算,不能把game event重放多次加分。
手动走一遍
A提交一步,revision10;B走下一步与A悔棋都以10发请求。若B先提交11,A undo预期版本失败;若A先undo成11,B原棋步需重同步后验证,不能在旧board上继续。
规模与取舍
单game写串行,但不同game可分片;board快照大小固定,日志按总步数。排名O(log U)有序更新或异步aggregate,棋局延迟与排行榜延迟分开预算。
易错点与追问
容易失分的边界
- 只在客户端禁按钮无法阻止race或恶意重复请求。
- undo把历史move删除会导致已看到旧revision客户端无法理解变化。
继续深挖
- 双方同意悔棋与单方窗口悔棋是不同规则,如何改状态机?
- 机器人/作弊分析在本题未指定,扩展应与权威合法走棋分离,不阻塞每步核心校验。
