Skip to content Skip to sidebar Skip to footer

Calling A Function Recursively For User Input

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

Solution 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).

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.

def player1():
    while True:
        x = raw_input("please select: Rock(r)/Paper(p)/Scissors(s): ").lower()
        ifx== 'r'orx== 'p'orx== 's'orx== 'rock'orx== 'paper'orx== '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 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.

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.

defplayer1():
    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())

Solution 2:

An improved version of @Makoto's example:

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.

An even more generalized version of this which becomes reusable:

Example: (reusable, non-recursion:)

#!/usr/bin/env pythonfrom __future__ import print_function  # For Python 2/3 compattry:
    input = raw_input  # For Python 2/3 compatexcept NameError:
    passdefprompt(prompt="Enter: ", valid=None):
    s = input(prompt)
    while valid and s notin 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:

Example: (reusable, recursive)

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

Solution 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.

Solution 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()
    ifx== 'r'orx== 'p'orx== 's'orx== 'rock'orx== 'paper'orx== '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:

defplayer1():
    playerInput=Nonewhile playerInput notin ('r', 'p', 's', 'rock', 'paper', 'scissors'):
        if playerInput isnotNone:
            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.

Post a Comment for "Calling A Function Recursively For User Input"