1

Im trying to make a poker game with in python using pygame and OOP. I previously made a text based blackjack game from a udemy course and im trying to use some of the same principles to create my deck but its not working. The problem I have is I want to create 52 card objects and I want each card object to have three attributes (suit, rank, and a png file).

class Card:

    def __init__(self, suit, rank, pic):

        self.suit = suit
        self.pic = pic
        self.rank = rank


class Deck:

    def __init__(self):

        self.deck_comp = []

    def create_deck(self):

        for suit in suits:
            for rank in ranks:
                for pic in deck:

                    self.deck_comp.append(Card(suit, rank, pic))

I have a feeling the three for loops are the problem. In the text based blackjack game the card only needed to have two attributes. For this game I need the card objects to have a picture and a value and suit so I can display them and compare them.

suit is a list of the four suit strings Rank is a list of card names as strings and pic is a list of 52 .png files (one for each card in the deck)

Alec
  • 8,529
  • 8
  • 37
  • 63
nat643
  • 19
  • 2
  • Welcome to StackOverflow. Could you tell us what the problem is? (You can edit your question and add the Python errors you are seeing.) – rajah9 May 24 '19 at 13:04
  • What is `deck`? I assume, however, that there is a one-to-one mapping of suit/rank pairs to pics, so you probably want something like `for suit, rank in product(suits, ranks): self.deck_comp.append(Card(suit, rank, deck[(suit, rank)]))` rather than iterating over *every* pic for every card. – chepner May 24 '19 at 13:22
  • Yes, you certainly don't want to loop over pics, just suit and rank, assigning the one right pic to each card. Presumably, you can name the picture files something like "card_s_8.png", etc, so that you can assemble the filename from rank and suit. – Lee Daniel Crocker May 24 '19 at 17:40

3 Answers3

2

Would it not be wiser to hold all the png names in a dictionary, and assign an image in the Card class?

class Card:
    def __init__(self, value, suit):
        self.value = value
        self.suit = suit
        self.img = png_images[f'{value}{suit}']

class Deck:
        def __init__(self, shuffle_cards=True):
        self.cards = []
        self.shuffle_cards = shuffle_cards
        self.create()

    def create(self):
        for _ in range(number_of_decks):
            for val in (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14):
                for suit in ("Hearts", "Spades", "Clubs", "Diamonds"):
                    self.cards.append(Card(val, suit))

        if self.shuffle_cards:
            shuffle(self.cards)
Alec
  • 8,529
  • 8
  • 37
  • 63
  • No problem. If my answer helped, would you mind accepting it? – Alec May 24 '19 at 16:06
  • Yes, this is the right approach. I also like that card values are numbers rather than strings. Suits should be as well, but that's less of a issue. – Lee Daniel Crocker May 24 '19 at 17:44
  • Suits can be strings because they aren’t directly compared. In poker, the only reason to compare suit is to detect 5 of the same suit – Alec May 24 '19 at 17:46
  • Agreed, but then there's games like bridge. And even in poker there's things like low-card bring-in for stud, which does compare suits. – Lee Daniel Crocker May 24 '19 at 20:08
2

Basing on the example from one of the books:

import collections

Card = collections.namedtuple('Card', ['rank', 'suit'])

class Deck:
    ranks = [str(n) for n in range(2, 11)] + ['JQKA']
    suits = ['spades', 'diamonds', 'clubs', 'hearts']
    #  dictionary of dictionaries which maps ranks and suits to the picture
    pic_mapping = {
                    'spades': {
                                '2': 'spades2',
                                '3': 'spades3'
                                ...
                              },
                    'hearts': {
                                '2': 'hearts2',
                                '3': 'hearts3'
                                ...
                              },  


    def __init__(self):
        self._cards = [Card(rank, suit, pic_mapping[suit][rank]) for suit in self.suits
                                        for rank in self.ranks]

Note that lists may become tuples or can be built using generators. Lists are just used for better readability. In addition you can overload __len__ and __getitem__ to support operations such as:

  • indexing [i]
  • random.choice(collection)
  • slicing
  • iterating
  • reversed(collection)

Instead of dict mapping, you can use images naming convention to follow this pattern f'{suit}{rank}' and dynamically add it to the Card object.

Lee Daniel Crocker
  • 12,927
  • 3
  • 29
  • 55
maslak
  • 1,115
  • 3
  • 8
  • 22
0

It's been a while since I've done something like this, but you could create a pickle dictionary, for each suit maybe.

Have a look at this: How can I use pickle to save a dict?

And creating TRIES: How to create a TRIE in Python

Hope it helps :)