Blackjack console game using Python

In this tutorial, let’s explore how to code a console playable blackjack game using Python with an easy approach to understand the flow of the game.

Blackjack is a simple cards game it requires a deck of 52 cards.

Importing the necessary Python modules

import random  # random module for picking a random card from the deck
from itertools import product  # to avoid nested for loops lets import product from itertools module
import math  # to use absolute function from the math module

# let us declare 2 global variables innerplay and outerplay for regulating the game conditions here.
outerplay = ""
innerplay = ""
# these global variables are used within a function to a make changes at a global scope and to avoid error these must be declared before usage

Generating a deck of cards:

Lets create a list of all the of all the 4 suits in a card and a list of all the cards in each suit, along with a dictionary consisting of each card with its value.

Here Ace is mapped to a  score of 11 however this is will be later decided as per the needs of the particular round in game because an Ace is either a score of 11 or 1 in Blackjack depending on whichever is best.

suit = ['clubs', ' spades', 'diamonds', 'hearts']
value_cards = {
    'Four': 4,
    'Two': 2,
    'Three': 3,
    'Five': 5,
    'Six': 6,
    'Seven': 7,
    'Eight': 8,
    'Nine': 9,
    'Ten': 10,
    'Jack': 10,
    'Queen': 10,
    'King': 10,
    'Ace': 11
}
face_cards = ['king', 'queen', 'jack', 'ace', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']

Lets create card class that generates a deck of cards. So that each object of this class generates an individual deck of 52 cards. This class generates a deck of 52 cards and it has method to pop one card from the shuffled deck.

class CardGen():
    def __init__(self):
        self.face_cards = face_cards
        self.suit = suit
        self.deck = []
        for suite, rankie in product(self.suit, self.face_cards):
            self.deck.append((rankie, suite))

    def cardsrandom(self):
        random.shuffle(self.deck)  # randomly shuffling the deck
        f1, s1 = self.deck.pop()
        return f1, s1

Creating a money class to keep account of the players winnings and losings in a game:

class money():
    def __init__(self, chips):
        self.chips = chips
        self.wincase = 1.5  # a gain of 50 % on his bettings

    def wincasecalc(self, bet):  # method to be called when player wins to add his winnings to his account
        if bet <= self.chips:
            self.chips = self.chips + bet * self.wincase
            print(f'You are now left with {self.chips}\n')
            print(f'You have gained an additional of {bet * self.wincase}\n')

    def loosecase(self, bet):  # method to be called when player loses to deduct his loss from his acoount
        if bet <= self.chips:
            self.chips = self.chips - bet
            print(f'You are now left with {self.chips}\n')
            print(f'You lost an amount of {bet}\n')

Creating all the necessary functions for the flow of this game:

  • Card display function: It takes in the rank and suit of the card and prints it as “rank of suit”.
  • Hit or stand function: The dealer by default hits until his score is 17 this function is primarily aimed at the players choice of whether he would like another card or stand his ground.
  • Bet taking function: It ensures that player is able to bet an amount that is greater than equal to his balance in account.
  • Score calculating function: This function calculates the score, in case of an Ace card it calculates 2 scores with one score where ace is valued as 1 and another score where ace is valued as 11 and the score that is closest to winning condition of the game will be selected based on their turn.
  • Win check function: This function will be repeatedly called to check who among the player and the dealer has won the game. All cases to decide the result of the game have been considered here.
  • Play again function: This function is to ask the player if they would like to play another game.
    def carddisplay(ts1, tf1):  # Card dusplay function
        print(f' {tf1} of {ts1} ')
    
    
    def bettake(amount):  # Bet taking function
        betting_amount = int(input('How much would you like to bet?\n'))
        if amount < betting_amount:
            print(f'Sorry your betting amount exceeds your balance! You currently have a balance of {amount}\n')
            bettake(amount)  # recurrent function until the condition is satisfied
            return betting_amount
        else:
            return betting_amount
    
    
    def scorecalculator(currentcard, score=0):   # function that takes the input of current card and score to return the updated score
        if currentcard == 'ACE':
            score1 = score + 11   # score calcuated with ace valued as 11
            score2 = score + 1   # score calculated with ace valued as 1
            if math.fabs(21 - score1) < math.fabs(21 - score2):    # the score closest to 21 is returned 
                return score1
            else:
                return score2
        else:
            score = score + value_cards.get(currentcard.capitalize(), 0)
            return score
    
    
    def wincheck(playerscore, dealerscore, balance, bettin_gamount):   # function that compares current score of player and dealer and checks win/lose case and makes appropriate actions on the players account
        if playerscore > 21:   # checks if player score is above 21, then player loses
            print('Player bust!\n')
            print('You have lost the game!\n')
            print(f'Your score:{playerscore}, and dealers score : {dealerscore}\n')
            balance.loosecase(bettin_gamount)
            return 'LOST'
        elif dealerscore > 21:   # check is dealer score is above 21, then dealer loses 
            print('You have won!\n')
            print(f'Your score:{playerscore}, and dealers score : {dealerscore}\n')
            balance.wincasecalc(bettin_gamount)
            return 'WON'
    
        elif playerscore == 21:  
            if dealerscore ==21:  # if players score and dealers score both are equal then its a tie
                print('ITS A TIE!\n')
                print(f'balance{balance.chips}\n')
                return 'TIE'
            else:
                print('Player wins!\n')  # if players score is 21 then player wins
                print('You have won the game!\n')
                print(f'Your score:{playerscore}, and dealers score : {dealerscore}\n')
                balance.wincasecalc(bettin_gamount)
                return 'WON'
        elif dealerscore == 21:  # if dealer score is 21 then dealer wins
            print('Player bust!\n')
            print('You have lost the game!\n')
            print(f'Your score:{playerscore}, and dealers score : {dealerscore}\n')
            balance.loosecase(bettin_gamount)
            return 'LOST'
        elif playerscore < 21 and 21 > dealerscore >= 17:  
            if playerscore > dealerscore:   # if players score is close to 21 then player wins
                print('Player wins!\n')
                print('You have won the game!\n')
                print(f'Your score:{playerscore}, and dealers score : {dealerscore}\n')
                balance.wincasecalc(bettin_gamount)
                return 'WON'
            elif dealerscore > playerscore:  # else if dealers score is close to 21 then dealer wins
                print('Player bust!\n')
                print('You have lost the game!\n')
                print(f'Your score:{playerscore}, and dealers score : {dealerscore}\n')
                balance.loosecase(bettin_gamount)
                return 'LOST'
        
    
    
    def hitorstand(turns, dscore, playercards, dealercards):   # players choice as to whether he would like to hit or stand
        if turns == 'PLAYER':  # checking if it is players turn
            choice = input('Would you like to hit or stand?').upper()   
            if choice == 'HIT':
                print('YOUR CARD:')
                pf, ps = playercards.cardsrandom()
                return ps, pf
            elif choice == 'STAND':
                return 0, 0
    
        elif turns == 'DEALER':  # checking dealers turn
            if dscore <= 17:   # dealer hits by default if the score is less than equal to 17
                print('DEALERS CARD:')
                df, ds = dealercards.cardsrandom()
                return ds, df
            else:
                print('As per the rules dealer chooses to stand!')
                return 0, 0
    
    
    def playagain(replaychoice):   # function to recreate game conditions if the player wishes to play again
        global innerplay
        global outerplay
        if replaychoice == 'Y':
            innerplay = False
        elif replaychoice == 'N':
            outerplay = 'n'
            innerplay = False
            print('Thank you for playing have a great day!\n')
    
    

    Now initiating the game play loop using the functions that we defined above:

    # MAIN GAME BEGINS HERE INNERPLAY AND OUTERPLAY LOOPS ARE TO REGULATE GAME PLAY FOR REPLAY AND EXIT LOOP.
    
    
    print('HELLO WELCOME TO BLACK JACK GAME!')
    outerplay = input('Ready to play, type y for yes n for no\n').upper()  # beginning the outer loop of the game
    while outerplay == 'Y':
        amount = int(input('What amount would you want in chips?\n'))  # taking user input for account
        Balance = money(amount)  # creating players account using the defined money class
        print('Let the game begin, dealer hits\n')
        turn = 'PLAYER'  # initiating the first turn of player
        pscore = 0  # initial score of the player
        dscore = 0  # initial score of the dealer
        playercards = CardGen()  # generating a deck of cards for player
        dealercards = CardGen()  # generating a deck of cards for dealer
        df1, ds1 = dealercards.cardsrandom()  # popping a random card from players deck
        df2, ds2 = dealercards.cardsrandom()  # popping a random card from dealers deck
        print('DEALERS CARD:\n')
        print('<card hidden>')
        carddisplay(ds2, df2)  # displaying one of dealers card
        dscore = scorecalculator(df2, dscore)  # updating dealers score
        pf1, ps1 = playercards.cardsrandom()  # generating 2 random cards of player
        pf2, ps2 = playercards.cardsrandom()
    
        print('YOUR CARDS:\n')
        carddisplay(ps1, pf1)  # displaying both player cards
        carddisplay(ps2, pf2)
        bettingmoney = bettake(amount)  # taking an appropriate bet amount
        pscore = scorecalculator(pf1, pscore)  # updating players score
        pscore = scorecalculator(pf2, pscore)
    
        print('DEALERS CARDS:')
        carddisplay(ds1, df1)
        carddisplay(ds2, df2)
        dscore = scorecalculator(df1, dscore)
        # checking game status of whether the player or dealer has won
        currentstatus = wincheck(pscore, dscore, Balance, bettingmoney)
        if currentstatus == 'WON' or currentstatus == 'LOST' or currentstatus == 'TIE':
            break  # if player or dealer has won then exit the outerplay loop
        innerplay = True
        turn = 'PLAYER'   # changing turn to players turn
        while innerplay:   # an inner loop for the game to progress until one of them loses or wins
            if turn == 'PLAYER':
                ps, pf = hitorstand('PLAYER', dscore, playercards, dealercards)   # whether players wishes to hit or stand
                if pf == 0:
                    turn = 'DEALER'  # changing it to players turn
                else:
                    carddisplay(ps, pf)
                    pscore = scorecalculator(pf, pscore)
                    currentstatus = wincheck(pscore, dscore, Balance, bettingmoney)
                    if currentstatus == 'WON' or currentstatus == 'LOST' or currentstatus == 'TIE':
                        break
                    turn = 'DEALER'
            elif turn == 'DEALER':
                ds, df = hitorstand('DEALER', dscore, playercards, dealercards)
                if df == 0:
                    turn = 'PLAYER'
                else:
                    carddisplay(ds, df)
                    dscore = scorecalculator(df, dscore)
                    currentstatus = wincheck(pscore, dscore, Balance, bettingmoney)
                    if currentstatus == 'WON' or currentstatus == 'LOST' or currentstatus == 'TIE':
                        break
                    turn = 'PLAYER'
        replaychoice = input('Would you like to play again? Y for yes and N for no.').upper()
        playagain(replaychoice)   # taking players input if they wish to play again from the start
    rating = input('How  would you like to rate this game play out of 5?\n')
    print(rating)
    print('THANK YOU!\n')

Output:

HELLO WELCOME TO BLACK JACK GAME!
Ready to play, type y for yes n for no
y
What amount would u want in chips?2000
Let the game begin, dealer hits
DEALERS CARD:

<card hidden>
two of clubs 
YOUR CARDS:

ten of diamonds 
nine of spades 
How much would you like to bet?
500
DEALERS CARDS:
eight of diamonds 
two of clubs 
would you like to hit or stand?
stand
DEALERS CARD:
three of diamonds 
Would you like to hit or stand?stand
DEALERS CARD:
five of spades 
Player wins!

You have won the game!

Your score:19, and dealers score : 18
You are now left with 2750.0

You have gained an additional of 250.0

Would you like to play again? Y for yes and N for no.n
Thank you for playing have a great day!

How would you like to rate this game play out of 5?4
4
THANK YOU!
  • This game can be coded with a minimalist approach in few lines of code. However the aim here is to have an understanding of  how to approach such problem statements.

Leave a Reply

Your email address will not be published. Required fields are marked *