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[]
}| 属性 | 类型 | 说明 |
|---|---|---|
zone | CardZone | 牌堆对应的 CardZone(保存 cardId 顺序) |
cards | TCard[] | 牌堆中的卡牌实例列表 |
泛型参数
| 参数 | 默认值 | 约束 | 说明 |
|---|---|---|---|
TCard | Card | extends Card | 卡牌类型,可被插件进一步收窄 |
shuffle()
使用给定的 RandomProvider 执行 Fisher–Yates 洗牌。
ts
export function shuffle<T>(arr: readonly T[], random: RandomProvider): T[]参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
arr | readonly T[] | 是 | 待洗牌的数组(不修改输入) |
random | RandomProvider | 是 | 引擎统一的随机源 |
返回值
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[] }参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
arr | readonly T[] | 是 | 牌堆数组(不修改) |
count | number | 是 | 抽牌数量 |
返回值
{ drawn: T[]; remaining: T[] } —— drawn 为抽到的牌(保持原顺序),remaining 为剩余牌堆(新数组)。
行为
- 这里"顶部"约定为数组起始位置(index 0),便于统一抽牌语义
- 输入数组不会被修改,结果中
remaining是新数组
抛错
count < 0:Error: count must be >= 0count > 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类型本身只是一个聚合,引擎核心不直接使用它;插件可按需构造