0

I have a program (blackjack.py) and it accesses another program's (cards.py and games.py) within its code. Most of this is from a book, so I'm having trouble understanding how it works.

Heres the code for cards.py:

class Card(object):
    """ A playing card. """
    RANKS = ["A", "2", "3", "4", "5", "6", "7",
             "8", "9", "10", "J", "Q", "K"]
    SUITS = ["c", "d", "h", "s"]
    def __init__(self, rank, suit, face_up = True):
        self.rank = rank
        self.suit = suit
        self.is_face_up = face_up

    def __str__(self):
        if self.is_face_up:
            rep = self.rank + self.suit
        else:
            rep = "XX"
        return rep

    def flip(self):
        self.is_face_up = not self.is_face_up


class Hand(object):
    """ A Hand of playing cards. """
    def __init__(self):
        self.cards = []

    def __str__(self):
        if self.cards:
            rep = ""
            for card in self.cards:
                rep += str(card) + "\t"
        else:
            rep = "<empty>"
        return rep

    def clear(self):
        self.cards = []

    def add(self, card):
        self.cards.append(card)

    def give(self, card, other_hand):
        self.cards.remove(card)
        other_hand.add(card)


class Deck(Hand):
    """ A deck of playing cards. """
    def populate(self):
        for suit in Card.SUITS:
            for rank in Card.RANKS:
                self.add(Card(rank, suit))

    def shuffle(self):
        import random
        random.shuffle(self.cards)

    def deal(self, hands, per_hand = 1):
        for round in range(per_hand):
            for hand in hands:
                if self.cards:
                    top_card = self.cards[0]
                    self.give(top_card, hand)
                else:
                    print "Can't continue deal. Out of cards!"

if __name__ == "__main__":
    print "This is a module with classes for playing cards."
    raw_input("\n\nPress the enter key to exit.")

I'm writing an error check for the blackjack.py and I need to gather the number of cards that have been used so far. I think I can do that by accessing the number of values in cards[]. The problem is, I am not sure on how to do that.

This is all in theory though. I will include the `blackjack.py' code as well, so you all can see what I am trying to do, and help me determine if my logic is flawed.

blackjack.py code

Any and all input is appreciated.

1 Answer 1

1

While I'm not entirely clear on your intended structure here, you have a couple of options.

First, in order to use any functions or classes from cards.py in your blackjack.py module, you can use the import statement to import them. There are two styles of doing this:

# blackjack.py
import cards

Would give you access to everything in the cards module, and you'd call each function/class by prefacing it with cards.<name>. So, if you wanted to initialize an instance of the Deck class,

# blackjack.py
import cards
mydeck = cards.Deck()

The other way is the from <X> import <Y>, which gives you access to the functions and classes without having to add the prefix. Example:

# blackjack.py
from cards import Deck  # or, to import everything, "from cards import *"
mydeck = Deck()

Either of these methods would give you an instance of the cards.Deck class.

Option 0

You can already tell this within your Deck class, since it subclasses from Hand, so every time you give a card it's taking out out of the Deck's cards attribute. Thus, the number of cards given out would simply be:

class Deck(Hand):
    # ...
    def number_cards_used(self):
         return 52 - len(self.cards)

Alternatively, if you can't edit cards.py, you can simply get the number of cards left from your given Deck by:

# blackjack.py
def get_number_cards_used_from_deck(deck):
    return 52 - len(deck.cards)

In use:

# blackjack.py
import cards
mydeck = cards.Deck()
# ...
# Do other operations with deck
# ...
cards_used = get_number_cards_used_from_deck(mydeck)

Option 1

If you can isolate all of and only those hands being played simultaneously, you can implement a method card_count:

class Hand(object):
   # ...
   # other code
   # ....

   def card_count(self):
       return len(self.cards)

Then, if you have a list of all the hands, for example, you could do something like:

sum(map(lambda h: h.card_count(), list_of_hands))

Option 2

Within your Deck class, since it subclasses Hand, you could simply keep another running list of the cards that have been given out that would often be refreshed. This would look like:

class Deck(Hand):
    # ...
    # other code
    # ...

    def __init__(self):
        self.populate()
        self.used_cards = []

    def give(self, card, other_hand):
        self.used_cards.append(card)
        super(Deck, self).give(card, other_hand)

    def number_cards_used(self):
        return len(self.used_cards)

There are other methods, of course.

Sign up to request clarification or add additional context in comments.

16 Comments

Is there anyway of doing this without adding to cards.py? I thought of something similar as well. I think that's what I am supposed to do anyway. I was asking how to use what I have in cards.py and blackjack.py to gather how many cards were left / in use. I have no idea how to access the cards.py file, and thought that by accessing it, I could somehow get the number of cards left. Can I?
I'm not sure what you mean by "accessing" cards.py. You don't have to edit cards.py to use option 0--given a Deck() initialized in variable mydeck, you could at any time do 52 - len(mydeck.cards) to find out how many cards were used. IS that what you mean?
Well, that means that myDeck.cards right now has no cards in it at all. That's because when you're just doing myDeck = cards.Deck(), the Deck class starts of with self.cards = []. You have to do myDeck = cards.Deck(), and then call the method myDeck.populate() in order to actually populate myDeck.cards with all of the cards. If you do that, and then try calling get_num_cards(myDeck), you'll probably find it returns 0.
It won't. When you instantiate a class, the __init__ method is called upon instantiation, but the Deck class you've provided in cards.py does not have an __init__ method. If you look at Option 2 that I provided, you'll see that I created an __init__ method for Deck that calls self.populate(), so that upon creating any Deck, Deck.cards would automatically be populated. In the code you provided above, it won't be.
Okay, well looking at your BJ_Game code, it does call self.deck.populate, so it should populate then. You shouldn't add numCards = len(self.deck) but you need to add numCards = len(self.deck.cards). Alternatively, you could add somewhere in one of the deck classes def __len__(self): return len(self.cards) or something along those lines.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.