在线联机原型全集:第 2 章 石头剪刀布(Rock–Paper–Scissors, RPS)

第 2 章:石头剪刀布(RPS),介绍了一个简单的回合制匹配游戏原型,包括玩家匹配、房间创建、加入、退出、动作选择、提交、判定、结算、存档等功能。

石头剪刀布(Rock–Paper–Scissors, RPS)

  • 类别:回合制匹配游戏原型
  • 目标:验证匹配、房间生命周期、锁步回合、服务器权威判定与日志存档的全流程。
  • 原型代号proto-002-rps
  • 依赖模块proto-001-echo-chatroom
  • 推荐语言栈:Go / Node.js / Rust
  • 网络协议:WebSocket(双向实时)

一、概述(Overview)

“石头剪刀布”是所有 匹配制游戏 的起点。
它既具备简单的规则确定性(三种动作、明确胜负),
又包含了最基础的网络交互闭环

匹配 → 准备 → 提交 → 判定 → 结算 → 存档

它验证了以下关键能力:

  • 匹配队列机制:支持多玩家排队等待配对;
  • 状态锁步(Turn-based Lockstep):同时提交指令,统一结算;
  • 服务器权威判定:防作弊与重放;
  • 断线重连对局恢复
  • 日志系统:完整记录对局过程。

这使得 RPS 成为整个“联机验证体系”的第二块基石。


二、核心玩法与系统目标(Gameplay & Objectives)

2.1 玩法简述

  • 玩家点击“开始匹配”;
  • 匹配系统将两个玩家配成一组;
  • 双方进入对战房间,倒计时开始;
  • 双方在 5 秒内选择动作(石头、剪刀、布);
  • 超时未提交则默认弃权;
  • 服务端判定胜负,广播结果;
  • 支持多局模式(BO3)。

2.2 系统目标与验证点

类别功能目标验证重点
匹配系统随机或 Elo 匹配两名玩家队列调度、并发锁
回合系统同步状态更新状态机控制、定时器
权威判定服务器结算胜负防作弊、防重放
存档系统保存战局日志可重放性验证
断线恢复重新连接后恢复状态Snapshot 恢复机制
观战系统第三方只读通道延迟广播与隔离
扩展验证积分 / Elo 排名MatchHistory + Leaderboard

三、系统架构设计(Architecture)

3.1 模块图

graph TD
A["Client"] --> B["Gateway Server"]
B --> C["Matchmaker"]
B --> D["Room Service"]
D --> E["Game Logic Engine"]
E --> F["Event Logger"]
E --> G["Ranking Service"]

说明:

模块功能说明
Gateway Server用户接入、身份验证、连接管理
Matchmaker匹配系统(队列、Elo 算法)
Room Service创建房间、维护状态机
Game Logic Engine回合判定逻辑与状态更新
Event Logger对局日志与重放存储
Ranking ServiceElo 积分与排行榜计算

3.2 系统分层

  1. 接入层(Gateway)

    • 负责连接与路由
    • 校验 token、绑定用户 ID
  2. 逻辑层(Game Engine)

    • 处理回合状态
    • 调用定时器触发结算
  3. 数据层(Storage)

    • Redis(匹配队列与房间状态)
    • PostgreSQL(对局日志、Elo 分数)
  4. 监控层(Metrics)

    • Prometheus 指标采集
    • Grafana 可视化

3.3 组件交互流程

sequenceDiagram
Client->>Gateway: request_match()
Gateway->>Matchmaker: enqueue(player)
Matchmaker->>RoomService: create_room(p1,p2)
RoomService->>Clients: notify_room_ready
Clients->>GameLogic: submit_action(rock/paper/scissors)
GameLogic->>Logger: record_event
GameLogic->>Clients: result(win/lose/draw)

四、功能模块详解(Functional Modules)

4.1 Matchmaker(匹配系统)

4.1.1 功能描述

匹配系统的任务是:

根据玩家的进入顺序或 Elo 分数,将两名玩家配成一场游戏。

4.1.2 队列机制

  • 基于 Redis SortedSet(score 为 Elo);

  • 支持:

    • enqueue(player_id, score)
    • dequeue(pair of players)
  • 匹配策略:

    • 优先相近 Elo;
    • 若等待时间 > T 秒,则扩大匹配窗口。

4.1.3 关键参数

参数默认值含义
MATCH_TICK100ms匹配轮询间隔
MATCH_WINDOW100 Elo初始 Elo 差距
EXPAND_RATE20 Elo/s匹配范围扩大速度

4.1.4 数据结构

type MatchRequest struct {
  UserID string
  Elo int
  EnqueueTime time.Time
}

4.2 Room Service(房间服务)

4.2.1 职责

  • 创建/销毁房间;
  • 管理房间成员;
  • 驱动游戏状态机。

4.2.2 状态机

stateDiagram-v2
  [*] --> Idle
  Idle --> Matching: enqueue
  Matching --> Ready: pair found
  Ready --> Playing: countdown
  Playing --> Judging: all submitted or timeout
  Judging --> Result: server decision
  Result --> Finished: show result
  Finished --> [*]

