【问题标题】:While loop counterWhile 循环计数器
【发布时间】:2016-04-02 10:03:01
【问题描述】:

使用VS2015Python 3.4
这个while 计数器有一些问题。它慢慢让我发疯,因为我确信它“应该”工作但没有更新计数器。我已经运行了步进调试,可以看到计数器在 while 条件行之前重置为 3。至少可以说让我很烦。

import random
import getpass
print ('Welcome to Rock, Paper or Sissors\nEnter an option.')
user_obj = getpass.getpass('Rock, Paper or Sissors: ').lower()
ai_obj = input('Rock, Paper or Sissors: ').lower()
rps = ('rock', 'paper', 'sissors')
#ai_rps = ['rock', 'paper', 'sissors']
#ai_obj = random.choice(ai_rps)
counter = 3
def rps_game(user_obj, ai_obj):
    print('Player selected %s ' % user_obj)
    print('Computer selected %s ' % ai_obj)
    condition = user_obj in rps and ai_obj in rps
    while condition == True and counter >= 0:     
        if user_obj == ai_obj:
            print('Its a draw!')
        elif user_obj == 'rock':
            if ai_obj == 'paper':
                print('You lose!')
                break
            else:
                print('You win!')
        elif user_obj == 'paper':
            if ai_obj == 'sissors':
                print('You lose!')
                break
            else:
                print('You win!')
        elif user_obj == 'sissors':
            if ai_obj == 'rock':
                print('You lose!')
            else:
                print('You win!')
                break    
    else:
        counter += 1 
        print('Invalid input, please select Rock, Paper or Sissors')
        rps_game(user_obj, ai_obj)

rps_game(user_obj, ai_obj)

【问题讨论】:

  • 您遇到错误了吗?我收到一个错误。我得到UnboundLocalError: local variable 'counter' referenced before assignment。这是你得到的错误吗?
  • 这是真的,但是如果我在定义的函数内移动变量,它会使 while 循环无限。请原谅我的无知我对编码还是很陌生。
  • 您并没有始终如一地打破循环。在某些情况下,您在获胜后会休息,而在其他情况下,您会继续比赛。检查所有的循环中断场景
  • 另请注意,在 while 循环中,您正在检查条件 == True,但在循环中您没有修改条件的值,因此这毫无意义。
  • 与 counter 相同(如果你从未点击过最后一个 else 语句)

标签: python loops while-loop counter


【解决方案1】:

counter 重置为其原始值,因为它是一个全局变量。 Python 中的全局变量的行为与其他语言中的不同。试试这个 sn-p:

counter = 3
def f():
    counter = 2 # Shadows global 'counter' by a newly defined one
f()
print (counter) # Prints 3 !

您可能期望打印的值为 2,但实际上是 3。全局变量默认是不可变的,如果没有 global 关键字尝试在本地范围内修改它,则会被本地定义隐藏。请参阅this discussion 以使用全局变量,尽管最好重新编写程序以使用局部变量。

编辑: 还有一个错误,counter初始化为3并且只递增,所以条件>=0总是会满足(从而产生了无限循环)。 你可以试试:

[...]
def rps_game(user_obj, ai_obj, counter):
    if counter <= 0:
         return
    print('Player selected %s ' % user_obj)
    print('Computer selected %s ' % ai_obj)
    while user_obj in rps and ai_obj in rps :
    [...]
    else:
        print('Invalid input, please select Rock, Paper or Sissors')
        rps_game(user_obj, ai_obj, counter-1)

rps_game(user_obj, ai_obj, 3)

【讨论】:

  • 我不知道为什么这个答案被否决了,这是完全正确的。 +1
  • 我不是反对者,但全局变量不是不可变的(至少在元组和字符串的意义上不是)。创建一个全局列表变量,并从一个函数将一个项目附加到它而不声明它是全局的。
  • 您给出的第一个示例对我来说很有意义,而且我理解(至少我认为我这样做 :P )函数之外的后续值声明将如何表现不同。我发现在 def() 内移动计数器会导致一个无限循环(这是因为使用原始用户输入导致条件调用不满足)而且,由于计数器变量在计数器时没有被“更新” -= 被执行。 *
  • (我不太明白 counter += 1 是如何被复制的,因为我在今天上午 10 点左右将它从添加到计数更改为从计数器中减去。抱歉)。虽然我不知道你可以在 func 调用的参数中添加这些变化。谢谢你的那个小宝石:) 仍然想念为什么,即使那样变量被更改为 local 。 . .等一下, 。 . . . .我敢打赌,声明没有帮助。 *掌脸
【解决方案2】:

包含计数器更新的else 是缩进的,因此它会暂时挂起。这意味着它仅在 while 循环终止时执行,因为条件为假(而不是在您中断时)。在这种情况下,当用户或 ai 输入不在有效输入列表中或计数器为负时,条件为假。计数器永远不会是负数,因为它从 3 开始并且只会递增。如果用户输入无效,则打印错误消息,计数器递增,然后您使用递归调用具有相同参数的函数。由于参数没有改变,函数应该做和刚才一样的事情,除非它依赖于全局数据(计数器)。但是,如果 counter 是本地的(在函数内部初始化),则函数的每次调用都会获得一个新副本。如果 counter 是全局的(在函数外部初始化,但在函数内部声明为全局),它仍然不起作用,因为您需要递减它。即使这样,由于其他输入都没有改变,它只会一遍又一遍地打印错误消息。

您的循环绑定似乎期望计数器从 3 开始倒计时,因为只要 counter 为正数,它就会一直运行。顺便说一句,使用&gt;= 作为条件将使循环执行4 次(3、2、1 和0)。您可能希望将条件更改为严格大于,并将计数器增量更改为计数器减量。

接下来,您将使用递归(函数调用自身),但这应该是不必要的,因为循环会将您返回到您需要的位置。

接下来,失败的案例会跳出循环,但获胜的案例不会。如果你赢了,代码会循环,不会修改计数器或任何其他输入,所以它不会终止。

最后,用户输入是从函数外部读取的,所以它在循环内永远不会改变。如果用户输入了非法值,循环将继续测试相同的值。您可能想在循环中读取用户输入。

【讨论】:

    猜你喜欢
    • 2020-11-13
    • 2016-02-27
    • 2015-07-08
    • 2015-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多