feat: basic function
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from random import Random
|
||||
|
||||
SUITS = ("c", "d", "h", "s")
|
||||
RANK_LABELS = {
|
||||
2: "2",
|
||||
3: "3",
|
||||
4: "4",
|
||||
5: "5",
|
||||
6: "6",
|
||||
7: "7",
|
||||
8: "8",
|
||||
9: "9",
|
||||
10: "T",
|
||||
11: "J",
|
||||
12: "Q",
|
||||
13: "K",
|
||||
14: "A",
|
||||
}
|
||||
LABEL_RANKS = {label: rank for rank, label in RANK_LABELS.items()}
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class Card:
|
||||
rank: int
|
||||
suit: str
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if self.rank not in RANK_LABELS:
|
||||
raise ValueError(f"invalid rank: {self.rank}")
|
||||
if self.suit not in SUITS:
|
||||
raise ValueError(f"invalid suit: {self.suit}")
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{RANK_LABELS[self.rank]}{self.suit}"
|
||||
|
||||
@classmethod
|
||||
def parse(cls, value: str) -> "Card":
|
||||
if len(value) != 2:
|
||||
raise ValueError(f"card must have two characters: {value!r}")
|
||||
rank_label = value[0].upper()
|
||||
suit = value[1].lower()
|
||||
if rank_label not in LABEL_RANKS:
|
||||
raise ValueError(f"invalid rank label: {rank_label}")
|
||||
return cls(LABEL_RANKS[rank_label], suit)
|
||||
|
||||
|
||||
class Deck:
|
||||
def __init__(self, rng: Random | None = None) -> None:
|
||||
self._rng = rng or Random()
|
||||
self._cards = [Card(rank, suit) for suit in SUITS for rank in range(2, 15)]
|
||||
self._rng.shuffle(self._cards)
|
||||
|
||||
def draw(self, count: int = 1) -> list[Card]:
|
||||
if count < 1:
|
||||
raise ValueError("count must be positive")
|
||||
if len(self._cards) < count:
|
||||
raise ValueError("deck does not have enough cards")
|
||||
drawn = self._cards[-count:]
|
||||
del self._cards[-count:]
|
||||
return drawn
|
||||
|
||||
def burn(self) -> None:
|
||||
self.draw(1)
|
||||
Reference in New Issue
Block a user