The goal of this notebook is to create a blackjack game with the following attributes: (1) The game needs to have one player versus an automated dealer. (2) The player can stand or hit. (3) The player must be able to pick their betting amount. (4) The program needs to keep track fo the players total money. (5) The program needs to alert the player of wins,losses, or busts, etc..

Steps in game:

(1) Initialize game with player, dealer, shuffled deck, and player bet amount

(2) Deal cards to player and dealer

(3) Ask player if they want to hit

(4) Determine if dealer wants to hit

(5) Ask player if they want to hit again, etc.

(6) When both player and dealer stay, compare cards and determine who wins

(7) Add or deduct bet amount from player's money

(8) Ask if player wants to play again


In [1]:
import random

In [2]:
# Define a deck
# Deck has 52 cards, 2-10 + Jack + Queen + King + Ace in four suits

class Deck(object):
    """ Creates deck for blackjack game.
    The default number of decks to use is 1,
    change by using the numdecks attribute."""
    
    suits = ['Heart', 'Spade', 'Club', 'Diamond']
    ranks = [2,3,4,5,6,7,8,9,10,'Jack','Queen','King','Ace']
    
    def __init__(self, numdecks = 1):
        self.numdecks = numdecks
        suitlist = []
        for suit in Deck.suits:
            for j in range(13):
                suitlist.append(suit)
        deck = zip(Deck.ranks*4, suitlist)
        
        self.deck = deck * numdecks
    
    def shuffle(self):
        return random.shuffle(self.deck)
    
    def deal(self, num_cards):
        return self.deck[:num_cards], self.deck[num_cards:]

In [3]:
class Player(object):
    """Initializes a player with a hand and an amount of money to spend.
    hand default = [], money default = 100"""
    
    def __init__(self, name, hand = [], total_money = 100):
        self.name = name
        self.hand = hand
        self.total_money = total_money
    
    def changeMoney(self, bet_amount):
        self.total_money += bet_amount
        no_money = False
        if self.total_money <= 0:
            no_money = True
        return self.total_money, no_money
    
    def ask_for_hit(self):
        while True:
            hit = raw_input('%s, your cards sum to %d, would you like to hit? (Y/N): ' %(self.name, sum_card_values(self.hand)))
            if hit.lower() == 'y':
                return True
                break
            elif hit.lower() == 'n':
                return False
                break
            else:
                print 'Invalid entry.'

In [4]:
class Dealer(object):
    """Dealer initialized with empty hand"""
    def __init__(self, hand = []):
        self.hand = hand
    
    def do_I_hit(self, hand):
        if sum_card_values(self.hand) < 17:
            return True
        else:
            return False

In [5]:
def ask_num_decks():
    while True:
        numdecks = raw_input('How many decks would you like to play with? (enter an int): ')
        try:
            numdecks = int(numdecks)
            break
        except ValueError:
            print 'Not an integer number of decks.'
    return numdecks

In [6]:
def get_bet_amount(player):
    while True:
        bet_amount = raw_input('How much would you like to bet? (enter an int): ')
        try:
            bet_amount = int(bet_amount)
            if bet_amount > player.total_money:
                print "You don't have that much money!"
                continue
            else:
                print "Ok!"
                break
        except ValueError:
            print 'Not an integer bet amount.'
    return bet_amount

In [7]:
def sum_card_values(hand):
    handsum = 0
    numaces = 0
    for rank, suit in hand:
        if rank == 'Jack' or rank == 'Queen' or rank == 'King':
            rank = 10
        elif rank == 'Ace':
            rank = 1
            numaces +=1
        handsum += rank
    
    num = 0
    while num <= numaces:
        if handsum + 10*num <= 21:
            handsum = handsum + 10*num
        num +=1
    
    return handsum

In [8]:
def initialize_game():
    # Get player name
    playername = raw_input('Please enter your player name: ')
    player = Player(playername)
    print "%s, you have %d dollars to spend." %(player.name, player.total_money)
    
    # Ask number of decks to play with
    numdecks = ask_num_decks()
    #deck = Deck(numdecks) ---> Moved to different part of play_game()
    #deck.shuffle()
    
    # Ask bet amount ---> Actually, this got moved to different part of play_game()
    #betamount = get_bet_amount()
    
    # Initialize dealer
    dealer = Dealer()
    
    return player, dealer, numdecks

In [9]:
def first_deal(player, dealer, deck):
    player.hand, deck.deck = deck.deal(2) # deal cards to player
    print '{0}, your hand is: {1}'.format(player.name, player.hand)
    
    dealer.hand, deck.deck = deck.deal(2) # deal cards to dealer, only the top one is revealed
    print "The dealer's top card is: ", dealer.hand[0]
    
    return player, dealer, deck

In [10]:
def hit(hit_bool, deck):
    '''Returns the new card to be appended to the player hand
    and the new deck with that card removed if hit_bool == True,
    else returns an empty tuple and the same deck.'''
    if hit_bool == True:
        newcard, deck.deck = deck.deal(1)
        return newcard[0], deck.deck #returns new card to be appended to player's hand
                                    # and new deck with card removed.
    else:
        return (0,0), deck.deck

