ООП карт и колод Python

#python-3.x #string #class #oop #playing-cards

#python-3.x #строка #класс #ооп #игральные карты

Вопрос:

Я пытаюсь написать программу, которая имеет:

функция, которая создает колоду карт, 52 по умолчанию или только 13, когда указана масть.

И

функция, которая удаляет первые карты card_count из колоды, возвращает их в виде списка и возвращает соответствующую ошибку, когда закончились карты.

Ожидаемые результаты ниже.

 >>> deck2 = Deck('♠')
>>> deck2.shuffle_deck()
>>> print(deck2.cards)
[A of ♠, 10 of ♠, 3 of ♠, 7 of ♠, 5 of ♠, 4 of ♠, 8 of ♠, J of ♠, 9 of ♠, Q of ♠, 6 of ♠, 2 of ♠, K of ♠]

>>> deck2.deal_card(7)
[A of ♠, 10 of ♠, 3 of ♠, 7 of ♠, 5 of ♠, 4 of ♠, 8 of ♠]

>>> deck2.deal_card(7)
Cannot deal 7 cards. The deck only has 6 cards left!
  

Моя проблема в том, что я возвращаю пустой список каждый раз, когда запускаю свой код. Я думаю, что у меня правильно настроен первый класс (PlayingCard) и необязательный аргумент для масти. Однако я не совсем уверен, как реализовать функцию deal или почему мой список возвращается пустым. Я упускаю что-то маленькое?

 import random

class PlayingCard():
    def __init__(self, rank, suit):
        acc_suit = ("♠", "♥", "♦", "♣")
        acc_rank = (2, 3, 4, 5, 6, 7, 8, 9, 10, "J", "Q", "K", "A")
        assert rank in acc_rank, "Not a valid rank for a playing card."
        assert suit in acc_suit, "Not a valid suit for a playing card."
        self.suit = suit
        self.rank = rank
    
    def __repr__(self):
        return self.rank   ' of '   self.suit

class Deck():
    
    def __init__(self, *suit):
        acc_suit = ("♠", "♥", "♦", "♣")
        self.cards = []
        if suit == None:
            for suit in range(4):
                for rank in range (1,14):
                    card = PlayingCard(rank, suit)
                    self.cards.append(card)
        if suit in acc_suit:
            for rank in range (1,14):
                card = PlayingCard(rank, suit)
                self.cards.append(card)
            

    def shuffle_deck(self):
        random.shuffle(self.cards)
    
    def deal_card(self):
        return self.cards.pop(0)
    
    
    def __str__(self):
        res = []
        for card in self.cards:
            res.append(str(card))
        return 'n'.join(res)
  

Ответ №1:

Причина, по которой ваш список пуст, заключается в том, что вы никогда не создаете колоду для начала, если предоставляете масть. Вызов

 deck2 = Deck('♠')
  

приведет к suit = ('♠',) 1-кортеж (содержащий 1 строку), поэтому он никогда не будет statistify if suit in acc_suit: => self.deck пуст.


Есть много других ошибок, чтобы сделать ваш код работоспособным — указано во встроенных комментариях:

 import random

class PlayingCard():
    def __init__(self, rank, suit):
        # you try to create cards by range(2,14) but you assert that suit must
        # be 2 to 10 or "J"-"A" for picture cards
        # also: range(2,14) is [2..13] only so you miss a card
        r = {11:"J",12:"Q",13:"K",14:"A"}   
        rank = r.get(rank,rank) # translate 10 to 14 to "JQMA"

        acc_suit = ("♠", "♥", "♦", "♣")
        acc_rank = (2, 3, 4, 5, 6, 7, 8, 9, 10, "J", "Q", "K", "A")
        assert rank in acc_rank, "Not a valid rank for a playing card."
        assert suit in acc_suit, "Not a valid suit for a playing card."
        self.suit = suit
        self.rank = rank
    
    def __repr__(self):
        # can not add a string to an integer (rank is an int for 2-10 !)
        return f"{self.rank} of {self.suit}"
  

и ваш класс колоды:

 class Deck():
    
    # change this to a named param with default so you need to supply suit=' '       
    # omit the ,* if you do not like to force suit=" " when calling this
    def __init__(self, *, suit = None):
        acc_suit = ("♠", "♥", "♦", "♣")
        self.cards = []
        if not suit:
            for suit in range(4):
                for rank in range (1,14):
                    card = PlayingCard(rank, suit)
                    self.cards.append(card)
        if suit in acc_suit:
            for rank in range (2,15):
                card = PlayingCard(rank, suit)
                self.cards.append(card)

    def shuffle_deck(self):
        random.shuffle(self.cards)
    
    # this function does not accept parameters like you posted its usage
    def deal_card(self, amount = 1):
        # always returns a list of cards, even if you only request one
        rv, self.cards = self.cards[:amount], self.cards[amount:]
        # this does NOT do the evaluation of enough cards are left, do it yourself:
        #  if len(rv) != amount: raise whatever
        return rv

    def __str__(self):
        return 'n'.join(str(c) for c in self.cards)
  

Тест:

 deck2 = Deck(suit = "♠")
print(deck2.cards)
deck2.shuffle_deck()
print(deck2.cards) 
print(deck2.deal_card(7))
print(deck2.deal_card(7))
  

Вывод:

 # orignal
[2 of ♠, 3 of ♠, 4 of ♠, 5 of ♠, 6 of ♠, 7 of ♠, 8 of ♠, 9 of ♠, 10 of ♠, 
 J of ♠, Q of ♠, K of ♠, A of ♠]
# shuffeled 
[3 of ♠, 5 of ♠, 10 of ♠, 8 of ♠, A of ♠, 7 of ♠, 6 of ♠, 4 of ♠, J of ♠, 
 Q of ♠, 9 of ♠, 2 of ♠, K of ♠]
# first 7
[3 of ♠, 5 of ♠, 10 of ♠, 8 of ♠, A of ♠, 7 of ♠, 6 of ♠]
# next 7 (only 6 remain)
[4 of ♠, J of ♠, Q of ♠, 9 of ♠, 2 of ♠, K of ♠]
  

Комментарии:

1. Возвращаюсь теперь, когда у меня достаточно очков для голосования. Спасибо!