2015-12-28 139 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)。您可能需要將條件更改爲嚴格大於,並將計數器增量更改爲計數器遞減。

接下來,您正在使用遞歸(函數調用自己),但這應該是不必要的,因爲循環讓您回到您需要的位置。

接下來,丟失案例突破循環,但贏得案件不。如果你贏了,代碼將循環,而不是修改計數器或任何其他輸入,所以它不會終止。

最後,用戶輸入是從函數外讀取的,所以它在循環內部不會改變。如果用戶輸入一個非法值,循環將繼續測試相同的值。您可能想要讀取循環內的用戶輸入。