Yes
Yes

Reputation: 31

Compare high cards in poker program

I'm having troubles with comparing high cards in my poker program. I wanted to do it with suit symbols instead of letters, so I've complicate a simple program and transformed it to a "medium" level of programming. And yes, still needing answer

import random, time, json
from random import shuffle
from collections import Counter
from enum import Enum

class CardSuits(Enum):
    Hearts = "Hearts"
    Diamonds = "Diamonds"
    Clubs = "Clubs"
    Spades = "Spades"

class CardValues(Enum):
    Two = 2
    Three = 3
    Four = 4
    Five = 5
    Six = 6
    Seven = 7
    Eight = 8
    Nine = 9
    Ten = 10
    Jack = 11
    Queen = 12
    King = 13
    Ace = 14


class Card:

    _symbols = {"Hearts": "♥️", "Diamonds": "♦️", "Clubs": "♣️", "Spades": "♠"}

    _numbers = {2: "2",
                3: "3",
                4: "4",
                5: "5",
                6: "6",
                7: "7",
                8: "8",
                9: "9",
                10: "10",
                11: "J",
                12: "Q",
                13: "K",
                14: "A"}
    
    def __init__(self, suit: CardSuits, value: CardValues) -> None:
        self.suit = suit
        self.value = value

    def __str__(self) -> str:
        return f"{self._numbers[self.value.value]}{self._symbols[self.suit.name]}"

    def __repr__(self) -> str:
        return f"{self._numbers[self.value.value]}{self._symbols[self.suit.name]}"

#GAME START
def start():
    play = input("You wanna play? ")
    if play.lower() in ("yes", "sure", "yeah"):
        all_cards = [Card(suits, value) for suits in CardSuits for value in CardValues]
        shuffle(all_cards)
        unique_cards = set()
        while len(unique_cards) < 5:
            unique_cards.add(random.choice(all_cards))
        cards = list(unique_cards)
        print("Your cards are:", ", ".join(str(card) for card in cards))
        time.sleep(4)

    #OPPONENTS CARD CREATION
    # First opponent
    unique_cards = set()
    while len(unique_cards) < 5:
        unique_cards.add(random.choice(all_cards))
    first_opponent_cards = list(unique_cards)
    # Second
    unique_cards = set()
    while len(unique_cards) < 5:
        unique_cards.add(random.choice(all_cards))
        second_opponent_cards = list(unique_cards)
    #CHECKING PHASE
    def checking_phase(cards):
        High_Card, Pair, Two_Pair, Three_of_a_Kind, Straight, Flush, Full, Four_of_a_Kind, Straight_Flush, Royal_Flush = ("High Card", "Pair", "Two Pair", "Three of a Kind", "Straight", "Flush", "Full", "Four of a Kind", "Straight Flush", "Royal Flush")
        if is_royal_flush:
            return Royal_Flush
        #elif series for returning other combinations
        else:
            return High_Card

    user_hand = checking_phase(cards)
    first_opponent_hand = checking_phase(first_opponent_cards)
    second_opponent_hand = checking_phase(second_opponent_cards)
    
    #SCORE DASHBOARD
    players = [user_hand, first_opponent_hand, second_opponent_hand]
    scores = [0, 0, 0] if not scores else scores
    # Determina il giocatore con la combinazione più alta
    max_hand_index = max(range(len(players)), key=lambda i: players[i])
    # Incrementa il punteggio del giocatore con la combinazione più alta
    if user_hand == "High Card" and first_opponent_hand == "High Card" and second_opponent_hand == "High Card":
        cards_remove_cycle = 0
        user_high = max(card.value.value for card in cards)
        first_op_high = max(card.value.value for card in first_opponent_cards)
        second_op_high = max(card.value.value for card in second_opponent_cards)
        high_list = [user_high, first_op_high, second_op_high]
        #caso in cui ci siano due o più player con max identici
        if user_high == first_op_high or user_high == second_op_high or first_op_high == second_op_high:
            print("Eureka! it works")
            comparing_HC_cycle = 0
            for player in players:
                for card in cards:
                    user_copyli = cards[:]
                    first_copyli = first_opponent_cards[:]
                    second_copyli = second_opponent_cards[:]
                    high_copyli = [user_copyli, first_copyli, second_copyli]
                    # max_HC_value = max(high_copyli)
                    max_HC_value = max(max(card.value.value for card in hand) for hand in high_copyli)
                    # Filtra la lista high_copyli per rimuovere i giocatori senza la carta più alta
                    high_copyli = [hand for hand in high_copyli if max(card.value.value for card in hand) == max_HC_value]
                    
                    if user_high in user_copyli:
                        user_copyli.remove(user_high)
                    if first_op_high in first_copyli:
                        first_copyli.remove(first_op_high)
                    if second_op_high in second_copyli:
                        second_copyli.remove(second_op_high)

                    user_high = max(card.value.value for card in cards)
                    first_op_high = max(card.value.value for card in first_opponent_cards)
                    second_op_high = max(card.value.value for card in second_opponent_cards)
                    
                    comparing_HC_cycle += 1
                    if comparing_HC_cycle > 4:
                        winner_index = players.index(player)
                        scores[winner_index] += 1
                        print("arriva, ma non funzia")
                        break

            else: #caso in cui il max di ogni player sia diverso, quindi solo 1 vincitore
                high_card_winner = max(high_list)
                HC_winner_index = high_list.index(high_card_winner)
                scores[HC_winner_index] += 1                                      
        else:
            scores[max_hand_index] += 1
        winning_player = ["You", "First opponent", "Second opponent"]
        if winning_player[max_hand_index] == "You":
            print("You won!")
        else:
            print(f"{winning_player[max_hand_index]} won. May you'll be luckier next time")

        score_phrase = """
        SCORE:          User: {}   |   First opponent: {}   |   Second opponent: {}   """
        print(score_phrase.format(scores[0], scores[1], scores[2]))

