Постоянный выбор ничего не делая

Поэтому я пытаюсь сделать простую игру в блэкджек на Python 3, и все работает отлично, за исключением того, что я терпеть не могу. Если я введу 2, он ничего не сделает. Заранее спасибо. РЕДАКТИРОВАТЬ 1: Удар работает хорошо. РЕДАКТИРОВАТЬ 2: Опубликовал весь сценарий, чтобы вы могли воспроизвести проблему, с которой я столкнулся, как предложил @roganjosh.

from random import shuffle
import sys


def deal(deck, player, dealer):
    shuffle(deck)

    for _ in range(2):
        player.append(deck.pop())
        dealer.append(deck.pop())

def score(hand):
    non_aces = [c for c in hand if c != 'A']
    aces = [c for c in hand if c == 'A']

    sum = 0

    for card in non_aces:
        if card in 'JQK':
            sum += 10
        else:
            sum += int(card)

    for card in aces:
        if sum <= 10:
            sum += 11
        else:
            sum += 1

    return sum

def display_info(player, dealer, stand):
    print("Your cards: [{}] ({})".format(']['.join(player), score(player)))
    if stand:
        print("Dealer cards: [{}] ({})".format(']['.join(dealer), score(dealer)))
    else:
        print("Dealer cards: [{}] [?]".format(dealer[0]))

def results(player, dealer, hand, stand):
    if score(player) == 21 and hand:
        print("Blackjack! You won!")    
        sys.exit()    
    elif score(player) > 21:
        print("Busted. You lost!")   
        sys.exit()     
    if stand:
        if score(dealer) > 21:
            print("Dealer busted. You won!")
        elif score(player) > score(dealer):
            print("You beat the dealer! You won!")
        elif score(player) < score(dealer):
            print("You lost!")
        else:
            print("Push. Nobody wins or losses.")
        sys.exit()

def hit_stand(deck, player, dealer, hand, stand):
    print("What would you like to do")
    print("[1] - Hit\n[2] - Stand")
    choice = input("> ")
    hand = False
    if choice == '1':
        player.append(deck.pop())
    elif choice == '2':
        stand = True
        while score(dealer) <= 16:
            dealer.append(deck.pop())

if __name__ == '__main__':
    deck = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']*4
    player = []
    dealer = []
    standing = False
    first_hand = True
    deal(deck, player, dealer)
    while True:
        display_info(player, dealer, standing)
        results(player, dealer, first_hand, standing)
        hit_stand(deck, player, dealer, first_hand, standing)

2 ответа

Решение

Вы не проверяете результат после того, как игрок решил встать. Так как вы только deal() один раз перед while True петля, вы просто получите бесконечное условие, если вы решите стоять несколько раз. Подсчитайте счет после того, как дилер забрал все свои карты.

def hit_stand(deck, player, dealer, hand, stand):
    print("What would you like to do")
    print("[1] - Hit\n[2] - Stand")
    choice = input("> ")
    hand = False
    if choice == '1':
        player.append(deck.pop())
    elif choice == '2':
        stand = True
        while score(dealer) <= 16:
            print(score(dealer))
            dealer.append(deck.pop())
        display_info(player, dealer, stand)
        results(player, dealer, first_hand, stand) # HERE

На несколько не связанной ноте вылет игры после определения окончательного результата не очень элегантен. Вы хотите посмотреть на лучшую конструкцию, чем while True: а также sys.exit() контролировать поток, но это упражнение для вас.

Наконец, вы не должны использовать sum как имя переменной внутри score() потому что это встроенная функция, которую вы переопределяете. Используйте что-то вроде total так что вы не рискуете замаскировать саму встроенную функцию.

Ответ @roganjosh правильный, но я хотел добавить еще одну заметку, потому что я думаю, что это действительно важный момент о том, как работает Python. Это то, что люди, пришедшие из C/C++/Java (то есть почти все мы), должны не учиться при использовании Python.

Как я уже говорил в комментариях выше, в оригинальном коде от Марии Лоры это выглядит как призыв к hit_stand предназначен для использования некоторых переменных (таких как stand) в качестве выходных переменных, и в Python у нас не может быть "выходных переменных" при вызове функции. Но Мария Лаура упомянула, что "удар работает хорошо", что означает, что параметр player был модифицирован. Итак, если мы не можем иметь "выходные переменные", то почему было значение player модифицируется функцией hit_stand ?

Когда код звонит hit_stand пять объектов передаются в функцию:

  • Объект списка, которому дано имя deck,
  • Объект списка, которому дано имя player,
  • Объект списка, которому дано имя dealer,
  • Булевый объект, которому дано имя hand,
  • Булевый объект, которому дано имя stand

Код за пределами этой функции также имеет имена (deck, player, dealer, first_hand, standing) указывая на эти же пять объектов. В коде hit_stand .append() метод вызывается на player а также dealer список объектов и .pop() метод вызывается на deck объект, поэтому все эти объекты видоизменены. Имена из вызывающей области все еще указывают на те же самые объекты, поэтому эти имена теперь будут видеть эти изменения.

История для hand а также stand это отличается. Внутри hit_stand функция, hand а также stand назначаются новые значения с = оператор. Как изложено в этой превосходной рецензии от Фредрика Лунда, = Оператор в Python не "меняет" переменную, он просто берет объект и связывает его с именем. Сами объекты не изменились, вместо этого они были заменены новыми булевыми объектами. Так что переменная standing во внешней области видимости все еще указывает на свой исходный логический объект, а переменная stand внутри функции указывает на совершенно новый логический объект, отличный от внешнего объекта. Мы ничего не можем сделать с переменными hand а также stand что будет видно во внешней области, не может быть такой вещи, как "передача по ссылке" или "выходной параметр", как у нас в других языках.

Это концепция, которая поначалу может показаться очень чужой, пока мы не изучим то, что узнали в нашем обучении C / C++ / Java.

Другие вопросы по тегам