Skip to content

Deck ​

Deck 表示一个牌堆:zone 描述其在 GameState 中的容器位置,cards 是该牌堆当前顺序下的 Card 实体(按需由 GameState 解析)。

概述 ​

Deck 是一个聚合类型,把 CardZone(保存 cardId 顺序)与 Card[](卡牌实例列表)组合起来,便于一次性操作整个牌堆。

shuffle 与 drawFromTop 是引擎提供的两个工具函数,配合 RandomProvider 使用,让随机性可被记录与回放。

Deck 类型 ​

ts
export interface Deck<TCard extends Card = Card> {
  zone: CardZone
  cards: TCard[]
}
属性类型说明
zoneCardZone牌堆对应的 CardZone(保存 cardId 顺序)
cardsTCard[]牌堆中的卡牌实例列表

泛型参数 ​

参数默认值约束说明
TCardCardextends Card卡牌类型,可被插件进一步收窄

shuffle() ​

使用给定的 RandomProvider 执行 Fisher–Yates 洗牌。

ts
export function shuffle<T>(arr: readonly T[], random: RandomProvider): T[]

参数 ​

参数类型必填说明
arrreadonly T[]是待洗牌的数组(不修改输入)
randomRandomProvider是引擎统一的随机源

返回值 ​

T[] —— 洗牌后的新数组(与原数组无引用共享)。

行为 ​

直接委托给 random.shuffle(arr)。插件禁止直接使用 Math.random 调用本函数 —— 应透传从 GameContext 或 ActionHandler 接收到的 RandomProvider。

示例 ​

ts
import { shuffle, SeededRandomProvider } from 'decklet'

const random = new SeededRandomProvider(123456)
const shuffled = shuffle(['a', 'b', 'c', 'd'], random)
console.log(shuffled)  // 确定性结果

drawFromTop() ​

从牌堆顶部抽取 count 张牌,返回抽到的牌与剩余牌堆。

ts
export function drawFromTop<T>(arr: readonly T[], count: number): { drawn: T[]; remaining: T[] }

参数 ​

参数类型必填说明
arrreadonly T[]是牌堆数组(不修改)
countnumber是抽牌数量

返回值 ​

{ drawn: T[]; remaining: T[] } —— drawn 为抽到的牌(保持原顺序),remaining 为剩余牌堆(新数组)。

行为 ​

  • 这里"顶部"约定为数组起始位置(index 0),便于统一抽牌语义
  • 输入数组不会被修改,结果中 remaining 是新数组

抛错 ​

  • count < 0:Error: count must be >= 0
  • count > arr.length:Error: Cannot draw ${count} cards from a deck with only ${arr.length} cards

示例 ​

ts
import { drawFromTop } from 'decklet'

const deck = ['c1', 'c2', 'c3', 'c4', 'c5']
const { drawn, remaining } = drawFromTop(deck, 2)
console.log(drawn)      // ['c1', 'c2']
console.log(remaining) // ['c3', 'c4', 'c5']
console.log(deck)      // ['c1', 'c2', 'c3', 'c4', 'c5']  原数组未修改

在 Plugin 中使用 ​

DrawPlugin 通过 DRAW_CARD action 抽牌时使用 moveCard 直接操作 state.zones,而不是 drawFromTop。但 drawFromTop 仍可在 Plugin 内部用于"批量抽牌到中间变量"的场景:

ts
import { drawFromTop, shuffle } from 'decklet'

// 在 ActionHandler 内
const handler: ActionHandler = {
  type: 'CUSTOM_DRAW',
  execute(action, ctx) {
    const state = ctx.state
    const deckZone = state.zones['deck']
    const deckCardIds = deckZone.cards
    const { drawn, remaining } = drawFromTop(deckCardIds, 5)

    // 用 ctx.random 而非 Math.random
    const shuffled = shuffle(deckCardIds, ctx.random)

    // ... 构造新 state ...
    return { state: nextState, events: [] }
  }
}

注意事项 ​

  • shuffle 必须接收 RandomProvider,禁止使用 Math.random 以保证可回放
  • drawFromTop 的"顶部"约定为数组起始位置(index 0)
  • 两个函数都是纯函数:不修改输入,返回新数组
  • Deck 类型本身只是一个聚合,引擎核心不直接使用它;插件可按需构造