4.2.3 数据结构

type Room struct {
  ID string
  Players []Player
  State RoomState
  Round int
  Actions map[string]string
  Timer *time.Timer
}

4.3 Game Logic Engine(判定逻辑)

4.3.1 判定规则

动作 A动作 B结果
RockScissorsA 胜
ScissorsPaperA 胜
PaperRockA 胜
相同相同平局

4.3.2 防作弊机制

  • 客户端提交动作时不暴露给对方;
  • 每回合有唯一 RoundToken
  • 服务器收到动作 → 暂存;
  • 双方都提交或超时 → 判定;
  • 所有操作写入日志;
  • 客户端提交签名:SHA256(player_id + round + secret)

4.3.3 多局模式(BO3)

  • 每局独立计分;
  • 胜方计 1 分;
  • 先获得 2 分即胜。

4.4 Event Logger(事件日志)

4.4.1 日志结构

{
  "room_id": "rps-001",
  "round": 1,
  "actions": {
    "u1": "rock",
    "u2": "scissors"
  },
  "result": "u1_win",
  "timestamp": 1730689200
}

4.4.2 存储结构

  • Redis:短期缓存;

  • PostgreSQL:长期归档;

  • 支持回放(Replay):

    • 按时间序列重放;
    • 验证一致性 hash。

4.5 Ranking Service(Elo 排名)

4.5.1 算法公式

[
E_A = \frac{1}{1+10^{(R_B-R_A)/400}}
]
[
R_A’ = R_A + K(S_A - E_A)
]

4.5.2 参数

参数默认说明
K32调整系数
R_init1000初始 Elo
S胜=1, 负=0, 平=0.5比赛结果

4.5.3 数据结构

type EloRecord struct {
  UserID string
  Score int
  Win int
  Lose int
  Draw int
}

五、状态与事件定义(State & Event Definitions)

5.1 客户端事件

事件参数描述
match_start-匹配开始
match_success{room_id}匹配成功
round_start{countdown}回合开始
submit_action{move: rock/paper/scissors}提交动作
round_result{winner, actions}回合结算
match_end{score}对局结束

六、数据模型(Data Model)

字段说明
matchesid, p1, p2, result, start_at, end_at比赛记录
roundsid, match_id, round_no, actions, winner每回合日志
elo_scoresuser_id, elo, win, lose, draw玩家积分

七、验证指标(Metrics & KPI)

指标目标说明
匹配平均耗时< 2 秒正常队列延迟
回合提交延迟< 100msPing-Pong 校准
判定一致率100%日志校验
断线恢复成功率≥ 99%Snapshot
吞吐能力≥ 1000 房间 / 节点并发验证

八、扩展功能(Extensions)

  1. 积分排行榜(Elo Rank)

    • Redis SortedSet + 周期性刷新
    • 每日 Top N 公告
  2. 重连机制

    • 客户端断开后 30 秒内重新连接 → 恢复房间状态
    • 服务器持有 SessionSnapshot
  3. 观战系统

    • 延迟 1 回合广播动作(防剧透)
    • 分层广播:玩家 vs 观众
  4. 回放系统

    • 重放日志 → 客户端动画化重现
    • 支持加速播放与分析

九、技术选型与实现建议

层级推荐技术理由
网络层Go + WebSocket性能稳定
匹配层Redis SortedSet时间复杂度 O(logN)
状态层FSM + TimerWheel精准控制回合超时
数据层PostgreSQL强一致存档
缓存层Redis快速读取 Elo 与房间状态
日志层Loki / ElasticSearch可视化检索
监控层Prometheus + Grafana实时可视化

十、压测与运维(Load & Ops)

测试项内容目标
匹配压力10 万用户并发入队平均延迟 < 2s
回合同步每秒 5000 回合无漏包
日志写入500 MB/minIO 无阻塞
网络丢包恢复30% 丢包率重连成功率 >99%

自动化监控指标:

  • match_queue_length
  • room_active_total
  • elo_update_latency
  • disconnect_reconnect_total

十一、设计反思与演化(Reflection & Evolution)

11.1 设计反思

  • RPS 虽简单,但完整覆盖了在线对局最核心的流程闭环;
  • 它的关键不是“游戏逻辑”,而是“系统可靠性”;
  • 匹配、超时、判定、存档构成了所有游戏的公共骨架。

11.2 向下一阶段演化

目标下一原型
网格逻辑与棋盘状态→ #3 井字棋
回放 / 观战系统→ #4 快速问答抢答
状态同步与 Tick 机制→ #6 Pong
房间生命周期管理→ #10 mini-SLG

十二、总结

“石头剪刀布” 是 服务器权威模型(Server-authoritative Model) 的最佳入门。
它让我们验证了从“客户端输入”到“服务器决策”的完整闭环:
每一条消息、每一次延迟、每一个回合状态,
都在教我们一件事——

“在分布式的不确定世界中,服务器才是唯一真相。”

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页