python/poker_class_version.py

146 lines
4.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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? (03): "))
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()