#StackBounty: #python #python-3.x #playing-cards Text Based Blackjack

Bounty: 50

I wanted to make a blackjack game to use while bored, but it turned out to be far more complicated than I thought.

from random import choice, randint

MASTER_DECK = ["A", "A", "A", "A",
               "2", "2", "2", "2",
               "3", "3", "3", "3",
               "4", "4", "4", "4",
               "5", "5", "5", "5",
               "6", "6", "6", "6",
               "7", "7", "7", "7",
               "8", "8", "8", "8",
               "9", "9", "9", "9",
               "10", "10", "10", "10",
               "J", "J", "J", "J",
               "Q", "Q", "Q", "Q",
               "K", "K", "K", "K"]


def setup(deck):
    """Sets up all game variables"""
    # Initialize all of the hands
    player_hand, deck = pick_cards(deck)
    dealer_hand, deck = pick_cards(deck)
    return deck, player_hand, dealer_hand


def pick_cards(deck):
    """Deals two random cards"""
    hand = []
    if len(deck) <= 6:
        deck = MASTER_DECK.copy()
    for card in range(0, 2):
        chosen_card = choice(deck)
        hand.append(chosen_card)
        deck.remove(chosen_card)
    return hand, deck


def print_ui(player_hand, dealer_hand, deck, game_state):
    """Prints out the display that tells the user there cards"""
    print()
    if game_state == "player_dealing":
        print("The dealer has these cards:n_, " + ", ".join(dealer_hand[1:]))
        print()
        print("You have these cards:n" + ", ".join(player_hand))
        print()
        print(f"There are {len(deck)} cards left in the deck")
    elif game_state == "dealer_dealing":
        print("The dealer has these cards:n" + ", ".join(dealer_hand))
        print()
        print("You have these cards:n" + ", ".join(player_hand))
        print()
        if have_won(player_hand, dealer_hand):
            print("You have beaten the dealer.")
        else:
            print("You have not beaten the dealer.")
    else:
        print("Something has gone wrong")
        while True:
            pass


def have_won(player_hand, dealer_hand):
    """Checks if the player has won"""
    numeric_player_hand = numeric_cards(player_hand.copy())
    player_hand_total = 0
    for card in numeric_player_hand:
        player_hand_total += card
    numeric_dealer_hand = numeric_cards(dealer_hand.copy())
    dealer_hand_total = 0
    for card in numeric_dealer_hand:
        dealer_hand_total += card
    if dealer_hand_total > 21:
        if player_hand_total > 21:
            return False
        return True
    if dealer_hand_total == 21:
        return False
    if dealer_hand_total < 21:
        if dealer_hand_total < player_hand_total <= 21:
            return True
        return False


def betting_phase(tokens):
    """Takes the users bet"""
    print(f"You have {tokens} tokens.")
    while True:
        try:
            bet = int(input("Please enter you bet: "))
            if int(bet) > 0:
                if (tokens - bet) >= 0:
                    break
                print("Do not bet more than you have.")
            else:
                print("Please enter a number greater than zero.")
        except ValueError:
            print("Please enter a number.")
    return tokens - bet, bet


def player_dealing(deck, player_hand, game_state):
    """Handles dealing to the player"""
    if not deck:
        print("As there are no more cards left, the round ends.")
        game_state = "dealer_dealing"
    else:
        while True:
            user_command = input("Would you like to hit or to stay? (H/S): ").lower()
            if user_command == "h":
                chosen_card = choice(deck)
                player_hand.append(chosen_card)
                deck.remove(chosen_card)
                break
            elif user_command == "s":
                game_state = "dealer_dealing"
                break
            else:
                print("Please only enter H for hit or S for stay.")
    return deck, player_hand, game_state


def dealer_dealing(deck, dealer_hand):
    """Handles dealing to the dealer"""
    while True:
        if not deck:
            break
        numeric_dealer_hand = numeric_cards(dealer_hand.copy())
        hand_total = 0
        for card in numeric_dealer_hand:
            hand_total += card
        if hand_total < 16:
            chosen_card = choice(deck)
            dealer_hand.append(chosen_card)
            deck.remove(chosen_card)
        elif hand_total == 16:
            if randint(0, 1):
                chosen_card = choice(deck)
                dealer_hand.append(chosen_card)
                deck.remove(chosen_card)
            else:
                break
        elif 11 in numeric_dealer_hand and hand_total > 21:
            for card_number, card in enumerate(numeric_dealer_hand):
                if card == 11:
                    numeric_dealer_hand[card_number] = 1
        else:
            break
    return deck, dealer_hand


def numeric_cards(hand):
    """Turns card letters into their number values"""
    for card_number, card in enumerate(hand):
        if card == "J" or card == "Q" or card == "K":
            hand[card_number] = 10
        elif card == "A":
            hand[card_number] = 11
        else:
            hand[card_number] = int(hand[card_number])
    hand_total = 0
    for card in hand:
        hand_total += card
    if hand_total > 21 and 11 in hand:
        for card_number, card in enumerate(hand):
            if card == 11:
                hand[card_number] = 1
    return hand


def play_again():
    """Allows user to play again or quit"""
    while True:
        play_again = input("Do you want to play again? (Y/N): ").lower()
        if play_again == "y":
            break
        elif play_again == "n":
            quit()
        print("Please only enter a Y or N")


deck = MASTER_DECK.copy()
tokens = 200

while True:
    game_state = "betting"
    playing_game = True

    deck, player_hand, dealer_hand = setup(deck)

    while playing_game:
        if game_state == "betting":
            tokens, bet = betting_phase(tokens)
            game_state = "player_dealing"
        else:
            print_ui(player_hand, dealer_hand, deck, game_state)
            deck, player_hand, game_state = player_dealing(deck, player_hand, game_state)
            if game_state == "dealer_dealing":
                deck, dealer_hand = dealer_dealing(deck, dealer_hand)
                if have_won(player_hand, dealer_hand):
                    tokens += 2 * bet
                print_ui(player_hand, dealer_hand, deck, game_state)
                playing_game = False
    if tokens:
        play_again()
    else:
        input("You have no more tokens to spend. Hit enter to quit.")
        quit()

Originally I wanted to add some AI players as well as including the split and double functions, but the code got so complicated that I thought it would be better not to include those unless the code was cleaned up.

Is there any way to clean this up and make it easier to add more features? As well, is there anything else that could be made better?


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.