Python Forum
Problem restricting user input in my rock paper scissors game
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Problem restricting user input in my rock paper scissors game
#1
Okay, I am a new Python Programmer, I am a beginner, I started doing this a few months ago. I have been working through various Python challenges I found on the internet to practice and learn. So, I am working on this one, it is a rock, paper scissors game, and I managed to get the code to work. But in order for me to call it complete I felt I needed to add some code to ensure that the user only enters in one of the three, rock, paper or scissors.

If figured at first that a while loop would work great for this, so I tried it, and here is the code:
def start():
player1 = input("Player one, What is your name? ")
user1="rock"
while user1 != "rock" or user1 != "paper" or user1 != "scissors":
user1 = input(player1 + ", you are up, what's it going to be, rock, paper or scissors? ")
user1 = user1.lower()
clear()
player2 = input("Player two, What is your name? ")
user2 = input(player2 + ", you are up, what's it going to be, rock, paper or scissors? ")
user2 = user2.lower()
return (player1, user1, player2, user2)

Please note, that I only added the while loop for the first input because I wanted to test it makes sure it worked before adding it for player two. This somehow makes the loop infinite and no matter what I enter it cycles back to the same question. I ran it through a debugger and it appears that as though my boolean arguments are being ignored. I figured that as long as the input was NOT rock, paper, or scissors then it should stay in the loop. if it's rock or paper or scissors it should exit the loop. Apparently this is not the case. Any suggestions?

I would appreciate more knowledge on how this loop works, most of the information i found in the internet was very simple with regards to this while loop so it may only work with single arguments, but this is why I am reaching out to you guys for help.

Okay, so failing that I figured an IF statement might work instead so I changed the code to read like this:
def start():
player1 = input("Player one, What is your name? ")
def player1_input():
user1 = input(player1 + ", you are up, what's it going to be, rock, paper or scissors? ")
user1 = user1.lower()
if user1 != "rock" or user1 != "paper" or user1 != "scissors":
print("Please enter one of the three: Rock, Paper or Scissors")
player1_input()
return user1
player1_input()
clear()
player2 = input("Player two, What is your name? ")
user2 = input(player2 + ", you are up, what's it going to be, rock, paper or scissors? ")
user2 = user2.lower()
return (player1, user1, player2, user2)

UGGH!!! Same problem!! So now I know that there is a problem with my conditions in that line. So it's not the while loop, it is the way I have written it. Please explain why this isn't working.

Okay, so here's the thing. I could have simply done it as a multiple choice, by having them enter 1, 2 or 3, and assigning the rock, paper scissors to each number and got it to work that way but I chose not to do that as I wanted to learn more about how to do exactly what I am explaining right now. Using the 1,2,3 idea was too easy basically.

So the goal is to allow the program to continue execution when one of the three words are entered and reject the rest. I am open to other methods and suggestions of how to do this other then the multiple choice input I had mentioned above.

I have written the code using the https://www.onlinegdb.com/, and when I am at home (I practice at work too, that's why I use GDB), I was using the Thonny IDE, so, the latest version of Thonny is python 3.7 and gdb, I never checked.

Thank you for you help.
Reply
#2
I would make a separate function to keep looping until it got a valid input and then return that string, like this:

def get_valid_input (player) :
	acceptable_answers = ('rock', 'paper', 'scissors')
	prompt = ", you are up, what's it going to be, rock, paper or scissors? "
	answer = 'BashBedlam was here.'
	while answer not in acceptable_answers :
		answer = input ('\n' + player +  prompt)
		answer = answer.lower ()
	return answer

def start():
	player1 = input("Player one, What is your name? ")
	player2 = input("Player two, What is your name? ")
	user1 = get_valid_input (player1)
	user2 = get_valid_input (player2)
	return (player1, user1, player2, user2)

print (start ())
Reply
#3
Since you are just starting this is a good time to write an input function that you can reuse in future projects.
def get_input(prompt, valid_values=None, converter=None):
    while True:
        value = input(prompt)
        if converter:
            try:
                value = converter(value)
            except:
                print('Invalid input')
                continue
        if valid_values:
            if not value in valid_values:
                print('Invalid input')
                continue

        return value

print(get_input('Enter a number ', converter=float))
print(get_input('Enter an integer ', converter=int))
print(get_input('Enter integer in range [1..10] ',
                converter=int, valid_values=range(1,11)))
print(get_input('Enter (R)ock, (P)aper, (S)cissor ',
                converter=lambda a: a.upper()[0], valid_values=('RPS')))
Output:
Enter a number a Invalid input Enter a number 3.14 3.14 Enter an integer 4.6 Invalid input Enter an integer 6 6 Enter integer in range [1..10] 11 Invalid input Enter integer in range [1..10] 10 10 Enter (R)ock, (P)aper, (S)cissor Lizard Invalid input Enter (R)ock, (P)aper, (S)cissor rock R
Used in the context of your game it might look something like this:
def get_input(prompt, valid_values=None, converter=None):
    while True:
        value = input(prompt)
        if converter:
            try:
                value = converter(value)
            except:
                print('Invalid input')
                continue
        if valid_values:
            if not value in valid_values:
                print('Invalid input')
                continue

        return value

def player(prompt):
    name = input(prompt)
    play = get_input(name + ' enter (R)ock, (P)aper or (S)cissor ',
                      converter=lambda a: a.upper()[0],
                      valid_values=('RPS'))
    return name, play

print(player("Player one, What is your name? "))
print(player("Player two, What is your name? "))
Write code for the general case. In your example you had a bunch of code for getting some input from player 1 and then a bunch of code for getting some input from player 2. Are player 1 and player 2 different? Does player one have any special requirements that are not shared by player two? Are the differences between player one and player two germane to playing Rock-Paper-Scissor?

Stop thinking that there is a Player One and a Player Two. There are two Players. They are the same. Especially so in a game like Rock-Player-Scissor where the players play at the same time. You should not have special code for each player. If you see repeated code it should make your eyes itch. It bothered me that I repeated the same line changing only "one" to "two". Think about what code you need for a player, write that code, and then reuse the code for each player.
Reply
#4
It works! But I have one question: When I programmed in C many years ago, the "user1 != "rock"...." line worked perfectly and also worked when I played with BASIC back in the day. Why doesn't it work with Python? Why do I have to resort to creating a list and executing the while statement or even the for statement from a list?

(Mar-18-2021, 02:26 PM)BashBedlam Wrote: I would make a separate function to keep looping until it got a valid input and then return that string, like this:

def get_valid_input (player) :
	acceptable_answers = ('rock', 'paper', 'scissors')
	prompt = ", you are up, what's it going to be, rock, paper or scissors? "
	answer = 'BashBedlam was here.'
	while answer not in acceptable_answers :
		answer = input ('\n' + player +  prompt)
		answer = answer.lower ()
	return answer

def start():
	player1 = input("Player one, What is your name? ")
	player2 = input("Player two, What is your name? ")
	user1 = get_valid_input (player1)
	user2 = get_valid_input (player2)
	return (player1, user1, player2, user2)

print (start ())
Reply
#5
(Mar-19-2021, 10:58 AM)ashergreen Wrote: It works! But I have one question: When I programmed in C many years ago, the "user1 != "rock"...." line worked perfectly and also worked when I played with BASIC back in the day. Why doesn't it work with Python?

You have an issue with your logic, not your Python code. This line will always evaluate to True, unless user1 is somehow simultaneously equal to all three values at once (not possible):
user1 != "rock" or user1 != "paper" or user1 != "scissors"
You could use and instead of or to fix this, or you could use in to evaluate the variable against a group of options (a tuple in this case):
user1 not in ("rock", "paper", "scissors")
Reply
#6
(Mar-19-2021, 11:14 AM)GOTO10 Wrote:
(Mar-19-2021, 10:58 AM)ashergreen Wrote: It works! But I have one question: When I programmed in C many years ago, the "user1 != "rock"...." line worked perfectly and also worked when I played with BASIC back in the day. Why doesn't it work with Python?

You have an issue with your logic, not your Python code. This line will always evaluate to True, unless user1 is somehow simultaneously equal to all three values at once (not possible):
user1 != "rock" or user1 != "paper" or user1 != "scissors"
You could use and instead of or to fix this, or you could use in to evaluate the variable against a group of options (a tuple in this case):
user1 not in ("rock", "paper", "scissors")

I tried the OR instead of AND and it didn't work. It appears that doing the list/tuple thing seems to be the only way to get it to work.
Reply
#7
This is an incorrect conclusion.
Quote:I tried the OR instead of AND and it didn't work. It appears that doing the list/tuple thing seems to be the only way to get it to work.
That you did not get it to work is no proof that any logical statement has to be written using "in". It is usually shorter, and in my opinion clearer, but an expression using "in" can be written using multiple comparisons strung together with "and" or "or", and maybe some parenthesis. I think your failing may be that you think C and Python logical expressions work the same way. If you don't really understand how "and" and "or" work in Python it is easy to get confusing results. Logically consistent, but not obvious to the new Python programmer.

Here is input verification using "and"
def player_input(player):
    inp = input(player + ' enter Rock, Paper or Scissor ').lower()
    while inp != "rock" and inp != "paper" and inp != "scissor":
        inp = input("Please enter Rock, Paper or Scissor ").lower()
    return inp

names = [input('Name for player 1 '), input('Name for player 2 ')]
plays = [player_input(name) for name in names]
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Exit function from nested function based on user input Turtle 5 330 Oct-10-2021, 12:55 AM
Last Post: Turtle
  Problem with my pong game code Than999 2 494 Sep-09-2021, 11:34 AM
Last Post: Than999
  Unable to access the user input value given to daterangepicker klllmmm 1 704 May-26-2021, 09:16 PM
Last Post: nilamo
  Rock Paper Scissors Project in Python ankitdixit 6 1,676 May-25-2021, 12:29 PM
Last Post: codypeltz41
  LinkedList by User Input SantiagoPB 5 1,277 Mar-03-2021, 09:54 PM
Last Post: deanhystad
  User input/picking from a list AnunnakiKungFu 2 768 Feb-27-2021, 12:10 AM
Last Post: BashBedlam
  Generate Random operator, take user input and validate the user mapypy 4 1,067 Feb-03-2021, 08:41 PM
Last Post: nilamo
  Loop back through loop based on user input, keeping previous changes loop made? hbkpancakes 2 1,205 Nov-21-2020, 02:35 AM
Last Post: hbkpancakes
  single input infinite output problem Chase91 2 686 Sep-23-2020, 10:01 PM
Last Post: Chase91
  user input for multi-dimentional list without a prior iteration using input() Parshaw 6 1,045 Sep-22-2020, 04:46 PM
Last Post: Parshaw

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020