2015-12-28 93 views
2

使用VS2015Python 3.4
与此while计数器有一些问题。由于我确信它'应该'起作用,但它并没有更新柜台,它正在慢慢地让我疯狂。我跑步调试,可以看到计数器重置为3之前的条件线。至少可以说我很烦人。While循环计数器

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) 
+3

您是否收到错误?我收到一个错误。我得到'UnboundLocalError:在赋值之前引用的局部变量'counter'。这是你得到的错误? – Kevin

+0

这是真的,但是如果我移动定义的函数内部的变量,它会将while循环变为无限。请原谅我的无知,我对编码还很陌生。 –

+0

你不是一直在打破你的循环。在某些情况下,当你赢了,你会继续打球。检查所有循环中断场景 – FuriousGeorge

回答

1

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

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

你可以预期打印值是2,但是是3。全局变量在默认情况下是不可变的,并且试图在本地范围内修改它,而不使用global关键字,而是按照本地定义进行映射。请参阅this discussion以使用全局变量,但最好将程序重写为使用局部变量。

编辑: 也有一个错误,计数器初始化为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) 
+0

评论为什么我低估了非常欢迎... –

+0

我不知道为什么这个答案得到了downvote,这是完全正确的。 +1 – xXliolauXx

+1

我不是downvoter,但globals不是不可变的(至少不是元组和字符串)。创建一个全局列表变量,并从一个函数追加一个项目而不声明它是全局的。 – pat

0

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

您的循环似乎期望计数器从3开始倒数,因为只要counter为正数,它就会一直保持。顺便提一句,使用>=作为条件会使循环执行4次(3,2,1和0)。您可能需要将条件更改为严格大于,并将计数器增量更改为计数器递减。

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

接下来,丢失案例突破循环,但赢得案件不。如果你赢了,代码将循环,而不是修改计数器或任何其他输入,所以它不会终止。

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