Projects/5-Card_Stud_Poker.py
2025-09-18 11:54:21 -07:00

220 lines
6.5 KiB
Python
Raw 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.

# 5-Card_Stud_Poker.py
import random
from collections import Counter
from hand_utils import evaluate_hand, Tuple, List, Card, SUITS, RANKS
rank_counts = Counter()
@staticmethod
def setup_players() -> List["Player"]:
num_players = int(input("Enter number of players (25): "))
if not 2 <= num_players <= 5:
raise ValueError("Must be between 2 and 5 players.")
return [Player(f"Player {i+1}") for i in range(num_players)]
@staticmethod
def deal_round(deck, players, round_num):
print(f"\n--- Round {round_num} ---")
for player in players:
if not player.folded:
player.receive_card(deck.deal_card())
print(player.show_hand())
@staticmethod
def determine_winner(players):
best_score = (-1, -1)
winner = None
for player in players:
if player.folded:
continue
full_hand = [player.hole_card] + player.face_up_cards
score = evaluate_hand(full_hand)
print(f"{player.name} hand score: {score}")
if score > best_score:
best_score = score
winner = player
if winner:
print(f"\n🏆 {winner.name} wins with: {winner.reveal_full_hand()}")
def deal_initial_cards(deck, players):
for player in players:
player.receive_hole_card(deck.deal_card()) # face-down
player.receive_face_up_card(deck.deal_card()) # first face-up
@staticmethod
def play():
deck = Deck()
players = setup_players()
deal_initial_cards(deck, players)
for round_num in range(2, 5): # 3 more face-up cards
# deal_round(deck, players, round_num)
print(f"\n--- Round {round_num} ---")
for player in players:
if not player.folded:
player.receive_face_up_card(deck.deal_card())
print(player.show_hand())
print("\n--- Showdown ---")
for player in players:
print(player.reveal_full_hand())
def betting_round(players: list, current_bet: int, pot: int) -> tuple[int, int]:
print(f"\nCurrent bet: {current_bet}")
for player in players:
if player.folded:
continue
print(f"\n{player.name}'s turn")
print(f"Visible cards: {' '.join(str(card) for card in player.face_up_cards)}")
decision = input("Choose action (call, raise, fold): ").strip().lower()
if decision == 'fold':
player.folded = True
print(f"{player.name} folds.")
elif decision == 'call':
pot += current_bet
print(f"{player.name} calls {current_bet}.")
elif decision == 'raise':
try:
raise_amount = int(input("Enter raise amount: "))
current_bet += raise_amount
pot += current_bet
print(f"{player.name} raises to {current_bet}.")
except ValueError:
print("Invalid raise amount. Treating as call.")
pot += current_bet
else:
print("Invalid input. Treating as fold.")
player.folded = True
return current_bet, pot
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):
self.name = name
self.hold_card: Card = None
self.face_up_cards: List[Card] = []
self.hand: List[Card] = []
self.folded = False
def receive_hole_card(self, card):
self.hole_card = card
def receive_face_up_card(self, card):
self.face_up_cards.append(card)
def show_hand(self):
return f"{self.name}: {' '.join(str(card) for card in self.face_up_cards)}"
def reveal_full_hand(self):
return f"{self.name}: {str(self.hole_card)} " + ' '.join(str(card) for card in self.face_up_cards)
def hand_rank(self) -> Tuple[int, List[int]]:
return evaluate_hand(self.hand)
def make_decision(self):
high_ranks = {'J', 'Q', 'K', 'A'}
visible_ranks = [card.rank for card in self.face_up_cards]
if any(rank in high_ranks for rank in visible_ranks):
return 'call'
else:
return 'fold'
def hand_rank_name(rank: int) -> str:
names = {
9: "Royal Flush",
8: "Straight Flush",
7: "Four of a Kind",
6: "Full House",
5: "Flush",
4: "Straight",
3: "Three of a Kind",
2: "Two Pair",
1: "One Pair",
0: "High Card"
}
return names.get(rank, "Unknown Hand")
class Game:
def __init__(self):
self.deck = Deck()
self.players = setup_players()
for player in self.players:
player.hand = self.deck.deal_hand()
def deal_initial_cards(deck, players):
for player in players:
player.receive_card(deck.deal_card()) # hole card
player.receive_card(deck.deal_card()) # first face-up card
def deal_round(deck, players, round_num):
print(f"\n--- Round {round_num} ---")
for player in players:
if not player.folded:
player.receive_card(deck.deal_card())
print(player.show_hand())
def main():
print("Welcome to 5-Card Stud Poker!")
deck = Deck()
players = setup_players()
deal_initial_cards(deck, players)
current_bet = 10
pot = 0
for round_num in range(2, 5):
print(f"\n--- Round {round_num} ---")
for player in players:
if not player.folded:
player.receive_face_up_card(deck.deal_card())
print(player.show_hand())
current_bet, pot = betting_round(players=players, current_bet=current_bet, pot=pot)
print("\n--- Showdown ---")
for player in players:
if not player.folded:
print(player.reveal_full_hand())
print(f"\nTotal pot: {pot}")
# Simulate betting round
current_bet, pot = betting_round(players, current_bet, pot)
pot += current_bet * sum(1 for p in players if not p.folded)
# Showdown
print("\n--- Showdown ---")
for player in players:
if not player.folded:
print(player.reveal_full_hand())
determine_winner(players)
print(f"\nTotal pot: {pot}")
if __name__ == "__main__":
main()