import random from typing import List, Tuple SUITS = ['Hearts', 'Diamonds', 'Clubs', 'Spades'] RANKS = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'] RANK_VALUES = {rank: i for i, rank in enumerate(RANKS, 2)} class Card: def __init__(self, rank: str, suit: str): self.rank = rank.strip().upper() self.suit = suit.strip().capitalize() def __repr__(self): return f"{self.rank} of {self.suit}" def __eq__(self, other): return isinstance(other, Card) and self.rank == other.rank and self.suit == other.suit class Deck: def __init__(self): self.cards: List[Card] = [Card(rank, suit) for suit in SUITS for rank in RANKS] random.shuffle(self.cards) def deal_card(self) -> Card: return self.cards.pop(0) def deal_hand(self, num: int = 5) -> List[Card]: hand = self.cards[:num] del self.cards[:num] return hand class Player: def __init__(self, name: str, deck: Deck): self.name = name self.hand: List[Card] = deck.deal_hand() def show_hand(self): return '\n '.join(str(card) for card in self.hand) def replace_card(self, old_card: Card, new_card: Card) -> bool: for i, card in enumerate(self.hand): if card == old_card: self.hand[i] = new_card return True return False def hand_rank(self) -> Tuple[int, List[int]]: ranks = sorted([RANK_VALUES[card.rank] for card in self.hand], reverse=True) suits = [card.suit for card in self.hand] rank_counts = {r: ranks.count(r) for r in ranks} is_flush = len(set(suits)) == 1 is_straight = all(ranks[i] - 1 == ranks[i+1] for i in range(len(ranks)-1)) # Handle Ace-low straight if ranks == [14, 5, 4, 3, 2]: is_straight = True ranks = [5, 4, 3, 2, 1] if is_flush and ranks == [14, 13, 12, 11, 10]: return (9, ranks) # Royal Flush counts = sorted(rank_counts.values(), reverse=True) if is_straight and is_flush: return (8, ranks) # Straight Flush elif counts[0] == 4: return (7, ranks) # Four of a Kind elif counts[0] == 3 and counts[1] == 2: return (6, ranks) # Full House elif is_flush: return (5, ranks) # Flush elif is_straight: return (4, ranks) # Straight elif counts[0] == 3: return (3, ranks) # Three of a Kind elif counts[0] == 2 and counts[1] == 2: return (2, ranks) # Two Pair elif counts[0] == 2: return (1, ranks) # One Pair else: return (0, ranks) # High Card class Game: def __init__(self): self.deck = Deck() self.player1 = Player("Player 1", self.deck) self.player2 = Player("Player 2", self.deck) def prompt_card_replacement(self, player: Player): while True: try: num = int(input(f"{player.name}, how many cards do you want to pull? (0–3): ")) if 0 <= num <= 3: break else: print("Invalid number. Please choose between 0 and 3.") except ValueError: print("Invalid input. Please enter a number between 0 and 3.") replacements_done = 0 while replacements_done < num: print("\nYour current hand:\n", player.show_hand()) user_input = input("Enter a card to replace (e.g., A of Spades): ").strip() if ' of ' not in user_input: print("Invalid format. Use 'Rank of Suit'.") continue rank, suit = user_input.split(' of ', 1) old_card = Card(rank, suit) if old_card not in player.hand: print(f"{old_card} not found in your hand. Please try again.") continue new_card = self.deck.deal_card() if player.replace_card(old_card, new_card): print(f"Replaced {old_card} with {new_card}") replacements_done += 1 else: print("Replacement failed unexpectedly.") def play(self): print("Initial hands:") print("Player 1:\n", self.player1.show_hand()) print("Player 2:\n", self.player2.show_hand()) self.prompt_card_replacement(self.player1) self.prompt_card_replacement(self.player2) rank1 = self.player1.hand_rank() rank2 = self.player2.hand_rank() print("\nFinal hands:") print("Player 1:\n", self.player1.show_hand()) print("Player 2:\n", self.player2.show_hand()) if rank1 > rank2: print("Player 1 wins!", rank1) elif rank2 > rank1: print("Player 2 wins!", rank2) else: print("It's a tie!") if __name__ == "__main__": Game().play()