Obviously, here is the initial code for this blackjack game. and in order for me to feel confident in this game I need to have an error check to make sure that there are at least 7 cards per player. And I have to do this in the second part of code listed below (cards).

# Blackjack
# From 1 to 7 players compete against a dealer

import cards, games     

class BJ_Card(cards.Card):
    """ A Blackjack Card. """
    ACE_VALUE = 1
    
    def get_value(self):
        if self.is_face_up:
            value = BJ_Card.RANKS.index(self.rank) + 1
            if value > 10:
                value = 10
        else:
            value = None
        return value

    value = property(get_value)


class BJ_Deck(cards.Deck):
    """ A Blackjack Deck. """
    def populate(self):
        for suit in BJ_Card.SUITS: 
            for rank in BJ_Card.RANKS: 
                self.cards.append(BJ_Card(rank, suit))
    

class BJ_Hand(cards.Hand):
    """ A Blackjack Hand. """
    def __init__(self, name):
        super(BJ_Hand, self).__init__()
        self.name = name

    def __str__(self):
        rep = self.name + ":\t" + super(BJ_Hand, self).__str__()  
        if self.total:
            rep += "(" + str(self.total) + ")"        
        return rep
     
    def get_total(self):
        # if a card in the hand has value of None, then total is None
        for card in self.cards:
            if not card.value:
                return None
        
        # add up card values, treat each Ace as 1
        total = 0
        for card in self.cards:
              total += card.value

        # determine if hand contains an Ace
        contains_ace = False
        for card in self.cards:
            if card.value == BJ_Card.ACE_VALUE:
                contains_ace = True
                
        # if hand contains Ace and total is low enough, treat Ace as 11
        if contains_ace and total <= 11:
            # add only 10 since we've already added 1 for the Ace
            total += 10   
                
        return total

    total = property(get_total)

    def is_busted(self):
        return self.total > 21


class BJ_Player(BJ_Hand):
    """ A Blackjack Player. """
    def is_hitting(self):
        response = games.ask_yes_no("\n" + self.name + ", do you want a hit? (Y/N): ")
        return response == "y"

    def bust(self):
        print self.name, "busts."
        self.lose()

    def lose(self):
        print self.name, "loses."

    def win(self):
        print self.name, "wins."

    def push(self):
        print self.name, "pushes."

        
class BJ_Dealer(BJ_Hand):
    """ A Blackjack Dealer. """
    def is_hitting(self):
        return self.total < 17

    def bust(self):
        print self.name, "busts."

    def flip_first_card(self):
        first_card = self.cards[0]
        first_card.flip()


class BJ_Game(object):
    """ A Blackjack Game. """
    def __init__(self, names):      
        self.players = []
        for name in names:
            player = BJ_Player(name)
            self.players.append(player)

        self.dealer = BJ_Dealer("Dealer")

        self.deck = BJ_Deck()
        self.deck.populate()
        self.deck.shuffle()

    def get_still_playing(self):
        remaining = []
        for player in self.players:
            if not player.is_busted():
                remaining.append(player)
        return remaining

    # list of players still playing (not busted) this round
    still_playing = property(get_still_playing)

    def __additional_cards(self, player):
        while not player.is_busted() and player.is_hitting():
            self.deck.deal([player])
            print player
            if player.is_busted():
                player.bust()
           
    def play(self):
        # deal initial 2 cards to everyone
        self.deck.deal(self.players + [self.dealer], per_hand = 2)
        self.dealer.flip_first_card()    # hide dealer's first card
        for player in self.players:
            print player
        print self.dealer

        # deal additional cards to players
        for player in self.players:
            self.__additional_cards(player)

        self.dealer.flip_first_card()    # reveal dealer's first 

        if not self.still_playing:
            # since all players have busted, just show the dealer's hand
            print self.dealer
        else:
            # deal additional cards to dealer
            print self.dealer
            self.__additional_cards(self.dealer)

            if self.dealer.is_busted():
                # everyone still playing wins
                for player in self.still_playing:
                    player.win()                    
            else:
                # compare each player still playing to dealer
                for player in self.still_playing:
                    if player.total > self.dealer.total:
                        player.win()
                    elif player.total < self.dealer.total:
                        player.lose()
                    else:
                        player.push()

        # remove everyone's cards
        for player in self.players:
            player.clear()
        self.dealer.clear()
        

def main():
    print "\t\tWelcome to Blackjack!\n"
    
    names = []
    number = games.ask_number("How many players? (1 - 7): ", low = 1, high = 8)
    for i in range(number):
        name = raw_input("Enter player name: ")
        names.append(name)
    print
        
    game = BJ_Game(names)

    again = None
    while again != "n":
        game.play()
        again = games.ask_yes_no("\nDo you want to play again?(Y/N): ")


main()
raw_input("\n\nPress the enter key to exit.")

Second part of code is below.

# Cards Module
# Basic classes for a game with playing cards

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 rounds 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.")

Should I write something like:

def check_cards(self, hands):
    if self.Card == 7:
        ##something to make the code keep going
    else:
        ##clear deck
        ##repopulate
        ##reshuffle

or should I implement that sort of code in the def deal?

I think black Jack is dealt normally from shoe with many decks shuffled together. Then the cards do not finish so often.

I think fresh deck should be automatically shuffled in Deck's __init__. Number of cards should be possible to check by len(myhand) but better would be to have deal method which raises exception if cards finish and you can replace the deck with new one in your exception handler.

Also looks for me that something is missing, this games module is nowhere around.

Must say that I do not understand you objects Deck inherting from Hand, but I am not expert in OO as I learned programming before it became fashion.

This property stuff is in my opinion more cleanly done by using @property decorator.

This seems to give the size of your deck in current implementation in main():

while again != "n":
        game.play()
        again = games.ask_yes_no("\nDo you want to play again?(Y/N): ")
        print('%i cards in deck' % len(game.deck.cards))

Edited 5 Years Ago by pyTony: n/a

The "self.deck.deal([player])" would be a good place to check except self.deck, self.deck = BJ_Deck(), does not have a deal() function. Generally you want to check every time before you deal or hit as you will also catch it if the burn card or the hit card reduce the deck to less than an acceptable number of cards.

Edited 5 Years Ago by woooee: n/a

This article has been dead for over six months. Start a new discussion instead.