我试图制作一个石头剪刀游戏, 并且我正在尝试验证输入。
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选项的第一个字母。
我错过了什么?
答案 0 :(得分:4)
你想要循环输入。你当前正在做的是递归调用player1
,并且递归的情况没有显式的返回值(因此返回None
)。
这样做很简单:输入无效时,再次提示。我正在使用这种修改版本的“while 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,这意味着在程序无法恢复崩溃之前,你有一个非常有限(但相当大)的尝试次数。
不仅如此,而且您的操作堆栈将不必要地填充方法调用,其行为方式与循环类似。为了记忆,除了绝对递归上限之外,不使用递归。
如果你绝对必须,我强烈建议 反对 这样做,那么你只需要从你的迭代案例中返回。< / p>
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())
答案 1 :(得分:4)
@ Makoto的一个改进版本的例子:
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
答案 2 :(得分:1)
在else
分支中,您的函数(特别是对函数的第一次调用)不会return
。在没有return
的任何事情的Python函数中,总是隐式地返回None
。
答案 3 :(得分: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缺少该构造。