package main import ( "fmt" "math/rand" ) type Suit int func (s Suit) String() string { switch s { case 0: return "♠" case 1: return "♥" case 2: return "♦" case 3: return "♣" case 4: return "★" default: panic("bad suit") } } type Card int func (c Card) Joker() bool { return (c == 0) } func (c Card) Masked() bool { return (c == -1) } func (c Card) Suit() Suit { if c.Joker() || c.Masked() { panic("Suit on invalid") } return Suit(int(c) % 5) } func (c Card) Face() int { if c.Joker() || c.Masked() { panic("Face on invalid") } return int(c) / 5 } func (c Card) String() string { if c.Joker() { return "Jok" // 🂿 U+1F0BF } if c.Masked() { return "INV" // Invalid } switch c.Face() { case 11: return fmt.Sprintf(" J%s", c.Suit().String()) case 12: return fmt.Sprintf(" Q%s", c.Suit().String()) case 13: return fmt.Sprintf(" K%s", c.Suit().String()) default: return fmt.Sprintf("%2d%s", c.Face(), c.Suit().String()) } } func NewMasked() Card { return Card(-1) } func NewJoker() Card { return Card(0) } func NewCardFrom(face int, suit Suit) Card { return Card(face*5 + int(suit)) } func Shuffle(c []Card, entropy *rand.Rand) { entropy.Shuffle(len(c), func(i, j int) { c[i], c[j] = c[j], c[i] }) } const DeckSize = 58 * 2 func Deck() []Card { // The full game deck is two 58-card decks // Each 58-card deck has 3 jokers plus {3..10 J Q K} in 5 suits. ret := make([]Card, 0, DeckSize) for i := 0; i < 6; i++ { ret = append(ret, NewJoker()) // Joker } for s := 0; s < 5; s++ { for f := 3; f < 14; f++ { ret = append(ret, NewCardFrom(f, Suit(s)), NewCardFrom(f, Suit(s))) } } return ret }