Python Forum
Rock, paper, scissors spelling error
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Rock, paper, scissors spelling error
#1
Question 
Hello! Hope everybody's fine.

Here I have written a RPS game:

player1 = input("Give player 1 a name:\n")
player2 = input("Give player 2 a name:\n")

while True:
    choice1 = input(f"{player1}, start the game:(rock/paper/scissors) ")
    choice2 = input(f"{player2}, it's your turn:(rock/paper/scissors) ")

    if choice1 == choice2:
        print("Same!")
    elif choice1 == 'rock':
        if choice2 == 'paper':
            print(f"{player2} wins!")
        else:
            print(f"{player1} wins!")
    elif choice1 == 'paper':
        if choice2 == 'scissors':
            print(f"{player2} wins!")
        else:
            print(f"{player1} wins!")
    elif choice1 == 'scissors':
        if choice2 == 'rock':
            print(f"{player2} wins!")
        else:
            print(f"{player1} wins!")
    else:
        print("Check the spelling.")

    if input("Continue?(y/n) ") == 'n': break
The problem is that this line:
print("Check the spelling.")
executes only when the 1st player misspells the input, and doesn't take the 2nd player's input into account.
1.How can I fix it?
2.Also any other suggestions for writing a simpler/shorter code for RPS game is much appreciated.

A huge thanks to everyone spending time answering the forums' questions. Heart
Reply
#2
it's an answer to both your questions - validate the user input. make a function that will ask for input until valid one is provided. then call that functions twice - for each of the players.

Also, you can simplify the long if list by using a dict to provide what wins over what. Search the forum - there were some good implementations of the game
banidjamali likes this post
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#3
The way your game is written, each combination has two possible outcomes when there should be three; player 1 wins, player 2 wins, player 2 had a typo.
while True:
    choice1 = input(f"{player1}, start the game:(rock/paper/scissors) ")
    choice2 = input(f"{player2}, it's your turn:(rock/paper/scissors) ")
 
    if choice1 == choice2:
        print("Same!")
    elif choice1 == 'rock':
        if choice2 == 'paper':
            print(f"{player2} wins!")
        elif choice2 == 'scissors':
            print(f"{player1} wins!")
        else:
            print("Check the spelling.")
    elif choice1 == 'paper':
        if choice2 == 'scissors':
            print(f"{player2} wins!")
        elif choice2 == 'rock':
            print(f"{player1} wins!")
        else:
            print("Check the spelling.")
    elif choice1 == 'scissors':
        if choice2 == 'rock':
            print(f"{player2} wins!")
        elif choic2 == 'paper':
            print(f"{player1} wins!")
        else:
            print("Check the spelling.")
    else:
        print("Check the spelling.")
 
    if input("Continue?(y/n) ") == 'n': break
That makes things really unwieldly. As buran suggests, the game logic is improved if you verify the input before playing the game.
player1 = input("Give player 1 a name:\n")
player2 = input("Give player 2 a name:\n")
 
while True:
    choice1 = verified_input(player1)
    choice2 = verified_input(player2)
 
    if choice1 == choice2:
        print("Same!")
    elif choice1 == 'rock':
        if choice2 == 'paper':
            print(f"{player2} wins!")
        else:
            print(f"{player1} wins!")
    elif choice1 == 'paper':
        if choice2 == 'scissors':
            print(f"{player2} wins!")
        else:
            print(f"{player1} wins!")
    elif choice1 == 'scissors':
        if choice2 == 'rock':
            print(f"{player2} wins!")
        else:
            print(f"{player1} wins!")
 
    if input("Continue?(y/n) ") == 'n': break
You can use the modulo operator to decide the winner. If we map the choices to integers, rock/paper/scissors = 0/1/2, the logic of the game becomes:

If player 1 == player 2, tie.
If player 2 == (player 1 + 1) % 3, player 1 wins, else player 2 wins.
def play(players):
    """Play a round.  Returns 0,1:players[N] wins, 2: Tie"""
    choices = {'rock':0, 'paper':1, 'scissor':2}
    p0 = verified_input(choices, players[0])
    p1 = verified_input(choices, players[1])
    if p0 == p1:
        return 2
    elif p1 == (p0 + 1) % 3:
        return 0
    return 1
As buran also suggests, this logic can also be embedded in a dictionary;
winner = {
    'rock/rock': 2,
    'rock/paper': 1,
    'rock/scissor': 0,
    'paper/paper': 2,
    'paper/scissor': 1,
    'paper/rock': 0,
    'scissor/scissor': 2,
    'scissor/rock': 1,
    'scissor/paper': 0
    }
Notice the repeating pattern of 2, 1, 0? That is what the modulo operator does in the prior example.
banidjamali likes this post
Reply
#4
(Jan-19-2021, 08:52 AM)buran Wrote: validate the user input
Thank you! they both helped a lot.
I did this:
player1 = input("Give player 1 a name:\n")
player2 = input("Give player 2 a name:\n")

choices = ['rock', 'paper', 'scissors']
def move(player):
    while True:
        choice = input(f"{player}, choose one:(rock/paper/scissors) ")
        if choice in choices: return choice
        print("Check the spelling.")

