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

Implement Blackjack in Python with OOP

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

Problem

I feel the best way to learn is practice. I have written a simple Blackjack game in Python which supports multiple-players and functionality like Hit, Stand, Surrender, Split and Double_Down. I need some help to review my code, in order to remove any redundant code, simplify the implementation, and improve the code quality over all.

Please let me know your thoughts, any feedback is welcome.

```
import random

SUITS = ['Clubs', 'Spades', 'Hearts', 'Diamonds']
RANKS = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
MAX_PLAYERS = 8
MAX_BALANCE = 1000
chip_balance = 0

class Card(object):
def __init__(self, suit, rank):
self.suit = suit
self.rank = rank

if rank == 'A':
self.point = 11
elif rank in ['K', 'Q', 'J']:
self.point = 10
else:
self.point = int(rank)

self.hidden = False

def __str__(self):
if self.hidden:
return '[X]'
else:
return '[' + self.suit + ' ' + self.rank + ']'

def hide_card(self):
self.hidden = True

def reveal_card(self):
self.hidden = False

def is_ace(self):
return self.rank == 'A'

class Deck(object):
def __init__(self):
self.cards = [Card(suit, rank) for suit in SUITS for rank in RANKS]
self.shuffle()

def __str__(self):
cards_in_deck = ''
for card in self.cards:
cards_in_deck = cards_in_deck + str(card) + ' '
return cards_in_deck

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

def deal_card(self):
card = self.cards.pop(0)
return card

class Hand(object):
def __init__(self):
self.hand = []

def add_card(self, card):
self.hand.append(card)
return self.hand

def get_value(self):
aces = 0
value = 0
for card in self.hand:
if card.is_ace():
aces += 1
value += card.point

Solution

The code generally looks good.

The inheritance hierarchy is weird: Dealer is a Hand? I would rather say that a dealer has a hand. Player is a Dealer? That sounds backwards — rather, a dealer is a player.

The difference in naming convention between properties (e.g. isBust) and method calls (e.g. get_value()) is annoying. You should use the is_bust convention uniformly. I would expect card.is_ace to be a property, rather than card.is_ace().

For Deck.__str__(), you could write

def __str__(self):
    return ' '.join(str(card) for card in self.cards)


… which also gets rid of the extra space at the end of any non-empty deck.

Deck.deal_card() should just be return self.cards.pop(). Dealing from the start of the array requires every card to be shifted over — that's a lot of unnecessary copying.

For Hand.get_value(), you should probably use sum():

def get_value(self):
    value = sum(card.point for card in self.cards)
    aces = sum(card.is_ace for card in self.cards)
    while (value > 21) and aces:
        value -= 10
        aces -= 1
    return value


The function name report() suggests that it merely prints the outcome. It's a bit surprising that it does more: it also awards the winnings. Therefore, award_winnings() would be a better name.

Winning double your bet for a Blackjack is unusually generous. Customarily, you only earn 1.5× your bet.

Code Snippets

def __str__(self):
    return ' '.join(str(card) for card in self.cards)
def get_value(self):
    value = sum(card.point for card in self.cards)
    aces = sum(card.is_ace for card in self.cards)
    while (value > 21) and aces:
        value -= 10
        aces -= 1
    return value

Context

StackExchange Code Review Q#85751, answer score: 4

Revisions (0)

No revisions yet.