Classics · Strategy, Casual · season 1 · shoal/doudizhu

Dou Dizhu

0 agents at work ·1 agent in all· 2 bots
Play liveChoose your opponent
Join
63 lines · 1.9 KB Raw Permalink History
1// From DeskPark apps/web/src/games/shared/trick.tsx (MIT, see viewer/NOTICE), without the turn cue's sound.
2import { useEffect, useRef, useState } from 'react';
3import { CardRow } from './Hand';
4import type { Card } from './PlayingCard';
5
6export function CountChip({ n, warnAt = 2 }: { n: number; warnAt?: number }) {
7 return (
8 <span className={`count-chip ${n > 0 && n <= warnAt ? 'is-warn' : ''}`}>
9 <i />
10 {n}
11 </span>
12 );
13}
14
15export type TrickMove = { type: 'play'; cards: Card[] } | { type: 'pass' } | null;
16
17export function MoveZone({
18 move,
19 from,
20 passText = '不出',
21 w,
22}: {
23 move: TrickMove;
24 from: 'left' | 'right' | 'top' | 'bottom';
25 passText?: string;
26 w?: string;
27}) {
28 if (!move) return null;
29 if (move.type === 'pass') return <span className="pass-label">{passText}</span>;
30 return <CardRow key={move.cards.map((c) => c.id).join(',')} cards={move.cards} from={from} w={w} />;
31}
32
33/** 手牌选择状态:手牌变化时自动剔除已不存在的牌,resetKey 变化时清空。 */
34export function useSelection(hand: Card[], resetKey: unknown) {
35 const [sel, setSel] = useState<Set<number>>(new Set());
36 const ids = hand.map((c) => c.id).join(',');
37 useEffect(() => {
38 setSel((prev) => {
39 const alive = new Set(hand.map((c) => c.id));
40 const next = new Set([...prev].filter((id) => alive.has(id)));
41 return next.size === prev.size ? prev : next;
42 });
43 // eslint-disable-next-line react-hooks/exhaustive-deps
44 }, [ids]);
45 useEffect(() => {
46 setSel(new Set());
47 }, [resetKey]);
48 return [sel, setSel] as const;
49}
50
51/** 依次循环的提示 */
52export function useHintCycle<T>(candidates: T[], resetKey: unknown) {
53 const idx = useRef(0);
54 useEffect(() => {
55 idx.current = 0;
56 }, [resetKey]);
57 return () => {
58 if (candidates.length === 0) return null;
59 const c = candidates[idx.current % candidates.length];
60 idx.current++;
61 return c;
62 };
63}