站立选择不做任何事情

Standing choice not doing anything

所以我想在 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)

你不是在玩家选择停止后查看结果。由于在 while True 循环之前你只 deal() 一次,所以如果你选择重复站立,你只会得到一个无限条件。庄家抽完所有牌后计算得分。

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() 更好的结构来控制流程,但这对您来说是一个练习。

最后,您不应在 score() 中使用 sum 作为变量名,因为这是您要重新定义的内置函数。使用像 total 这样的东西,这样你就不会冒险屏蔽内置函数本身。

@roganjosh 的回答是正确的,但我想再补充一点,因为我认为这是关于 Python 如何工作的一个非常重要的观点。这是来自 C/C++/Java 背景的人(即我们几乎所有人)在使用 Python.

时需要取消学习的东西

正如我在上面的评论中所述,在 Maria Laura 的原始代码中,对 hit_stand 的调用似乎是为了使用一些变量(例如 stand)作为输出变量,并且在 Python 中我们不能在函数调用中使用 "output variables"。但是 Maria Laura 提到 "hitting works well",这意味着参数 player 正在被修改。所以,如果我们不能有 "output variables",那么为什么 player 的值被函数 hit_stand 修改了?

当代码调用hit_stand时,五个对象被传入函数:

  • 一个列表对象,其名称为 deck
  • 一个列表对象,其名称为 player
  • 一个列表对象,其名称为 dealer
  • 一个布尔对象,其名称为 hand
  • 一个布尔对象,其名称为 stand

此函数外的代码也有指向这五个相同对象的名称 (deck, player, dealer, first_hand, standing)。在 hit_stand 的代码中,在 playerdealer 列表对象上调用了 .append() 方法,在 [=16= 上调用了 .pop() 方法] 对象,所以所有这些对象都发生了变化。调用范围中的名称仍然指向那些相同的对象,因此这些名称现在将看到那些更改。

handstand 的情况不同。在 hit_stand 函数中,handstand 使用 = 运算符分配新值。如 this excellent write-up from Fredrik Lundh 中所述,Python 中的 = 运算符不是 "change" 变量,它只是获取一个对象并将其绑定到一个名称。 对象本身并没有改变,而是被新的布尔对象替换了。所以外部作用域中的变量standing仍然指向它原来的布尔对象,并且变量stand 函数内部指向一个全新的布尔对象,与外部作用域中的不同。我们无法对将在外部范围内看到的变量 handstand 做任何事情,不能像我们在其他语言。

这个概念起初看起来很陌生,直到我们不再学习我们在 C/C++/Java 教育中学到的东西。