4
\$\begingroup\$

Code below, very new to python, would love some constructive criticism, mainly in relation to what I could have improved on, if my use of aces (where I subtract 10) is smart, and my use of functions?

The way my code works is it starts by dealing 2 cards to both the dealer and the user, this is done randomly, it then asks the user if they want another card...if they say no, the dealer gets their cards dealt, if they type yes, then they get another card and asked the question again. Aces I had trouble with utilizing so I basically just subtracted 10 from everyone who went over 21 because it's basically how people play blackjack (no one opts for a 1 if they can opt for an 11 and stay equal to or under 21).

For those wondering about the rules: Blackjack (twenty-one) is a casino game played with cards. The goal of the game to draw cards that total as close to 21 points as possible without going over. All face cards count as 10 points, aces count as 1 or 11, and all other cards count their numeric value.

The game is played against a dealer. The player tries to get closer to 21 (without going over) than the dealer. If the dealer busts (goes over 21) the player automatically wins (provided the player had not already busted). The dealer must always take cards according to a fixed set of rules. The dealer takes cards until he or she achieves a total of at least 17. If the dealer's hand contains an ace, it will be counted as 11 when that results in a total between 17 and 21 inclusive; otherwise, the ace is counted as 1.

import random

deck =(2,3,4,5,6,7,8,9,10,10,10,10,11) # main deck tuple including aces (aces become 1 if user > 21)
dealer_hand = [] # dealer list to hold cars
user_hand = [] # user list to hold cards
    
def draw(): # function that will be called to draw a random card from the deck
    new_card = random.choice(deck)
    return new_card

def dealer_draw(user_total):
    if user_total < 21:
        while sum(dealer_hand) < 17:
            dealer_hand.append(draw())
    return dealer_hand

def blackjack(): # game fuction
    for i in range(2): # for loop to draw 2 cards to both the user and dealer
        user_hand.append(draw())
        dealer_hand.append(draw())
        
    print(f'User has: {user_hand}')
    print(f'Dealer has: {dealer_hand}')
    
    continue_game = True # will be used to terminate while loop
    
    while continue_game == True and sum(user_hand) < 21:
        drawing = input("Would you like to draw another card (y/n)       : ").lower()
        
        if drawing == 'y': # if users types y, it draws another card
            user_hand.append(draw())
            
            if 11 in user_hand and sum(user_hand) > 21: # aces (11's) get converted to 1's if > 21
                user_hand.remove(11)
                user_hand.append(1)
                
            print(f'User now has has: {user_hand}')
            print(f'Dealer has: {dealer_hand}')
            
        else:
            continue_game = False        
        
    dealer_draw(sum(user_hand)) # Function to draw card for dealer (if necessary)
                              
    print("~~~~~~~~~~~~~~~~~ Final results ~~~~~~~~~~~~~~~~~")
    print(f"User has {user_hand} for a total of {sum(user_hand)}")
    print(f"Dealer has {dealer_hand} for a total of {sum(dealer_hand)}")
    
    if sum(user_hand) > 21: #if statements check for bust, then draws, then checks for values between user/dealer 
        print("User busts! Dealer wins")
    elif sum(user_hand) == sum(dealer_hand):
        print("Draw")
    elif sum(dealer_hand) > sum(user_hand) and sum(dealer_hand) <= 21:
        print("Dealer wins")
    else:
        print("User wins")
    

# Main Game
print('____________________________________________________________________')
print("                      Welcome to Blackjack           ")
print("Blackjack is a card game where the user goes against the dealer.")
print("Your Goal is to draw cards to get closest to 21 points,")
print("however you don't want to go above 21 points because you will lose!")


play_game = False
while play_game == False:
    play = input("          Would you like to play?     (y/n)       :       ").lower()

    if play == "y":
        blackjack()
        play_game = True
    elif play == "n":
        print('_______________________________________________________________')
        print("Goodbye")
        play_game = True
    else:
        print("You did not enter either 'y' or 'n'.")
\$\endgroup\$
3
  • \$\begingroup\$ First thing I can see is the variable play_game and while play_game == False: - it's kinda confusing and could use a different name like valid_option_chosen. \$\endgroup\$
    – lukstru
    Jun 4, 2022 at 9:40
  • \$\begingroup\$ I also just noticed a bug: Aces get converted to 1 for the user, but not the bank. \$\endgroup\$
    – lukstru
    Jun 4, 2022 at 11:26
  • \$\begingroup\$ In regular blackjack, between one and eight standard 52-card decks are shuffled together. In your code, you're drawing with replacement, which is equivalent to pulling out a fresh deck for every card drawn. Is that intentional? \$\endgroup\$
    – Jasmijn
    Jun 4, 2022 at 16:11

1 Answer 1

2
\$\begingroup\$

In regards to your question of your use of functions: I think you under utilize them. Note that I could remove a lot of your comments because it is clear from the code what the code does, just by extracting functions and naming them appropriately (i would recommend the chapter Naming Conventions from Uncle Bobs Clean Code). I think your solution with the aces is fine.

Oh and I also moved everything into a class so it's easier to restart the game by just initializing a new instance. This way the game can be played more than once without restarting the whole application.

import random


def draw_for(hand):
    deck = (2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11)  # main deck tuple including aces (aces become 1 if user > 21)
    new_card = random.choice(deck)
    hand.append(new_card)


class BlackJack:
    def __init__(self):
        self.user_hand = None  # init so pycharm doesn't warn
        self.dealer_hand = None

    def play(self):  # game function
        self.reset()
        self.draw_starter_cards()
        self.print_hands()

        self.main_action()
        self.dealer_draw_to_limit()

        self.print_final_hands()
        self.print_winner()

    def reset(self):
        self.dealer_hand = []
        self.user_hand = []

    def main_action(self):  # could use a better name
        continue_game = True
        while continue_game and not self.user_busted():
            drawing = input("Would you like to draw another card (y/n)       : ").lower()

            if drawing == 'y':
                self.user_draws()
                self.print_hands()
            else:
                continue_game = False

    def user_busted(self):
        return sum(self.user_hand) > 21

    def user_draws(self):
        draw_for(self.user_hand)

        if self.user_has_aces() and self.user_busted():
            self.convert_aces()

    def user_has_aces(self):
        return 11 in self.user_hand

    def convert_aces(self):
        self.user_hand.remove(11)
        self.user_hand.append(1)

    def dealer_draw_to_limit(self):
        if not self.user_busted():
            while sum(self.dealer_hand) < 17:
                draw_for(self.dealer_hand)
        return self.dealer_hand

    def print_winner(self):
        if self.user_busted():
            print("User busts! Dealer wins")
        elif sum(self.user_hand) == sum(self.dealer_hand):
            print("Draw")
        elif sum(self.user_hand) < sum(self.dealer_hand) <= 21:
            print("Dealer wins")
        else:
            print("User wins")

    def print_final_hands(self):
        print("~~~~~~~~~~~~~~~~~ Final results ~~~~~~~~~~~~~~~~~")
        print(f"User has {self.user_hand} for a total of {sum(self.user_hand)}")
        print(f"Dealer has {self.dealer_hand} for a total of {sum(self.dealer_hand)}")

    def print_hands(self):
        print(f'User has: {self.user_hand}')
        print(f'Dealer has: {self.dealer_hand}')

    def draw_starter_cards(self):
        for i in range(2):
            draw_for(self.user_hand)
            draw_for(self.dealer_hand)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.