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

OO Blackjack game design

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

Problem

I have set up card, deck, hand, player, dealer, and game classes. The game class is there to keep a lot of the logic out of the interface (main.py). Let me know any thoughts on that.

I haven't ran pyflakes or a PEP8 checker on it yet, so keep that in mind!

main.py

from game import Game
from card import Card
from deck import Deck
from hand import Hand
from player import Player
from dealer import Dealer

name = input("Please enter your name: ")

dealer = Dealer()
player = Player(name)
deck = Deck()
game = Game(dealer, player, deck)
game_loop = True

while game_loop:

    game.new_turn()

    print("You have {} dollars".format(game.player.stack))
    print("How much would you like to bet?")
    game.place_bet(input("> "))

    game.dealer.show_hand()
    game.player.show_hand()

    hit = game.hit_or_stand()

    while hit and not game.player.hand.bust():
        game.player.hit(game.deck)
        game.player.show_hand()
        if game.player.hand.best_hand  21:
            print("Dealer busts!, you win!")
            game.player.stack += game.pot * 2
        else:
            game.check_for_winner(game.dealer, game.player)
    else:
        if dealer.hand.best_hand == 21:
            print("Dealer has blackjack! You lose!")
        else:
            print("Your hand is over 21, you lose!!")

    if player.stack < 1:
        print("You are out of money! Game over!")
        break

    game_loop = game.play_again()


game.py

```
from dealer import Dealer
from player import Player
from hand import Hand
from card import Card
from deck import Deck, Clubs, Diamonds, Hearts, Spades

class Game:
"""Information about the game.

Responsibilities:

* Check for winner
* Handles betting and bankroll
* Resets the game and hands

Collaborators

* Checks the player and dealer's hand amounts and compares them
"""

def __init__(self, dealer, player, deck):
self.dealer = dealer
self.player = player
sel

Solution

I haven't ran pyflakes or a PEP8 checker on it yet, so keep that in mind!

Uhm, why haven't you? That's a rhetorical question. You should have run those,
and your statement of having not run doesn't help the reviewer in anyway,
except that one might think you're deliberately careless.

Strange things

This is a bit odd:

if game.dealer.hand.best_hand > 21:
        print("Dealer busts!, you win!")
        game.player.stack += game.pot * 2
    else:
        game.check_for_winner(game.dealer, game.player)


The if branch prints something, the else branch doesn't...
Taking a quick look at game.check_for_winner:

def check_for_winner(self, dealer, player):
    if self.player.hand.best_hand < self.dealer.hand.best_hand:
        return("You Lose")
    elif self.dealer.hand.best_hand < self.player.hand.best_hand:
        print("You Win!")
        self.player.stack += self.pot * 2
    elif self.dealer.hand.best_hand == self.player.hand.best_hand:
        print("Push!")
        self.player.stack += self.pot


The method sometimes returns a string, sometimes prints a string.
You should make it behave consistently.
It's probably a typo, you meant to print instead of return.
But even so,
this is not good:
the printing of game results is split in two places:
main and game.
It would be better to keep main fully in charge of that,
having the logic in one place.

Also, the last elif should really be a simple else.

In game.place_bet this is really strange:

try:
        int(amount)
        if int(amount) <= self.player.stack:
            self.player.stack -= int(amount)
            self.pot += int(amount)
        else:
            self.place_bet(input("Not enough funds! You have {} dollars. "
                                 "Place a bet: ".format(self.player.stack)))
    except ValueError:
        self.place_bet(input("Place a bet: "))


Why call int(amount) multiple times, re-parsing a string to integer multiple times? Better do it once and save in a variable.

Naming

stack is a strange name for a pot or bet.
It's especially bad because in programming the term "stack" evokes a specific data structure, making the code misleading and harder to read.
Even if "stack" is the correct and single best obvious term in Black Jack (I don't know), I suggest to find something else.

This is a bit confusing:

game.dealer.reveal_hand()
    game.player.show_hand()


"show" and "reveal" are synonyms, which makes these statements confusing.
It's not great when I have to open the implementation of two functions to see the difference of what they do.

new_turn in game can be misleading.
It's really a new game.
But that would be misleading too,
because a method starting with "new" usually returns a new instance of something.
reset_game would be better.

Other things

I know this is Black Jack and the goal to reach must be 21,
but it would be fun sometimes to mess with the system and see how the game dynamics change if we use a different number, like 31.
To make such future extensions easier,
I'd put 21 in a global constant, and call it for example BLACKJACK.
In any case I think it's a good natural reflex to develop to always replace repeated things with constant variables.

Code Snippets

if game.dealer.hand.best_hand > 21:
        print("Dealer busts!, you win!")
        game.player.stack += game.pot * 2
    else:
        game.check_for_winner(game.dealer, game.player)
def check_for_winner(self, dealer, player):
    if self.player.hand.best_hand < self.dealer.hand.best_hand:
        return("You Lose")
    elif self.dealer.hand.best_hand < self.player.hand.best_hand:
        print("You Win!")
        self.player.stack += self.pot * 2
    elif self.dealer.hand.best_hand == self.player.hand.best_hand:
        print("Push!")
        self.player.stack += self.pot
try:
        int(amount)
        if int(amount) <= self.player.stack:
            self.player.stack -= int(amount)
            self.pot += int(amount)
        else:
            self.place_bet(input("Not enough funds! You have {} dollars. "
                                 "Place a bet: ".format(self.player.stack)))
    except ValueError:
        self.place_bet(input("Place a bet: "))
game.dealer.reveal_hand()
    game.player.show_hand()

Context

StackExchange Code Review Q#78515, answer score: 4

Revisions (0)

No revisions yet.