HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Blackjack card game

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
gamecardblackjack

Problem

It's been a long while since I've done any Python programming so I thought I'd start with a simple Blackjack game. Any comments on how I can make this more readable? Use more methods perhaps?

```
from sys import exit
from random import randint

class Game(object):

def __init__(self, start):
self.quips = [
" you kinda suck at this.",
"don't quit your day job.",
"Such a loser."
]
self.start = start

#main method to start playing
def play(self):
next = self.start
action = "y"

#start playing
while True:
print "\n-------"
print "Beginning blkjk"
print "Dealing.. \n"

#deal user's cards
unum1 = randint(1,10)
unum2 = randint(1,10)
utotal = unum1 + unum2
print "Ur cards are: %d & %d totalling %d \n" % (unum1, unum2,utotal)

#hit until user says stop
while action == "y":
action = raw_input("Hit? > ")
if action == "y":
utotal = utotal + self.hit()
print "ur new total is %d" % utotal

print "Ur total is %d " % utotal

#deal dealer's cards
dnum1 = randint(1,10)
dnum2 = randint(1,10)
dtotal = dnum1 + dnum2
print "Dealer's cards are %d & %d totalling %d \n" % (dnum1, dnum2, dtotal)

#dealer keeps hitting until close/more than 21
while dtotal dtotal:
print "you win!"
exit(1)
else:
print "dealer wins"
self.death()
else:
print "Dealer busts, u win!"
exit(1)

def death(self):
print self.quips[randint(0, len(self.quips)-1)]
exit(1)

def hit(self):
n

Solution

I don't think that having a huge "Game" class that contains the flow of the entire game is the way you want to do it. Why don't you break the game into some manageable chunks? Here's what I came up with after a little thinking:

import random
DEFAULT_CHIPS = 20

class Card(object):
    card_to_name = {1:"Ace", 2:"Two", 3:"Three", 4:"Four", 5:"Five", 6:"Six", 7:"Seven",
                    8:"Eight", 9:"Nine", 10:"Ten", 11:"Jack", 12:"Queen", 13:"King"}

    def __init__(self, value, suit):
        self.name = self.card_to_name[value]
        self.suit = suit
        self.title = "%s of %s" % (self.name, self.suit)
        self.score = min(value, 10)

    def __repr__(self):
        return self.title

class Hand(object):
    def __init__(self, cards):
        self.hand = cards

    def get_scores(self):
        num_aces = sum(card.name == "Ace" for card in self.hand)
        score = sum(card.score for card in self.hand)
        return [score + i*10 for i in range(num_aces+1)]

    def possible_scores(self):
            return [s for s in self.get_scores() if s <= 21]

    def __repr__(self):
        return str(self.hand)

class Deck(object):
    unshuffled_deck = [Card(card, suit) for card in range(1, 14) for suit in ["Clubs", "Diamonds", "Hearts", "Spades"]]
    def __init__(self, num_decks=1):
        self.deck = self.unshuffled_deck * num_decks
        random.shuffle(self.deck)

    def deal_card(self):
        return self.deck.pop()

    def deal_hand(self):
        return Hand([self.deal_card(), self.deal_card()])

class Player(object):
    def __init__(self, name="Player 1", chips=DEFAULT_CHIPS):
        self.name = name
        self.chips = chips
        self.current_bet = 0

    def new_hand(self, hand):
        self.hand = hand

    def hit(self, card):
        self.hand.hand.append(card)

    def is_busted(self):
        return len(self.hand.possible_scores()) == 0

    def scores(self):
            return self.hand.get_scores() if self.is_busted() else self.hand.possible_scores()

    def __repr__(self):
        player_str = self.name + "(BUSTED)" if self.is_busted() else self.name
        return "Player: {}\nChips: {}\nCurrent Bet: {}\nCards: {}\nScore: {}".format(
            player_str, self.chips, self.current_bet, self.hand, self.scores())

if __name__ == "__main__":
    d = Deck()
    print d.deck
    h = d.deal_hand()
    p = Player()
    p.new_hand(h)
    print p
    p.hit(d.deal_card())
    print p


Here is some test output:


[Two of Spades, Two of Diamonds, Three of Clubs, Ten of Hearts, Ace of

Diamonds, Eight of Diamonds, Seven of Diamonds, King of Hearts, Seven

of Hearts, Queen of Diamonds, Six of Clubs, Nine of Diamonds, Seven of

Spades, Four of Spades, Four of Diamonds, Ten of Clubs, Four of Clubs,

Jack of Hearts, Ace of Clubs, Six of Spades, Eight of Spades, Seven of

Clubs, Eight of Hearts, Three of Diamonds, Jack of Clubs, King of

Diamonds, Five of Clubs, King of Clubs, Ace of Spades, King of Spades,

Six of Diamonds, Ten of Diamonds, Queen of Clubs, Two of Hearts, Eight

of Clubs, Nine of Hearts, Ace of Hearts, Five of Spades, Jack of

Diamonds, Nine of Spades, Four of Hearts, Six of Hearts, Two of Clubs,

Three of Spades, Jack of Spades, Five of Diamonds, Three of Hearts, Ten

of Spades, Five of Hearts, Queen of Hearts, Nine of Clubs, Queen of

Spades]

Player: Player 1

Chips: 20

Current Bet: 0

Cards: [Queen of Spades, Nine of Clubs]

Score: [19]

Player: Player 1(BUSTED)

Chips: 20

Current Bet: 0

Cards: [Queen of Spades, Nine of Clubs, Queen of Hearts]

Score: [29]

From there, implementing the game in a clean fashion wouldn't be too tough.

Code Snippets

import random
DEFAULT_CHIPS = 20

class Card(object):
    card_to_name = {1:"Ace", 2:"Two", 3:"Three", 4:"Four", 5:"Five", 6:"Six", 7:"Seven",
                    8:"Eight", 9:"Nine", 10:"Ten", 11:"Jack", 12:"Queen", 13:"King"}

    def __init__(self, value, suit):
        self.name = self.card_to_name[value]
        self.suit = suit
        self.title = "%s of %s" % (self.name, self.suit)
        self.score = min(value, 10)

    def __repr__(self):
        return self.title

class Hand(object):
    def __init__(self, cards):
        self.hand = cards

    def get_scores(self):
        num_aces = sum(card.name == "Ace" for card in self.hand)
        score = sum(card.score for card in self.hand)
        return [score + i*10 for i in range(num_aces+1)]

    def possible_scores(self):
            return [s for s in self.get_scores() if s <= 21]

    def __repr__(self):
        return str(self.hand)

class Deck(object):
    unshuffled_deck = [Card(card, suit) for card in range(1, 14) for suit in ["Clubs", "Diamonds", "Hearts", "Spades"]]
    def __init__(self, num_decks=1):
        self.deck = self.unshuffled_deck * num_decks
        random.shuffle(self.deck)

    def deal_card(self):
        return self.deck.pop()

    def deal_hand(self):
        return Hand([self.deal_card(), self.deal_card()])

class Player(object):
    def __init__(self, name="Player 1", chips=DEFAULT_CHIPS):
        self.name = name
        self.chips = chips
        self.current_bet = 0

    def new_hand(self, hand):
        self.hand = hand

    def hit(self, card):
        self.hand.hand.append(card)

    def is_busted(self):
        return len(self.hand.possible_scores()) == 0

    def scores(self):
            return self.hand.get_scores() if self.is_busted() else self.hand.possible_scores()

    def __repr__(self):
        player_str = self.name + "(BUSTED)" if self.is_busted() else self.name
        return "Player: {}\nChips: {}\nCurrent Bet: {}\nCards: {}\nScore: {}".format(
            player_str, self.chips, self.current_bet, self.hand, self.scores())

if __name__ == "__main__":
    d = Deck()
    print d.deck
    h = d.deal_hand()
    p = Player()
    p.new_hand(h)
    print p
    p.hit(d.deal_card())
    print p

Context

StackExchange Code Review Q#11972, answer score: 6

Revisions (0)

No revisions yet.