Skip to content

UNO 插件总览 ​

CardGameEngine 内置的标准 UNO 牌类游戏插件,通过 UnoPlugin 装配到 GameEngine 即可对局。

概述 ​

UNO 插件(UnoPlugin)基于引擎核心(GameEngine + GameContext)以及公共插件 TurnPlugin、DrawPlugin 实现,提供完整的标准 UNO 规则:108 张牌堆、初始 7 张手牌、出牌方向、Skip / Reverse / DrawTwo / Wild / Wild Draw Four 效果、胜负判定。

UNO 插件不单独使用——它依赖 TurnPlugin(回合推进)与 DrawPlugin(手牌 zone / 抽牌重洗),需要按顺序 engine.use() 装配。createDefaultPluginRegistry() 已封装该默认装配栈。

牌堆构成 ​

标准 UNO 牌堆共 108 张(UNO_DECK_SIZE = 108),由 createUnoCards() 生成:

来源颜色 / 类型张数
数字牌 0每色 × 14 × 1 = 4
数字牌 1–9每色 × 24 × 9 × 2 = 72
Skip每色 × 24 × 2 = 8
Reverse每色 × 24 × 2 = 8
Draw Two每色 × 24 × 2 = 8
Wild—4
Wild Draw Four—4
合计108

四种实色(UNO_COLORS):red / yellow / green / blue。Wild 类牌自身颜色为 'wild',实际生效颜色由玩家在出牌后通过 CHOOSE_COLOR_ACTION 指定。

核心规则 ​

  • 初始手牌:每名玩家发 7 张(UNO_INITIAL_HAND_SIZE = 7)。
  • 初始弃牌:游戏开始时由 UNO_FLIP_INITIAL_ACTION 从牌堆顶翻牌,直到出现数字牌作为起始弃牌;功能牌 / Wild 牌轮转回牌堆底部。
  • 出牌方向:由 TurnPlugin 的 TURN_VARIABLE_DIRECTION 变量维护(1 顺时针 / -1 逆时针),Reverse 牌切换方向。
  • 合法出牌:与当前生效颜色相同,或与弃牌堆顶张牌面相同(数字牌按点数、功能牌按类型匹配);Wild 类牌可随时打出。
  • Wild Draw Four 限制:仅当玩家手中无与当前颜色同色的牌时才允许打出(canPlayWildDrawFourRule)。
  • 胜利条件:某玩家手牌为 0 即获胜(WinRule + handleCardPlayed 判定)。

效果一览 ​

卡牌类型效果触发事件
number无特殊效果,直接结束回合—
skip跳过下家UNO_PLAYER_SKIPPED
reverse反转出牌方向;两人局等价于跳过UNO_PLAYER_REVERSED(+ UNO_PLAYER_SKIPPED 当两人局)
draw2下家抽 2 张并跳过UNO_DRAW_TWO
wild等待玩家选色UNO_COLOR_CHANGED(reason='choose')、UNO_COLOR_CHOSEN
wild_draw4等待玩家选色,选色后下家抽 4 张并跳过UNO_COLOR_CHOSEN → UNO_DRAW_FOUR

流程图 ​

                       createGame / engine.start()
                                  │
                                  ▼
                       ┌──────────────────────┐
                       │  GAME_STARTED        │
                       │  handleGameStarted   │
                       └─────────┬────────────┘
                                 │
            ┌────────────────────┴─────────────────────┐
            ▼                                          ▼
   每位玩家 DRAW_CARD(7)                  UNO_FLIP_INITIAL
   (UNO_INITIAL_HAND_SIZE)            翻到数字牌作为初始弃牌
            │                                          │
            └────────────────────┬─────────────────────┘
                                 ▼
                       ┌──────────────────────┐
                       │   玩家轮到出牌        │◀────────┐
                       └─────────┬────────────┘          │
                                 │                       │
                                 ▼                       │
                  ┌──────────────────────────────┐       │
                  │  PLAY_CARD / DRAW_CARD /      │       │
                  │  CHOOSE_COLOR                 │       │
                  └──────────────┬───────────────┘       │
                                 │                       │
                                 ▼                       │
                         CARD_PLAYED 事件                 │
                                 │                       │
                  ┌──────────────▼───────────────┐       │
                  │  handleCardPlayed            │       │
                  │  判定胜负 → 派发对应 Effect   │       │
                  └──────────────┬───────────────┘       │
                                 │                       │
                  ┌──────────────▼───────────────┐       │
                  │  Effect (Skip/Reverse/...    │       │
                  │  /Wild/WildDrawFour)         │       │
                  │  → END_TURN / DRAW_CARD      │       │
                  └──────────────┬───────────────┘       │
                                 │                       │
                                 └───────────────────────┘
                                 │
                            有人手牌为 0
                                 ▼
                       ┌──────────────────────┐
                       │  GAME_WON            │
                       │  UNO_GAME_WON         │
                       │  GAME_FINISHED       │
                       └──────────────────────┘

模块组成 ​

模块说明详细文档
UnoPlugin插件主对象,装配 setup / rules / actions / eventsuno-plugin.md
UnoStatezone id / variable key 常量与访问器state.md
UnoActionsCHOOSE_COLOR、UNO_FLIP_INITIAL Actionactions.md
Effects5 种卡牌效果的副作用函数effects.md
Rules4 类校验规则rules.md
Cards颜色 / 类型 / 卡牌构造cards.md
Events8 种 UNO 专属事件events.md

快速上手 ​

ts
import { GameEngine, TurnPlugin, DrawPlugin, createPlayCardAction } from 'decklet'
import { UnoPlugin } from 'decklet/uno'

const engine = new GameEngine()
engine.use(TurnPlugin).use(DrawPlugin).use(UnoPlugin)

engine.createGame({
  players: [
    { id: 'p1', name: 'Alice', seat: 1 },
    { id: 'p2', name: 'Bob', seat: 2 }
  ]
})
engine.start()

// 当前轮到的玩家出牌
const currentId = engine.getState().currentPlayerId!
engine.dispatch(createPlayCardAction(currentId, ['<cardId>']))

完整示例参见 examples/uno.ts,演示了 3 人局从发牌到分出胜负的全流程。

注意事项 ​

  • UNO 插件必须与 TurnPlugin、DrawPlugin 一起使用,且装配顺序为 TurnPlugin → DrawPlugin → UnoPlugin(由 RuleEngine 短路顺序决定)。
  • UnoPlugin.setup 通过 zone / cards 存在性判断保持幂等,兼容回放重放。
  • Wild 牌的"当前生效颜色"不存储在卡牌自身,而是记录在 UNO_VAR_CURRENT_COLOR 变量中。
  • 引擎内置事件(CARD_PLAYED / GAME_WON / GAME_FINISHED)与 UNO 专属事件并存,前者用于通用流程,后者用于业务细节。