wins = {'rock': 'scissors', 'paper': 'rock', 'scissors': 'paper' }
while True:
    choice1 = move(player1)
    choice2 = move(player2)
    print(f"{player2} wins!" if choice1 == wins[choice2] else f"{player1} wins!" if choice2 == wins[choice1] else "Same!")
    if input("Continue?(y/n) ") == 'n': break
Out of curiosity, now in the
def move(player):
I validate the input which is in the function itself.
But can I define a validation function that uses 'while True' to validate an input that is defined outside of it? Like calling a validate function on any output that is outside of the function?!
Something like this:
answer = input("some stuff here: ")

def validate(parameter):
    while True:
        if parameter is blah blah: break
        print("correct the answer.")
        #some code to return to the answer outside

#Now calling the validate function on answer
validate(answer)
Reply
#5
Your validation function needs to "return" a value, not break. But otherwise, sure. Here's an example where a verify function is used along with an input function.
def verify_rps(choice):
    """Verify input and conver rock/paper/scissor to 0/1/2"""
    choices = {'rock':0, 'paper':1, 'scissor':2}
    choice = choices.get(choice.lower())
    if choice is None:
        print('Check spelling')
    return choice

def input_choice(prompt='', verify=None):
    """Request input"""
    while True:
        choice = input(prompt)
        if verify is None:
            return choice
        if (choice := verify(choice)) is not None:
            return choice

def play(players):
    """Play a round.  Returns 0,1:players[N] wins, 2: Tie"""
    p = [0, 0]
    for i, player in enumerate(players):
        prompt = f'{player} [rock/paper/scissor]: '
        p[i] = input_choice(prompt, verify_rps)
    
    if p[0] == p[1]:
        return 2
    elif p[0] == (p[1] + 1) % 3:
        return 0
    return 1
Notice that the input function is pretty generic. You could use the same input function with a different prompt and verify to get different inputs.
def verify_yes(choice):
    """Return True if choice == [Y]es, else False"""
    return choice[0] in 'yY'

if not input_choice('Play again [Yes/No]: ', verify_yes):
    break
banidjamali likes this post
Reply
#6
(Jan-19-2021, 12:04 PM)banidjamali Wrote: But can I define a validation function that uses 'while True' to validate an input that is defined outside of it? Like calling a validate function on any output that is outside of the function?!

You can always write a validation function that will take an argument and return True or False, based on some conditions. You don't need a loop though - you take one argument and check that argument against some conditions (i.e. no need of the loop at all)

Also, writing validation function makes sense if you perform some more complex validation. In this case it will not add much benefit and it can even be argued it complicates the code unnecessarily (i.e. compare if some_input in valid_inputs: vs if is_valid(some_input): where is_valid(param) is function that will do just return param in valid_inputs

couple of other things
  • in your function it would be better if choices is defined inside the function, or provided as argument.
  • something like this only makes the code more difficult to read and follow:
        print(f"{player2} wins!" if choice1 == wins[choice2] else f"{player1} wins!" if choice2 == wins[choice1] else "Same!")
  • many (me too) don't like one-line ifs like if choice in choices: return choice
player1 = input("Give player 1 a name:\n")
player2 = input("Give player 2 a name:\n")
 

def move(player):
    choices = ['rock', 'paper', 'scissors']
    while True:
        choice = input(f"{player}, choose one:({'/'.join(choices)}) ")
        if choice in choices:
            return choice
        print("Check the spelling.")
 
wins = {'rock':'scissors', 'paper':'rock', 'scissors':'paper'}
while True:
    choice1 = move(player1)
    choice2 = move(player2)
    if choice1 == choice2:
        print('Same')
    else:
        winner = player1 if choice2 == wins[choice1] else player2
        print(f'{winner} wins')

        # alternatively
        if choice2 == wins[choice1]:
            print(f'{player1} wins')
        else:
            print(f'{player2} wins')

    if input("Continue?(y/n) ") == 'n':
        break
banidjamali likes this post
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#7
@buran
@deanhystad
Thank you both for providing a lot of good information.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  I attempted to make a rock paper scissors bot for homework Intellectual11 3 2,888 Jun-24-2021, 08:00 PM
Last Post: deanhystad
  Rock, Paper, Scissors Game kramon19 2 5,319 Jan-10-2020, 08:18 AM
Last Post: perfringo
  I need help with a python Rock Paper Scissors game urgently. Riff_Raff 3 5,821 Dec-05-2018, 09:13 PM
Last Post: nilamo
  Rock, Paper, Scissors Advanced that saves, loads, and keeps statistics EvanCahill 0 5,197 Jul-21-2018, 07:32 PM
Last Post: EvanCahill
  Rock Paper Scissors Warmlawpk441 4 5,013 Oct-11-2017, 10:55 AM
Last Post: gruntfutuk
  Rock paper scissors game samiraheen 3 6,339 Oct-03-2017, 07:07 PM
Last Post: buran
  The Python Book altered rock paper scissors Python_Noob 0 2,907 Sep-18-2017, 06:13 AM
Last Post: Python_Noob
  HELP---problems with rock paper scissors games kalt91 2 4,110 Sep-15-2017, 04:51 PM
Last Post: micseydel
  Rock, Paper, Scissors game help.. hentera 3 5,031 May-19-2017, 10:56 PM
Last Post: ichabod801
  Rock Paper Scissors game codeobri 3 13,388 Apr-28-2017, 01:02 AM
Last Post: codeobri

Forum Jump:

User Panel Messages

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