n1c9
n1c9

Reputation: 2687

Having troubles with OOP-style Blackjack sim - AttributeError: 'Deck' object has no attribute 'fulldeck'

I'm trying to learn the principles of OOP through creating a Blackjack game that someone can play through a cli.

I've successfully set up a full deck of 52 cards with the proper number per suit, but I'm having trouble getting a player's hand.

Code I've written already:

import random

class Deck:

    def makeCards(self):
        self.suits = ['Clubs', 'Diamonds', 'Spades', 'Hearts']
        self.rank = ['2','3','4','5','6','7','8','9','10','J','Q','K','A']
        for suit in self.suits:
            for rank in self.rank:
                self.fulldeck = (suit, rank)
                self.fulldeck = list(self.fulldeck)
                return(self.fulldeck)

    def playerHand(self):
        self.cardone = random.choice(self.fulldeck)
        self.cardtwo = random.choice(self.fulldeck)
        print(self.cardone, self.cardtwo)

Deck().makeCards()
Deck().playerHand()

I'd expect this to output 2 random cards from the cards defined in self.fulldeck, but instead it gives me

AttributeError: 'Deck' object has no attribute 'fulldeck'

I don't get why, as I've defined self.fulldeck in the makeCards function.

Upvotes: 3

Views: 455

Answers (1)

TigerhawkT3
TigerhawkT3

Reputation: 49330

The main part of your issue is that you are calling methods on two separate instances:

Deck().makeCards() # create a Deck instance, call makeCards on it, and discard it
Deck().playerHand() # create a new Deck instance, call playerHand on it, and discard it

Save a reference to one instance and then reuse it:

a = Deck()
a.makeCards()
a.playerHand()

I also suspect you will have a problem here:

for suit in self.suits:
    for rank in self.rank:
        self.fulldeck = (suit, rank)
        self.fulldeck = list(self.fulldeck)
        return(self.fulldeck)

You're iterating through a nested loop, but on every iteration you're reassigning a brand-new self.fulldeck, so only the last one will remain. However, the first iteration is the last one, because you return on it. When you called this function, you didn't even save it - there's no need to return here at all.

You may want something like this instead:

self.fulldeck = []
for suit in self.suits:
    for rank in self.rank:
        self.fulldeck.append([suit, rank])

You can also refine and fix playerHand as follows:

def playerHand(self):
    return random.sample(self.fulldeck, 2)

Your current version chooses a random card twice, with replacement. The card you choose with random.choice is not removed from the deck, so you could get the same card twice. Using random.sample will return two random cards that are guaranteed not to be the same card. You can do whatever you like with these cards, such as print them (print(a.playerHand())).

Upvotes: 4

Related Questions