May 30, 2025
Learn how to make a Python Blackjack game with a detailed code review and some best practices
I made a simple Python Blackjack game so others can learn from the code, get better at programming, or find ideas. You can look at the code, copy it, or change it if you want.
import sys, random, time
HEARTS = '\u2665'
DIAMONDS = '\u2666'
CLUBS = '\u2663'
SPADES = '\u2660'
DEALER_SLEEP_TIME = 1
def get_user_bet(money):
"""
Prompts the user to enter a valid bet amount.
Returns:
int: The valid bet amount entered by the user.
"""
print(f'You currently have ${money}')
while True:
try:
bet = int(input('Enter your bet: '))
if 0 < bet <= money:
return bet
else:
print('Try again')
except ValueError:
print(f'Please enter a value between 1 and {money}')
def get_deck():
"""
Creates and shuffles a standard deck of 52 playing cards.
Returns:
list: A shuffled list of tuples representing a deck of cards,
where each tuple contains a rank and a suit.
"""
deck = []
for suit in (HEARTS, DIAMONDS, CLUBS, SPADES):
for rank in range(2, 11):
deck.append((rank, suit))
face_cards = ['A', 'J', 'Q', 'K']
for suit in (HEARTS, DIAMONDS, CLUBS, SPADES):
for face_card in face_cards:
deck.append((face_card, suit))
random.shuffle(deck)
return deck
def deal_cards(deck):
"""
Deals initial cards to both the user and the dealer.
Returns:
tuple: A tuple containing the user's cards, the dealer's
cards, and the remaining deck.
"""
user_cards = []
dealer_cards = []
for _ in range(2):
user_cards.append(deck.pop())
dealer_cards.append(deck.pop())
dealer_cards.append(('##', '#'))
display_cards(user_cards, dealer_cards)
return user_cards, dealer_cards, deck
def get_user_decision():
"""
Asks the user for their decision after being dealt cards.
Returns:
str: The user's decision, which can be 'h' for hit, 's' for stand, or 'd'
for double down.
"""
choices = ['h', 's', 'd']
while True:
user_decision = input('\nDo you want to (H)it - (S)tand or (D)ouble Down? ').lower()
if user_decision not in choices:
print('Please choose (h, s, d)')
else:
return user_decision
def draw_card(deck):
"""
Draws a random card from the deck
"""
card = deck.pop()
return card, deck
def calculate_score(cards):
"""
Calculate the total score of a given list of cards.
"""
total_score = 0
aces = 0
for card in cards:
if card[0] in ['J', 'Q', 'K']:
total_score += 10
elif card[0] == 'A':
aces += 1
else:
total_score += card[0]
for _ in range(aces):
if total_score + 11 <= 21:
total_score += 11
else:
total_score += 1
return total_score
def user_action(cards, deck, bet, money):
"""
Asks the user for their action
Returns:
tuple: A tuple containing the updated cards, deck and a boolean indicating
whether the user has doubled down or not.
"""
double_down = False
while True:
decision = get_user_decision()
if decision == 'h':
new_card, deck = draw_card(deck)
print(f'You drew a {new_card[0]} of {new_card[1]}')
cards.append((new_card[0], new_card[1]))
display_cards(user_cards=cards)
if calculate_score(cards) >= 21:
return cards, deck, double_down
elif decision == 'd':
if bet > money:
print('You do not have enough money to double down')
continue
if len(cards) > 2:
print('You can not double down after having more than 2 cards')
continue
new_card, deck = draw_card(deck)
cards.append((new_card[0], new_card[1]))
print(f'You drew a {new_card[0]} of {new_card[1]}')
display_cards(user_cards=cards)
double_down = True
return cards, deck, double_down
else:
return cards, deck, double_down
def print_cards(cards):
"""
Prints out a graphical representation of the given cards.
"""
rows = ['', '', '', '']
for card in cards:
rank, suit = card
rows[0] += ' ___ '
rows[1] += '|{} | '.format(str(rank).ljust(2))
rows[2] += '| {} | '.format(suit)
rows[3] += '|_{}| '.format(str(rank).rjust(2, '_'))
for row in rows:
print(row)
def dealer_action(cards, deck):
"""
Dealer's turn to draw cards. The dealer draws cards until
it has a score of 17 or higher
"""
cards.pop()
while calculate_score(cards) < 17:
new_card, deck = draw_card(deck)
cards.append((new_card[0], new_card[1]))
display_cards(dealer_cards=cards)
time.sleep(DEALER_SLEEP_TIME)
return cards, deck
def display_cards(user_cards=None, dealer_cards=None):
"""
Displays the given cards in a graphical format
"""
if dealer_cards:
if dealer_cards[1][1] == '#':
print('\nDEALER: ???')
else:
print(f'\nDEALER: {calculate_score(dealer_cards)}')
print_cards(dealer_cards)
if user_cards:
print(f'\nPLAYER: {calculate_score(user_cards)}')
print_cards(user_cards)
def get_results(user_cards, dealer_cards, bet, double_down):
"""
Calculates the result of the round, given the scores of the user
and dealer, and the bet.
Returns:
int: The result of the round, which can be either the bet * 2 if
the user has won, 0 if the user has lost, or the bet if it's a
tie.
"""
user_score = calculate_score(user_cards)
dealer_score = calculate_score(dealer_cards)
if double_down:
bet *= 2
if user_score > dealer_score and user_score <= 21:
bet *= 2
print('\n#####################################')
print(f'\nYou have won!!\n')
print('#####################################\n')
return bet
elif user_score < dealer_score and dealer_score > 21:
bet *= 2
print('\n#####################################')
print(f'\nYou have won!!\n')
print('#####################################\n')
return bet
elif user_score < dealer_score and dealer_score <= 21:
print('\n#####################################')
print(f'\nYou have lost!!\n')
print('#####################################')
return 0
elif user_score > 21 and dealer_score <= 21:
print('\n#####################################')
print(f'\nYou have lost!!\n')
print('#####################################')
return 0
else:
print('\n#####################################')
print(f'\nIt\' a tie!!\n')
print('#####################################\n')
return bet
def main():
money = 5000
while True:
if money <= 0:
print('No more money left')
print('Bye!')
sys.exit()
# Retrieve bet of the user
bet = get_user_bet(money)
money -= bet
# Create a new deck of cards
deck = get_deck()
# Deal out cards to the user and dealer
user_cards, dealer_cards, deck = deal_cards(deck)
# Allow the user to draw cards
user_cards, deck, double_down = user_action(user_cards, deck, bet, money)
# Deduct the bet once more when double down is True
if double_down:
money -= bet
# Allow the dealer to draw cards
dealer_cards, deck = dealer_action(dealer_cards, deck)
# Compare results and update money with result
result = get_results(user_cards, dealer_cards, bet, double_down)
money += result
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('Exit')
Happy coding ・‿・