I've improved my code with answer suggestions, but the problem is that every time the code works, it gives user the score, even if it has the lowest card. My idea was (in case of 2 or more players have the same max card) to create a copy-list of player hands and removing the equal cards (at the same time disqualifying a player if he has a lower high card), until the player with the highest card remains (unless 2 players have the same cards, in that case there would be a pair). To clarify, all the other combinations works, I'm having problems only with comparing high cards. Thank you in advance

Upvotes: 0

Views: 129

Answers (2)

Mark Tolonen
Mark Tolonen

Reputation: 178021

Use simple number values for the cards and suits and display then nicely with symbols.

Use functools.total_ordering decorator and define __eq__ and __lt__ for your class to enable all comparisons.

Minimal example:

import functools

@functools.total_ordering
class Card:

    _symsuit = '♥♦♣♠'
    _symvalue = '23456789TJQKA'

    def __init__(self, suit, value):
        self.suit = suit
        self.value = value

    def __repr__(self):
        return f'Card(suit={self.suit}, value={self.value})'

    def __str__(self):
        return f'{self._symvalue[self.value]}{self._symsuit[self.suit]}'

    def __lt__(self, other):
        return self.value < other.value  # ignores suit

    def __eq__(self, other):
        return self.value == other.value  # ignores suit

deck = [Card(suit, value) for suit in range(4) for value in range(13)]
print(deck)
a, b = deck[:2]
print(f'{a} <  {b} is {a < b}')
print(f'{a} >  {b} is {a > b}')
print(f'{a} <= {b} is {a <= b}')
print(f'{a} >= {b} is {a >= b}')
print(f'{a} == {b} is {a == b}')
b = deck[13]
print(f'{a} <  {b} is {a < b}')
print(f'{a} >  {b} is {a > b}')
print(f'{a} <= {b} is {a <= b}')
print(f'{a} >= {b} is {a >= b}')
print(f'{a} == {b} is {a == b}')

Output:

[Card(suit=0, value=0), Card(suit=0, value=1), Card(suit=0, value=2), Card(suit=0, value=3), Card(suit=0, value=4), Card(suit=0, value=5), Card(suit=0, value=6), Card(suit=0, value=7), Card(suit=0, value=8), Card(suit=0, value=9), Card(suit=0, value=10), Card(suit=0, value=11), Card(suit=0, value=12), Card(suit=1, value=0), Card(suit=1, value=1), Card(suit=1, value=2), Card(suit=1, value=3), Card(suit=1, value=4), Card(suit=1, value=5), Card(suit=1, value=6), Card(suit=1, value=7), Card(suit=1, value=8), Card(suit=1, value=9), Card(suit=1, value=10), Card(suit=1, value=11), Card(suit=1, value=12), Card(suit=2, value=0), Card(suit=2, value=1), Card(suit=2, value=2), Card(suit=2, value=3), Card(suit=2, value=4), Card(suit=2, value=5), Card(suit=2, value=6), Card(suit=2, value=7), Card(suit=2, value=8), Card(suit=2, value=9), Card(suit=2, value=10), Card(suit=2, value=11), Card(suit=2, value=12), Card(suit=3, value=0), Card(suit=3, value=1), Card(suit=3, value=2), Card(suit=3, value=3), Card(suit=3, value=4), Card(suit=3, value=5), Card(suit=3, value=6), Card(suit=3, value=7), Card(suit=3, value=8), Card(suit=3, value=9), Card(suit=3, value=10), Card(suit=3, value=11), Card(suit=3, value=12)]
2♥ <  3♥ is True
2♥ >  3♥ is False
2♥ <= 3♥ is True
2♥ >= 3♥ is False
2♥ == 3♥ is False
2♥ <  2♦ is False
2♥ >  2♦ is False
2♥ <= 2♦ is True
2♥ >= 2♦ is True
2♥ == 2♦ is True

Upvotes: 0

Ghorban M. Tavakoly
Ghorban M. Tavakoly

Reputation: 1249

Add __gt__ method to your Card class to support > operator.


class Card:

    def __gt__(self, other):
        '''return True or False'''
        ...

See documentation for more details.

Upvotes: 0

Related Questions