3
\$\begingroup\$
import random

tries = 0
while tries <= 2:
    user_input = input("Enter your Symbol => ")
    possible_actions = ["Rock", "Paper", "Scissors"]
    computer_action = random.choice(possible_actions)
    score = 0

    print(f"Computer Chose {computer_action}")

    if user_input.lower() == "rock" and computer_action == "Scissors":
        print("You Won! ")
        tries += 1
        print(f"You have {3-tries} tries left")
        score += 1
    if user_input.lower() == "scissors" and computer_action == "Rock":
        print("You Lost!")
        tries += 1
        print(f"You have {3-tries} tries left")
    if user_input.lower() == "paper" and computer_action == "Rock":
        print("You Won!")
        tries += 1
        print(f"You have {3-tries} tries left")
        score += 1
    if user_input.lower() == "rock" and computer_action == "Paper":
        print("You Lost!")
        tries += 1
        print(f"You have {3-tries} tries left")
    if user_input.lower() == "scissors" and computer_action == "Paper":
        print("You Won!")
        tries += 1
        print(f"You have {3-tries} tries left")
        score += 1
    if user_input.lower() == "paper" and computer_action == "Scissors":
        print("You Lost!")
        tries += 1
        print(f"You have {3-tries} tries left")
    if tries == 3:
        print(f"You lost the competition as you had {tries} tries left")
    if score == 3 and tries == 3:
        print("You Won the competition")

This is a rock paper scissor game made using Python. Is there any way to make this code cleaner and prettier to look at? I tried to shorten it as much as possible. I also need to make it invulnerable to user errors like if the user inputs the wrong spelling.

\$\endgroup\$

3 Answers 3

1
\$\begingroup\$

Repeated calls to user_input.lower()

Make this call once:

while tries <= 2:
    user_input = input("Enter your Symbol => ").lower() #<---- here
    possible_actions = ["Rock", "Paper", "Scissors"]
    computer_action = random.choice(possible_actions)
    score = 0

    if user_input ==...

if elif elif elif...

You are repeating if for mutually exclusive conditions, use elif instead:

    if user_input == "rock" and computer_action == "Scissors":
        print("You Won! ")
        tries += 1
        print(f"You have {3-tries} tries left")
        score += 1
    elif user_input == "scissors" and computer_action == "Rock":
        print("You Lost!")
        tries += 1
        print(f"You have {3-tries} tries left")
    elif user_input == "paper" and computer_action == "Rock":
        print("You Won!")
        tries += 1
        print(f"You have {3-tries} tries left")
    ...

Win States

Instead of using if/elif to check for wins, you know what the player win conditions are. With this, you can use a set of tuples to check for membership, if the condition isn't there, the player has lost:

win_states = set(
     # win,   # lose
    ('rock', 'scissors'),
    ('scissors', 'paper'),
    ('paper', 'rock')
)

user = 'paper'
cpu = 'rock'

(user, cpu) in win_states
True

So now your if blocks are reduced to:

WIN_STATES = set(
     # win,   # lose
    ('rock', 'scissors'),
    ('scissors', 'paper'),
    ('paper', 'rock')
)


while tries <= 2:
    user_input = input("Enter your Symbol => ").lower()
    possible_actions = ["Rock", "Paper", "Scissors"]
    computer_action = random.choice(possible_actions).lower()
    score = 0

    print(f"Computer Chose {computer_action}")

    if (user_input, computer_action) in WIN_STATES:
        print("You won!")
        score += 1
    elif user_input == computer_action:
        print("Draw!")
    else:
       print("You lost!")

Tell the user what the choices are

The user has to read the code to figure out that they need to pick "Rock", "Paper", or "Scissors". Tell them in the prompt instead:

# these two don't change, so define them outside the loop
choices = ["Rock", "Paper", "Scissors"]
prompt = f"Choose one of {', '.join(choices)}: "

while tries <= 2:
    user_input = input(prompt).lower()
    computer_action = random.choice(choices).lower()
    ...

Tracking Counters

Instead of tracking tries as a counter, implement a for loop:

for attempt in range(3):
    print(f"Attempt number {attempt}")
    ...

Or, since you are using it to tell the user how many attempts are left, you can reverse the range:

for remaining in reversed(range(3)):
    print(f"You have {remaining} tries left")

You have 2 tries left
You have 1 tries left
You have 0 tries left
\$\endgroup\$
0
\$\begingroup\$

I think the most obvious improvement is to get your rounds and checks to work with the while/for loop, and the second would be to do at least some minimal "error handling" (what happens if a user types something where str.lower() isn't in ("rock", "paper", "scissors")?).

What I mean by the first line is that you can do the result checks after the while tries <= 2 loop breaks (so outside of it). Then you can get rid of the explicit if tries == 3 part (since we know there have been > 2 tries if we're outside of the loop).

You also have two errors in your logic in the final two checks; you look for if tries == 3 before looking for if score == 3 and tries == 3, which means that you will print both "You lost the competition [...] and You won the competition when a user has won, and you are missing the case where a user has 2 in score out of 3 tries (which should mean that they have won). You also make the user go through a 3rd play/try when they are 2-0 up (which also should be a win for them).

\$\endgroup\$
0
\$\begingroup\$

Instead of using if if if in a row use if then elif so that once a statement has been found that is True it won't go through the other if statements under it.

Think about what is the same for all statements such as the tries variable being increased. Instead of having it being increased in all of the ifs have it under them and outside of the if statements.

Code change:

from random import choice

MOVES = ["rock", "paper", "scissors"]

WINNING_MOVES = {
    "rock" : "scissors",
    "paper" : "rock",
    "scissors" : "paper"
}

def getMove():
    print('Moves : ', *MOVES)
    user_input = input("Enter your move > ").lower()
    if user_input in MOVES:
        return user_input
    return getMove()

tries = 3
score = 0
scoreRequired = 3

while tries > 0 and score != scoreRequired:
    user_input = getMove()
    computer_action = choice(MOVES)

    print(f"Computer Chose {computer_action}")

    if WINNING_MOVES[user_input] == computer_action:
        print("You Won! ")
        score += 1
    elif user_input == computer_action:
        print('Draw')
    else:
        print("You Lost!")
    
    tries -= 1
    print(f"You have {tries} tries left")

    if score == scoreRequired:
        print("You Won the competition")
    elif tries == 0:
        print(f"You lost the competition as you had {tries} tries left")
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.