I'm trying to make a rock-paper-scissors game, and am trying to verify the input.
我正在尝试制作一个石头剪刀游戏,并试图验证输入。
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())
If I enter the right input on the first try, everything works fine. But if I enter wrong input on first try, and enter the right input on the second time, I get None
in the output, instead of the first letter of the RPS options.
如果我在第一次尝试时输入正确的输入,一切正常。但是如果我在第一次输入时输入错误的输入,并在第二次输入正确的输入,我在输出中得到None,而不是RPS选项的第一个字母。
What am I missing?
我错过了什么?
4 个解决方案
#1
You're going to want to loop on input. What you're doing currently is recursively calling player1
, and the recursive case doesn't have an explicit return value (hence, None
is returned).
你想要循环输入。你当前正在做的是递归调用player1,并且递归的情况没有显式的返回值(因此,返回None)。
The way you do this is simple: while there is invalid input, prompt again. I'm using a modified version of this in the vein of the "while True break" style; it accomplishes the same goal. We loop indefinitely, and if the condition we want is valid, we return; otherwise, we prompt for input and loop again.
你这样做很简单:当输入无效时,再次提示。我正在使用这种修改版本的“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!"
As an alternative to that if
statement, there is a slightly more clean way to express it via the in
operator.
作为if语句的替代方法,有一种更简洁的方式通过in运算符表达它。
if x in ('r', 'p', 's', 'rock', 'paper', 'scissors'):
As an addendum to your original question (as it says that you have to do it recursively), I must strongly caution you against doing any input evaluation through recursion. Python has a call stack size of around 1,000, which means that you have a very finite (yet reasonably large) amount of tries before the program irrecoverably crashes.
作为原始问题的补充(因为它表示你必须递归地执行),我必须强烈提醒你不要通过递归进行任何输入评估。 Python的调用堆栈大小约为1,000,这意味着在程序无法恢复崩溃之前,您有一个非常有限(但相当大)的尝试次数。
Not just that, but your operation stack will be unnecessarily filled with method calls that behave in a similar fashion to a loop. For memory's sake in addition to the absolute recursion ceiling, do not use recursion for this.
不仅如此,您的操作堆栈将不必要地填充方法调用,其行为方式与循环类似。为了记忆,除了绝对递归上限之外,不要为此使用递归。
If you absolutely must, and again I strongly advise against doing this, then you simply have to return from your iterative case.
如果你绝对必须,我强烈建议不要这样做,那么你只需要从你的迭代案例中返回。
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())
#2
An improved version of @Makoto's example:
@ 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()
This is a little more concise than many or
expressions which gets a bit unwieldy if you have a lot of conditions you want to check!
这比许多或表达更简洁,如果你想要检查很多条件,它会变得有点笨拙!
A little explanation:
一点解释:
We're checking to see
x
(our user input) is in pre-defined list of valid inputs.我们正在检查x(我们的用户输入)是否在预定义的有效输入列表中。
An even more generalized version of this which becomes reusable:
一个更加通用的版本,可以重复使用:
Example: (reusable, non-recursion:)
示例:(可重用,非递归:)
#!/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"])
Demo:
$ 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: Sorry I didn't answer your question using recursion. IHMO this is not a good use-case for recursion. Oh well :) However; this is pretty easy to change:
PS:对不起,我没有用递归回答你的问题。 IHMO这不是递归的好用例。哦,好吧:)但是;这很容易改变:
Example: (reusable, recursive)
示例:(可重用,递归)
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
#3
In the else
branch your function (the first call to your function, in particular) doesn’t return
anything. In Python functions that do not return
anything always return None
implicitly.
在else分支中,您的函数(特别是对函数的第一次调用)不会返回任何内容。在Python中,不返回任何内容的函数总是隐式返回None。
#4
I'm adding this answer for completeness sake, as you do ask for a recursive solution. Here is my solution that is closest to yours:
为了完整起见,我正在添加这个答案,因为你要求递归解决方案。这是我最接近你的解决方案:
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()
As you can see, all you've forgotten is a return statement. A more readable way might be:
正如你所看到的,你所遗忘的只是一个回报声明。更可读的方式可能是:
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]
It would be even cleaner with a do while loop, but python lacks that construct.
使用while循环会更清晰,但python缺少该构造。
#1
You're going to want to loop on input. What you're doing currently is recursively calling player1
, and the recursive case doesn't have an explicit return value (hence, None
is returned).
你想要循环输入。你当前正在做的是递归调用player1,并且递归的情况没有显式的返回值(因此,返回None)。
The way you do this is simple: while there is invalid input, prompt again. I'm using a modified version of this in the vein of the "while True break" style; it accomplishes the same goal. We loop indefinitely, and if the condition we want is valid, we return; otherwise, we prompt for input and loop again.
你这样做很简单:当输入无效时,再次提示。我正在使用这种修改版本的“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!"
As an alternative to that if
statement, there is a slightly more clean way to express it via the in
operator.
作为if语句的替代方法,有一种更简洁的方式通过in运算符表达它。
if x in ('r', 'p', 's', 'rock', 'paper', 'scissors'):
As an addendum to your original question (as it says that you have to do it recursively), I must strongly caution you against doing any input evaluation through recursion. Python has a call stack size of around 1,000, which means that you have a very finite (yet reasonably large) amount of tries before the program irrecoverably crashes.
作为原始问题的补充(因为它表示你必须递归地执行),我必须强烈提醒你不要通过递归进行任何输入评估。 Python的调用堆栈大小约为1,000,这意味着在程序无法恢复崩溃之前,您有一个非常有限(但相当大)的尝试次数。
Not just that, but your operation stack will be unnecessarily filled with method calls that behave in a similar fashion to a loop. For memory's sake in addition to the absolute recursion ceiling, do not use recursion for this.
不仅如此,您的操作堆栈将不必要地填充方法调用,其行为方式与循环类似。为了记忆,除了绝对递归上限之外,不要为此使用递归。
If you absolutely must, and again I strongly advise against doing this, then you simply have to return from your iterative case.
如果你绝对必须,我强烈建议不要这样做,那么你只需要从你的迭代案例中返回。
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())
#2
An improved version of @Makoto's example:
@ 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()
This is a little more concise than many or
expressions which gets a bit unwieldy if you have a lot of conditions you want to check!
这比许多或表达更简洁,如果你想要检查很多条件,它会变得有点笨拙!
A little explanation:
一点解释:
We're checking to see
x
(our user input) is in pre-defined list of valid inputs.我们正在检查x(我们的用户输入)是否在预定义的有效输入列表中。
An even more generalized version of this which becomes reusable:
一个更加通用的版本,可以重复使用:
Example: (reusable, non-recursion:)
示例:(可重用,非递归:)
#!/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"])
Demo:
$ 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: Sorry I didn't answer your question using recursion. IHMO this is not a good use-case for recursion. Oh well :) However; this is pretty easy to change:
PS:对不起,我没有用递归回答你的问题。 IHMO这不是递归的好用例。哦,好吧:)但是;这很容易改变:
Example: (reusable, recursive)
示例:(可重用,递归)
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
#3
In the else
branch your function (the first call to your function, in particular) doesn’t return
anything. In Python functions that do not return
anything always return None
implicitly.
在else分支中,您的函数(特别是对函数的第一次调用)不会返回任何内容。在Python中,不返回任何内容的函数总是隐式返回None。
#4
I'm adding this answer for completeness sake, as you do ask for a recursive solution. Here is my solution that is closest to yours:
为了完整起见,我正在添加这个答案,因为你要求递归解决方案。这是我最接近你的解决方案:
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()
As you can see, all you've forgotten is a return statement. A more readable way might be:
正如你所看到的,你所遗忘的只是一个回报声明。更可读的方式可能是:
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]
It would be even cleaner with a do while loop, but python lacks that construct.
使用while循环会更清晰,但python缺少该构造。