2015-05-11 47 views
1

我正在試圖製作一個rock-paper-scissors遊戲, 並試圖驗證輸入。爲用戶輸入遞歸調用一個函數

def player1(): 
    x = (raw_input("please select: Rock(r)/Paper(p)/Scissors(s): ")).lower() 
    if x == 'r' or x == 'p' or x == 's' or x == 'rock' or x == 'paper' or x == 'scissors': 
     return x[0] 
    else: 
     print "Error - wrong input!" 
     player1() #I know I can run a While loop, but I need to run it this way. 

print(player1()) 

如果我在第一次嘗試時輸入正確的輸入,一切正常。 但是,如果我在第一次嘗試時輸入了錯誤的輸入,並且第二次輸入了正確的輸入,則輸出中會顯示None,而不是RPS選項的第一個字母。

我錯過了什麼?

+2

在發佈的代碼中的評論狀態'#我知道我可以運行一個While循環,但我需要這樣運行它.'似乎需要@JMG來進行遞歸調用。正如@kirelagin指出的那樣,在你的'else'中你需要:'return player1()' – Scott

+1

嗯(*我錯過了這個!*);但是,這不是一個遞歸IHMO的好用例:) –

回答

3

您將要循環輸入。你目前正在做的是遞歸調用player1,並且遞歸情況沒有明確的返回值(因此,返回None)。

你這樣做的方式很簡單:當輸入無效時,再次提示。我正在使用「True True break」風格的修改版本;它實現了相同的目標。我們無限循環,如果我們想要的條件是有效的,我們會返回;否則,我們會提示輸入並重新循環。

def player1(): 
    while True: 
     x = raw_input("please select: Rock(r)/Paper(p)/Scissors(s): ").lower() 
     if x == 'r' or x == 'p' or x == 's' or x == 'rock' or x == 'paper' or x == 'scissors': 
      return x[0] 
     else: 
      print "Error - wrong input!" 

作爲替代的是if說法,有通過in操作來表達它一個稍微更清潔的方式。

if x in ('r', 'p', 's', 'rock', 'paper', 'scissors'): 

作爲附錄你原來的問題(因爲它說,你必須遞歸地做到這一點),我必須強烈警告你不要通過遞歸做任何輸入評價。 Python的調用堆棧大小約爲1,000,這意味着在程序無法恢復崩潰之前,您的嘗試次數非常有限(但相當大)。

不僅如此,而且您的操作堆棧將不必要地填充與循環類似的方法調用。除了絕對遞歸天花板之外,爲了記憶的緣故,不要爲此使用遞歸。

如果絕對必須,我再次強烈建議這樣做,那麼你只需從你的迭代的情況下返回。

def player1(): 
    x = (raw_input("please select: Rock(r)/Paper(p)/Scissors(s): ")).lower() 
    if x == 'r' or x == 'p' or x == 's' or x == 'rock' or x == 'paper' or x == 'scissors': 
     return x[0] 
    else: 
     print "Error - wrong input!" 
     return player1() #I know I can run a While loop, but I need to run it this way. 

print(player1()) 
+0

在整個循環中放入第一個'raw_input',並在最後刪除多餘的第二個。 –

+0

好主意。我修改了答案。 – Makoto

+0

恐怕你沒有閱讀OP代碼中的註釋:'#我知道我可以運行一個While循環,但我需要這樣運行。「 – kirelagin

1

else分支你的功能(特別是你的功能的第一個調用)不return任何東西。在不包含return的Python函數中,隱式地返回None

+0

謝謝!有效!但出於一些奇怪的原因,第一次輸入錯誤的輸入時,它會打印出錯誤信息,並返回到第一個輸入行... – JMG

+0

@JMG「返回到第一個輸入行」是什麼意思? – kirelagin

4

的@誠的例子的改進版本:

def player1(): 
    x = raw_input("please select: Rock(r)/Paper(p)/Scissors(s): ").lower() 
    while True: 
     if x in ['r', 'p', 's', 'rock', 'paper', 'scissors']: 
      return x[0] 
     else: 
      print "Error - wrong input!" 
      x = raw_input("please select: Rock(r)/Paper(p)/Scissors(s): ").lower() 

這是多一點簡潔比許多or表情,如果你有很多的條件要檢查它變得有點笨拙!

一點解釋:

我們檢查,看看x我們的用戶輸入)爲有效輸入預先定義的列表。

一個甚至這成爲可重用更一般化版本:

實施例:可重複使用的,非遞歸:

#!/usr/bin/env python 


from __future__ import print_function # For Python 2/3 compat 


try: 
    input = raw_input # For Python 2/3 compat 
except NameError: 
    pass 


def prompt(prompt="Enter: ", valid=None): 
    s = input(prompt) 
    while valid and s not in valid: 
     print("Invalid input! Please try again. Valid inputs are {0:s}".format(" ".join(valid))) 
     s = input(prompt) 
    return s 


x = prompt("Enter action ([r]ock, [p]aper, [s]cissors): ", ["r", "p", "s", "rock", "paper", "scissors"]) 

演示:

$ python foo.py 
Enter action ([r]ock, [p]aper, [s]cissors): a 
Invalid input! Please try again. Valid inputs are r p s rock paper scissors 
Enter action ([r]ock, [p]aper, [s]cissors): foo 
Invalid input! Please try again. Valid inputs are r p s rock paper scissors 
Enter action ([r]ock, [p]aper, [s]cissors): r 

$ python foo.py 
Enter action ([r]ock, [p]aper, [s]cissors): a 
Invalid input! Please try again. Valid inputs are r p s rock paper scissors 
Enter action ([r]ock, [p]aper, [s]cissors): foo 
Invalid input! Please try again. Valid inputs are r p s rock paper scissors 
Enter action ([r]ock, [p]aper, [s]cissors): rock 

PS:對不起,我沒有用遞歸回答你的問題。 IHMO對於遞歸不是一個好的用例。 呵呵 :)然而;這是很容易改變:

例子:可重複使用的,遞歸

def userprompt(prompt="Enter: ", valid=None): 
    s = input(prompt) 
    while valid and s not in valid: 
     print("Invalid input! Please try again. Valid inputs are {0:s}".format(" ".join(valid))) 
     s = userprompt(prompt, valid) 
    return s 
+0

很棒的後記。 – Scott

+0

@Scott「postscript」? :) –

+0

我不確定笑臉是否意味着諷刺。附:是postscript的縮寫。 – Scott

0

我加入這個答案的完整性考慮,因爲你問一個遞歸解決方案。這裏是我的解決方案,是最接近你的:

def player1(): 
    x = (raw_input("please select: Rock(r)/Paper(p)/Scissors(s): ")).lower() 
    if x == 'r' or x == 'p' or x == 's' or x == 'rock' or x == 'paper' or x == 'scissors': 
     return x[0] 
    else: 
     print "Error - wrong input!" 
     return player1() 

正如你所看到的,你忘記了所有的是一個返回語句。一個更可讀的方式可能是:

def player1(): 
    playerInput=None 
    while playerInput not in ('r', 'p', 's', 'rock', 'paper', 'scissors'): 
     if playerInput is not None: 
      print("Error - wrong input!") 
     playerInput = raw_input("please select: Rock(r)/Paper(p)/Scissors(s)").lower() 
    return playerInput[0] 

這將是更乾淨的do while循環,但python缺乏這種構造。