# 36字花核心玩法与前端规则摘要 ## 1. 项目定位 36字花是一个**单期开奖结果、单期号循环运行**的实时开奖类游戏。 前端的核心界面是: - 36 宫格下注盘 - 倒计时与当前期状态栏 - 筹码与确认下注区 - 开奖历史与走势信息 - 公告、规则、自动托管、充值提现等外围模块 产品运行原则: - 全平台共享同一局数据 - `PC` 与 `Mobile` 只分界面,不分玩法、不分对局 - 前端必须以服务端状态为准,不能靠本地时间自行判断开奖或封盘 --- ## 2. 核心玩法 ### 2.1 基本盘面 - 游戏共有 **36 个号码格子** - 每个格子代表一个“字花编号” - 编号范围为 **1-36** - 当前前端盘面布局为 **6 x 6** 相关代码与约束: - [src/features/game/shared/constants.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/shared/constants.ts) - `GAME_GRID_ROWS = 6` - `GAME_GRID_COLUMNS = 6` - `GAME_TOTAL_CELLS = 36` ### 2.2 开奖规则 - 每一期只会开出 **1 个中奖号码** - 开奖号码属于 1-36 中的一个 - 用户只要下注号码集合中包含该号码,即视为中奖 接口口径见: - [docs/36字花-移动端接口设计草案.md](/Users/jiaunun/Desktop/36-character-flower/docs/36字花-移动端接口设计草案.md) - `POST /api/game/placeBet` 文档原意: - 玩家提交的是“号码集合 + 单注金额” - 系统按“单注金额 × 号码数量”计算本笔总扣款 - 开奖后只出一个号码 - 若该号码命中玩家所选集合,则该笔下注中奖 --- ## 3. 下注模型 ### 3.1 单注结构 一笔下注至少包含: - `period_no`:下注目标期号 - `numbers`:本次下注号码集合 - `single_bet_amount`:单个号码的下注金额 说明: - `numbers` 是一个号码集合,而不是单个号码 - 多选号码时,总扣款 = `single_bet_amount × numbers数量` - 重复号码应去重 ### 3.2 前端当前数据模型 当前前端 store 中的单笔选择数据为: - `cellId` - `chipId` - `amount` - `placedAt` - `source` 定义见: - [src/features/game/shared/types.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/shared/types.ts) - `BetSelection` 当前本地 mock 与 store 落地方式是: - 每点击一个格子,会追加一条 `selection` - 每条 `selection` 对应一个格子和一个筹码金额 这与接口文档中的“号码集合提交”并不完全一致。 因此当前前端可以先采用如下理解: - UI 交互阶段:按“逐格选择”记录本地状态 - 提交到后端阶段:再把本地多个格子聚合成 `numbers` 这是后续 `confirm bet` 需要承担的转换逻辑。 --- ## 4. 回合状态机 ### 4.1 当前状态枚举 当前项目中定义的回合阶段为: - `waiting` - `betting` - `locked` - `revealing` - `settled` 定义见: - [src/features/game/shared/constants.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/shared/constants.ts) 接口文档中的状态口径包括: - `betting` - `locked` - `settling` - `finished` - `void` 说明: - 当前前端内部状态和接口文档状态还未完全统一 - 第一阶段前端可继续沿用内部状态机 - 后续真实联调时,要补一层接口状态 -> 前端状态的映射 ### 4.2 各阶段前端规则 #### `BETTING` - 允许选格子 - 允许切换筹码 - 允许清除当前选择 - 允许重复上一注 - 允许确认下注 - 允许开启自动托管 #### `LOCKED` - 已封盘 - 前端必须立即停止下注交互 - 不应等待后端返回后才禁用点击 #### `REVEALING / SETTLING` - 等待开奖与派彩 - 展示开奖结果、跑马灯、中奖态 #### `SETTLED / FINISHED` - 本期结束 - 准备进入下一轮 - 历史、走势、余额等应刷新 #### `VOID` - 本期作废 - 需要退款待开奖本金 - 前端要清理本期下注态并正确提示 --- ## 5. 封盘与倒计时规则 ### 5.1 核心原则 - 前端必须以服务端返回的时间和阶段为准 - 到达封盘时间点时,前端应立即锁盘 - 即使网络延迟,也不能继续允许下注交互 这点在需求文档中是明确要求: - [docs/frontend-baseline-requirements.md](/Users/jiaunun/Desktop/36-character-flower/docs/frontend-baseline-requirements.md) ### 5.2 当前前端倒计时模型 当前前端使用: - `round.bettingClosesAt` - `round.revealingAt` - `round.settledAt` 并通过: - [src/features/game/shared/selectors.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/shared/selectors.ts) - `getRoundCountdownMs(round)` 来计算当前倒计时毫秒数。 规则如下: - `waiting / betting`:倒计时到 `bettingClosesAt` - `locked / revealing`:倒计时到 `revealingAt` - 其余:倒计时到 `settledAt` ### 5.3 Mock 数据口径 当前 mock 数据中: - 开始后约 18 秒封盘 - 约 24 秒开奖 - 约 30 秒结算 来源: - [src/features/game/shared/mock-data.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/shared/mock-data.ts) 这只是前端演示节奏,不代表最终真实服务端配置。 --- ## 6. 赔率、金额与筹码规则 ### 6.1 当前赔率 当前 mock 中每个格子赔率固定为: - `36` 来源: - [src/features/game/shared/mock-data.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/shared/mock-data.ts) - `createGameCells()` ### 6.2 当前默认筹码 当前默认筹码面额为: - `10` - `25` - `50` - `100` - `200` - `500` 来源: - [src/features/game/shared/constants.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/shared/constants.ts) - `DEFAULT_GAME_CHIP_AMOUNTS` ### 6.3 下注限制 从接口文档与基线需求中可得出以下前端规则: - 单次下注号码数量不得超过 `pick_max_number_count` - 单号码下注金额不得超过 `single_number_max_bet` - 总下注额不得超过余额 - 封盘后不能继续下注 文档来源: - [docs/36字花-移动端接口设计草案.md](/Users/jiaunun/Desktop/36-character-flower/docs/36字花-移动端接口设计草案.md) - [docs/frontend-baseline-requirements.md](/Users/jiaunun/Desktop/36-character-flower/docs/frontend-baseline-requirements.md) --- ## 7. 中奖、历史与走势 ### 7.1 历史记录 每期开奖后应产生一条历史记录,至少包括: - `roundId` - `winningCellId` - `settledAt` - `payoutMultiplier` - `totalPoolAmount` 定义见: - [src/features/game/shared/types.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/shared/types.ts) - `HistoryEntry` ### 7.2 走势 前端会基于历史数据派生走势信息,包括: - `currentStreak` - `hitCount` - `missCount` - `direction` - `lastHitRoundId` 派生逻辑见: - [src/features/game/shared/selectors.ts](/Users/jiaunun/Desktop/36-character-flower/src/features/game/shared/selectors.ts) - `deriveTrendEntries(history)` 说明: - 走势属于纯派生展示数据 - 不应由 UI 组件自己重复计算 --- ## 8. 公告、维护与运行开关 ### 8.1 运行开关 接口文档中存在: - `runtime_enabled` 含义: - `true`:游戏正常运行 - `false`:后台维护中,禁止下注 规则: - 维护中不允许新下注 - 当前已开盘的一局仍可正常开奖和派彩 - 前端应禁用下注入口并提示维护状态 ### 8.2 公告 公告是前端大厅的一部分,但不属于主玩法。 当前前端已存在公告模型: - `AnnouncementState` - `AnnouncementItem` 它们属于会话层状态,不应混入下注与回合逻辑。 --- ## 9. 自动托管 接口文档中已定义自动托管能力: - `POST /api/game/autoSpin` 入参包括: - `action` - `period_no` - `numbers` - `single_bet_amount` - `rounds` 说明: - 自动托管属于建立在主玩法之上的扩展能力 - 它依赖同一套选号与下注规则 - 当前前端可以先保留 UI 壳层,不需要在主玩法没走通前抢先落业务 --- ## 10. 前端当前最应该优先走通的主玩法链路 基于上述规则,当前前端最核心、最应该优先走通的是: 1. 状态栏拿到当前期状态与倒计时 2. 控制栏拿到当前筹码与总下注额 3. 选号盘点击格子后写入本地下注选择 4. 总下注额、选中数量、选号高亮联动刷新 5. 后续再补确认下注请求与开奖结果回写 这也是为什么当前下一步应优先实现: - `useGameBoardVm` 而不是优先改 `mobile` 或外围弹窗。 --- ## 11. 总结 36字花这个项目的核心,不是“36 张图摆出来”,而是下面这条实时对局链路: - 同一局 - 同一倒计时 - 同一开奖结果 - 36 格可选号码 - 用户用统一筹码模型下注 - 封盘、开奖、派奖按服务端状态推进 前端实现时必须坚持两点: 1. **玩法规则统一** - PC 和 Mobile 只能换壳,不能换规则 2. **服务端状态优先** - 前端可以先做本地交互反馈 - 但回合状态、封盘、开奖、派彩都必须最终以服务端为准