Текстовый блэкджек

Я хотел сделать игру в блэкджек, чтобы пользоваться ею, когда мне скучно, но это оказалось намного сложнее, чем я думал.

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()

Первоначально я хотел добавить несколько AI-плееров, а также включить функции split и double, но код стал настолько сложным, что я подумал, что лучше не включать их, если код не был очищен.

Есть ли способ очистить это и упростить добавление дополнительных функций? Кроме того, есть ли что-нибудь еще, что можно было бы улучшить?

0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *