题目重点:题目的设计追问聚焦 Player/Hand 分离、连续分牌处理、多副牌洗牌与 Cut Card 触发;用状态机和具体局面说明取舍。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练版 Player 持有一个有序 Hand 列表;每个 Hand 有自己的牌、下注额、结算状态和唯一 ID。Split 需经过 RuleSet 校验,例如是否允许再次分牌以及最大 Hand 数;这些规则不是题目指定。
- Shoe 含 N 副标准 52 张牌,N 可配置为 6–8;洗牌时用 Fisher–Yates 类均匀置换。Cut Card 是进入预定穿透深度后的标记,不是可发给玩家的牌。
- Cut Card 出现后本训练版完成当前局再换新 Shoe;具体赌场流程可不同,需要在面试时澄清。
解题路线
- Player 不因 Split 被复制。一次 Split 把原 Hand 的一张牌与新抽的牌组成原 Hand,再创建兄弟 Hand 放到同一 Player 的手牌列表;两份 Hand 各有下注与状态。
- 把待行动 Hand 放进队列。玩家对队首 Hand 选择 hit/stand/double/split;若继续 Split,把新 Hand 插在规则规定的位置;每个 Hand 独立推进直到完成。迭代状态机比无上限递归更容易暂停与恢复。
- GameRound 保留当前行动的 playerId/handId、庄家手牌与 Shoe 引用。Split、发牌、下注扣款与回合迁移作为原子状态转移,按 handId 记录日志,结算时逐手计算。
- Shoe 洗好 N×52 张牌后在指定剩余张数或穿透位置放 Cut Card;draw() 跳过标记、设置 reshufflePending,当前局结束统一替换 Shoe。若牌数不足以完成新局,应在发局前换 Shoe。
- 测试连续 Split、最大 Hand 数、单手爆牌不影响兄弟手、Cut Card 出现在中途和重洗时仍有未结算局。
手动走一遍
Player P 原有 Hand H1=[8♠,8♥]。Split 后 P.handIds=[H1,H2],两手各一张 8 并分别补牌。若 H1 又补到 8 且规则允许,追加 H3;此时 P 仍是同一玩家,三手独立下注和结算。Shoe 若在当前局的第二手发牌时触及 Cut Card,只设置 pending,庄家与所有手完成该局后才换 Shoe。
规模与取舍
N 副牌共 52N 张,构建与洗牌 O(52N) 时间和空间;抽一张摊销 O(1)。H 手、每手 A 次动作时状态推进 O(H+A),日志 O(A),队列最多 O(H)。若用数组中间插入新 Hand 可能 O(H),可用 deque/链表或在末尾追加并明确行动顺序。
易错点与追问
容易失分的边界
- Split 时复制 Player,导致余额、身份和其他 Hand 状态分叉。
- Hand 只存两张牌,后续 hit 与再次 Split 无法表达。
- 把 Cut Card 当真实牌发出或遇到标记立刻重洗,破坏当前局的牌序。
- 没有 RuleSet 就硬编码重分牌上限或 A 牌特殊规则。
- 结算只按 Player 汇总一次,漏掉每手独立胜负与下注。
继续深挖
- 若允许多个玩家并发操作,如何保证同一 Shoe 的抽牌顺序?
- 重复请求 Split 或网络重试怎样做到幂等?
- 游戏断线恢复时,哪些状态必须持久化以重放到相同结果?
- 洗牌随机数在审计与公平性验证中如何记录和保护?
