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