One way to clear each phase. Compare the approach with your own, then try the patterns yourself.
"""Phase 1: Card equality must include suit, not just rank."""
from enum import Enum
class Suit(Enum):
SPADES = "S"
HEARTS = "H"
DIAMONDS = "D"
CLUBS = "C"
class Card:
"""A playing card. Rank is 1-13 where 1=Ace, 11=Jack, 12=Queen, 13=King."""
def __init__(self, rank: int, suit: Suit):
if rank < 1 or rank > 13:
raise ValueError(f"rank must be 1..13, got {rank}")
self._rank = rank
self._suit = suit
@property
def rank(self) -> int:
return self._rank
@property
def suit(self) -> Suit:
return self._suit
def __eq__(self, other: object) -> bool:
if not isinstance(other, Card):
return False
# Bug fix: a card is identified by both rank AND suit.
return self._rank == other._rank and self._suit == other._suit
def __hash__(self) -> int:
return hash((self._rank, self._suit))
def __repr__(self) -> str:
names = {1: "A", 11: "J", 12: "Q", 13: "K"}
label = names.get(self._rank, str(self._rank))
return f"{label}{self._suit.value}"
"""Phase 1: Hand.card_value scoring rules."""
from typing import List
from card import Card
class Hand:
"""A collection of cards with rules for how each card scores."""
def __init__(self, ace_high: bool = False):
self._cards: List[Card] = []
self._ace_high = ace_high
def add(self, card: Card) -> None:
self._cards.append(card)
def size(self) -> int:
return len(self._cards)
def get(self, index: int) -> Card:
return self._cards[index]
def all_cards(self) -> List[Card]:
return list(self._cards)
def card_value(self, index: int) -> int:
"""
Scoring value for the card at index. Rules:
- Ace (rank 1): 11 if ace_high else 1
- Face cards (Jack=11, Queen=12, King=13): all score as 10
- All others (2-10): score as their rank
"""
card = self._cards[index]
rank = card.rank
if rank == 1:
# Bug fix: ace_high must actually score the Ace as 11.
return 11 if self._ace_high else 1
if rank >= 11:
# Bug fix: face cards (J/Q/K) all score as 10, not their rank.
return 10
return rank
Sign in to join the discussion