In [11]:
def who_won(player, dealer):
    '''Determines if the player or dealer has won after both player and dealer do not hit.
    returns True if player wins, False if dealer wins.'''
    
    player_hand_sum = sum_card_values(player.hand)
    dealer_hand_sum = sum_card_values(dealer.hand)
    
    if player_hand_sum > dealer_hand_sum and player_hand_sum <= 21:
        print 'Congratulations, %s, you won!' %player.name
        return True
    elif player_hand_sum == dealer_hand_sum:
        print 'Tie!'
        return None
    elif player_hand_sum > 21 and dealer_hand_sum > 21:
        print 'Tie!'
        return None
    elif player_hand_sum <= 21 and dealer_hand_sum > 21:
        print 'Congratulations, %s, you won!' %player.name
        return True
    else:
        print 'Sorry, %s, the dealer beat you.' %player.name
        return False

In [12]:
def play_hand(player, dealer, deck, betamount):
    """Function to run through one hand of blackjack.
    Returns boolean True/False in response to 'play another hand?' """
    
    playerbool = True
    dealerbool = True
    
    while playerbool == True:
        
        playerbool = player.ask_for_hit()
        newcard, deck.deck = hit(playerbool, deck)
        player.hand.append(newcard)
        if newcard == (0,0):
            player.hand.remove(newcard)
        print ""
        print "{0}, your hand is: {1}".format(player.name, player.hand)
        if sum_card_values(player.hand) > 21:
            print 'The value of your cards exceeds 21.'
            break
    
    print 'Thank you. Now the dealer will resolve their hand.'
    print '-------------------------------------------------'
    
    if sum_card_values(player.hand) > 21:
        dealerbool = False
    while dealerbool == True:
        dealerbool = dealer.do_I_hit(dealer.hand)
        newdealercard, deck.deck = hit(dealerbool, deck)
        
        # print 'The dealer hand sums to: ', sum_card_values(dealer.hand)
        dealer.hand.append(newdealercard)
        
        if newdealercard == (0,0):
            dealer.hand.remove(newdealercard)
            
        if dealerbool == True:
            print ""
            print "The dealer chose to hit."
            print "The Dealer's new card is: ", newdealercard
            if sum_card_values(dealer.hand) > 21:
                print 'The value of the dealer cards exceeds 21.'
                break
        else:
            print "The dealer chose to stay."

    
    print "The dealer's hand is: ", dealer.hand
    
    did_player_win = who_won(player, dealer)
    
    print '-------------------------------------------------'
    
    if did_player_win == True:
        player.total_money, gameoverbool = player.changeMoney(betamount)
        print "{0}, you now have {1} dollars.".format(player.name, player.total_money)
        while True:
            play_again = raw_input("Would you like to play another hand? (y/n): ")
            if play_again.lower() == 'y':
                return True
                break
            elif play_again.lower() == 'n':
                return False
                break
            else:
                print 'Invalid entry.'
                
    elif did_player_win == False:
        player.total_money, gameoverbool = player.changeMoney(-betamount)
        print "{0}, you now have {1} dollars.".format(player.name, player.total_money)
        if gameoverbool == True:
            print "You have no more money to play with. See you next time!"
            return False
        if gameoverbool == False:
            while True:
                play_again = raw_input("Would you like to play another hand? (y/n): ")
                if play_again.lower() == 'y':
                    return True
                    break
                elif play_again.lower() == 'n':
                    return False
                    break
                else:
                    print 'Invalid entry.'
        
    else:
        print "{0}, you still have {1} dollars.".format(player.name, player.total_money)
        while True:
            play_again = raw_input("Would you like to play another hand? (y/n): ")
            if play_again.lower() == 'y':
                return True
                break
            elif play_again.lower() == 'n':
                return False
                break
            else:
                print 'Invalid entry.'

In [13]:
def play_game():    
    player, dealer, numdecks = initialize_game() # initialize player and game
    
    play_again = True
    
    while play_again == True:
        betamount = get_bet_amount(player)
        deck = Deck(numdecks)
        deck.shuffle()
        
        player, dealer, deck = first_deal(player, dealer, deck) # Give initial cards
        
        play_again = play_hand(player, dealer, deck, betamount)
        
    print 'Thanks for playing!'

In [14]:
play_game()


Please enter your player name: Jolene
Jolene, you have 100 dollars to spend.
How many decks would you like to play with? (enter an int): 2
How much would you like to bet? (enter an int): 1000
You don't have that much money!
How much would you like to bet? (enter an int): 50
Ok!
Jolene, your hand is: [(2, 'Club'), ('Jack', 'Spade')]
The dealer's top card is:  (3, 'Diamond')
Jolene, your cards sum to 12, would you like to hit? (Y/N): y

Jolene, your hand is: [(2, 'Club'), ('Jack', 'Spade'), (8, 'Diamond')]
Jolene, your cards sum to 20, would you like to hit? (Y/N): n

Jolene, your hand is: [(2, 'Club'), ('Jack', 'Spade'), (8, 'Diamond')]
Thank you. Now the dealer will resolve their hand.
-------------------------------------------------

The dealer chose to hit.
The Dealer's new card is:  ('Queen', 'Spade')
The value of the dealer cards exceeds 21.
The dealer's hand is:  [(3, 'Diamond'), (9, 'Diamond'), ('Queen', 'Spade')]
Congratulations, Jolene, you won!
-------------------------------------------------
Jolene, you now have 150 dollars.
Would you like to play another hand? (y/n): n
Thanks for playing!

In [ ]: