Create a Blackjack Game with Python – Source Code Included

02 May 2023 Balmiki Mandal 0 Python

Create a Blackjack Game using Python with source code

Blackjack, or 21, is one of the most popular casino card games in the world. In this tutorial, we will learn how to build a basic Blackjack game in Python using Classes. We’ll keep the game simple by using the following rules and criteria for decisions:

  • The Player and the Dealer are each dealt 2 cards.
  • The Player looks at their cards and can choose to ‘Hit’ or ‘Stand’.
  • If the Player ‘Hits’, they take an additional card.
  • If the Player ‘Stands’, they stop taking cards.
  • The Dealer must hit on 16 and stand on 17.
  • The highest score that does not exceed 21 wins the game.

Let’s get started by defining the classes and functions that we will need to create our Blackjack game.

1. Create the Card Class

The Card class represents a single playing card. It contains the rank (Ace, 2, 3, etc.), suit (Clubs, Diamonds, Hearts, Spades), and value (1 to 10) of each card.

class Card:
    def __init__(self, rank, suit):
        self.rank = rank
        self.suit = suit
        if self.rank == 'Ace':
            self.value = 11
        elif self.rank in ['Jack', 'Queen', 'King']:
            self.value = 10
        else:
            self.value = int(self.rank)
            
    def __str__(self):
        return self.rank + ' of ' + self.suit
    

2. Create the Deck Class

The Deck class contains a list of Card objects. We will define 3 instance methods for our Deck class:

  • `__init__()`: This method will be called when a Deck object is created. It initializes all 52 possible cards and adds them to the deck.
  • `shuffle_deck()`: This method shuffles all the cards in the deck randomly.
  • `deal()`: This method deals a card from the top of the deck.
import random

class Deck:
    def __init__(self):
        self.deck = [] # start with an empty list
        for suit in ['Spades', 'Clubs', 'Diamonds', 'Hearts']:
            for rank in ['Ace', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King']:
                self.deck.append(Card(rank, suit))
                
    def shuffle_deck(self):
        random.shuffle(self.deck)
        
    def deal(self):
        single_card = self.deck.pop()
        return single_card
        

3. Create the Hand Class

The Hand class is used to calculate the total points of a player's hand. It contains a list of Card objects and a `calc_value()` method to calculate the total points of the hand.

class Hand:
    def __init__(self):
        self.cards = [] # start with an empty list as we did in the Deck class
        self.value = 0  # start with zero value
        self.aces = 0   # add an attribute to keep track of aces
        
    def add_card(self,card):
        # card passed in
        # from Deck.deal() ---> single Card(rank,suit)
        self.cards.append(card)
        self.value += card.value
        
        # track aces
        if card.rank == 'Ace':
            self.aces += 1 
    
    def adjust_for_ace(self):
        # If total value > 21 and I still have an Ace
        # than change my Ace to be a 1 instead of an 11
        while self.value > 21 and self.aces:
            self.value -= 10
            self.aces -= 1 
            

4. Create the Chips Class

The Chips class is used to track how much money a player has. This class contains an instance variable to store the amount of chips a player has. We will also define two methods:

  • `__init__()` is used to set up the chips when a new game starts.
  • `win_bet()` is used to increase the amount of player's chips when they win.
  • `lose_bet()` is used to decrease the amount of player's chips when they lose.
class Chips:
    def __init__(self, total=100):
        self.total = total  # This can be set to a default value or supplied by a user input
        self.bet = 0
        
    def win_bet(self):
        self.total += self.bet
    
    def lose_bet(self):
        self.total -= self.bet
        

5. Create a Function for Taking Bets

This function will prompt the user to make a bet and ensure their bet does not exceed their chip total.

def take_bet(chips):
    while True:
        try:
            chips.bet = int(input('How many chips would you like to bet? '))
        except ValueError:
            print('Sorry, a bet must be an integer!')
        else:
            if chips.bet > chips.total:
                print("Sorry, your bet can't exceed",chips.total)
            else:
                break

6. Create a Function for Taking Hits

This function will prompt the user to either Hit or Stand and update the player's hand accordingly.

def hit(deck,hand):
    
    single_card = deck.deal()
    hand.add_card(single_card)
    hand.adjust_for_ace()

7. Create a Function Prompting the Player to Hit or Stand

This function will prompt the user to either Hit or Stand and update the player's hand accordingly.

def hit_or_stand(deck,hand):
    global playing  # to control an upcoming while loop
    
    while True:
        x = input("Would you like to Hit or Stand? Enter 'h' or 's' ")
        
        if x[0].lower() == 'h':
            hit(deck,hand)  # hit() function defined above

        elif x[0].lower() == 's':
            print("Player stands. Dealer is playing.")
            playing = False

        else:
            print("Sorry, please try again.")
            continue
        break

8. Create Functions to Display Cards

These two functions display the cards that each player holds and the cards that are in play.

def show_some(player,dealer):
    print("\nDealer's Hand:")
    print(" ")
    print('',dealer.cards[1])  
    print("\nPlayer's Hand:", *player.cards, sep='\n ')
    
def show_all(player,dealer):
    print("\nDealer's Hand:", *dealer.cards, sep='\n ')
    print("Dealer's Hand =",dealer.value)
    print("\nPlayer's Hand:", *player.cards, sep='\n ')
    print("Player's Hand =",player.value)

9. Create Functions to Handle End of Game Scenarios

These two functions run different scenarios at the end of the game depending on who won.

def player_busts(player,dealer,chips):
    print("Player busts!")
    chips.lose_bet()

def player_wins(player,dealer,chips):
    print("Player wins!")
    chips.win_bet()

def dealer_busts(player,dealer,chips):
    print("Dealer busts!")
    chips.win_bet()
    
def dealer_wins(player,dealer,chips):
    print("Dealer wins!")
    chips.lose_bet()
    
def push(player,dealer):
    print("Dealer and Player tie! It's a push.")

10. Put it all Together

Now that we have our classes and functions defined, we can create the logic for our game. Let’s create a game loop withwhile loop. Each time the loop runs, we'll leave the game and ask the player if they want to play again.

# Global Variables
playing  = True

#Game Loop
while True:
    # Print an opening statement
    print('Welcome to BlackJack! Get as close to 21 as you can without going over!\n\
    Dealer hits until she reaches 17. Aces count as 1 or 11.')
    
    # Create & shuffle the deck, deal two cards to each player
    deck = Deck()
    deck.shuffle_deck()
    
    player_hand = Hand()
    player_hand.add_card(deck.deal())
    player_hand.add_card(deck.deal())
    
    dealer_hand = Hand()
    dealer_hand.add_card(deck.deal())
    dealer_hand.add_card(deck.deal())
            
    # Set up the Player's chips
    player_chips = Chips()  
    
    # Prompt the Player for their bet
    take_bet(player_chips)
    
    # Show cards (but keep one dealer card hidden)
    show_some(player_hand,dealer_hand)
    
    while playing:  # recall this variable from our hit_or_stand function
        
        # Prompt for Player to Hit or Stand
        hit_or_stand(deck,player_hand) 
        
        # Show cards (but keep one dealer card hidden)
        show_some(player_hand,dealer_hand)  
        
        # If player's hand exceeds 21, run player_busts() and break out of loop
        if player_hand.value > 21:
            player_busts(player_hand,dealer_hand,player_chips)
            break        


    # If Player hasn't busted, play Dealer's hand until Dealer reaches 17 
    if player_hand.value <= 21:
        
        while dealer_hand.value < 17:
            hit(deck,dealer_hand)    
    
        # Show all cards
        show_all(player_hand,dealer_hand)
        
        # Run different winning scenarios
        if dealer_hand.value > 21:
            dealer_busts(player_hand,dealer_hand,player_chips)

        elif dealer_hand.value > player_hand.value:
            dealer_wins(player_hand,dealer_hand,player_chips)

        elif dealer_hand.value < player_hand.value:
            player_wins(player_hand,dealer_hand,player_chips)

        else:
            push(player_hand,dealer_hand)        
    
    # Inform Player of their chips total 
    print("\nPlayer's winnings stand at",player_chips.total)
    
    # Ask to play again
    new_game = input("Would you like to play another hand? Enter 'y' or 'n' ")
    
    if new_game[0].lower()=='y':
        playing=True
        continue
    else:
        print("Thanks for playing!")
        break

And that’s it! You now have a functioning Blackjack game! Feel free to extend the project by adding additional features like doubling down and splitting, or try building a similar game using Object-Oriented Programming to take your skill with Python to the next level.

BY: Balmiki Mandal

Related Blogs

Post Comments.

Login to Post a Comment

No comments yet, Be the first to comment.