3
\$\begingroup\$
import random
#1 = Rock, 2 = Paper, 3 = Scissors
random_number = random.randint(1,3)
try:
  input = int(input("1 for rock, 2 for paper, 3 for scissors: "))
except ValueError:
  print("You didn't enter a number. You lose.")

if input == random_number:
  if input == 1:
    input = "Rock"
  elif input == 2:
    input = "Paper"
  else:
    input = "Scissors"
  if random_number == 1:
    random_number = "Rock"
  elif random_number == 2:
    random_number = "Paper"
  else:
    random_number = "Scissors"
  print(f"You chose {input} and the computer chose {random_number}. You Tie.")

elif (input==1 and random_number==2) or (input==2 and random_number==3) or (input==3 and random_number==1):
  if input == 1:
    input = "Rock"
  elif input == 2:
    input = "Paper"
  else:
    input = "Scissors"
  if random_number == 1:
    random_number = "Rock"
  elif random_number == 2:
    random_number = "Paper"
  else:
    random_number = "Scissors"
  print(f"You chose {input} and the computer chose {random_number}. You Lose.")

elif (input==1 and random_number==3) or (input==2 and random_number==1) or (input==3 and random_number==2):
  if input == 1:
    input = "Rock"
  elif input == 2:
    input = "Paper"
  else:
    input = "Scissors"
  if random_number == 1:

        random_number = "Rock"
      elif random_number == 2:
        random_number = "Paper"
      else:
        random_number = "Scissors"
      print(f"You chose {input} and the computer chose {random_number}. You Win.") 
      
    else:
      if type(input) is int:
        print("You chose an invalid number. You Lose.")

This code plays the "Rock, Paper, Scissors" game against the user. I was wondering how exactly should I handle my repeated nesting. I am looking for more organized code.

\$\endgroup\$
3
  • 4
    \$\begingroup\$ Hello And Welcome to CodeReview! The question should contain an explanation of what your code does, and the question title should be a descriptive summary of the question. Please, see How do I ask a good question? \$\endgroup\$ Commented Sep 25 at 14:37
  • 1
    \$\begingroup\$ The word constant has a special meaning in programming, it refers to variables that cannot be changed, and we refer to it as deeply nested. And it is not nested too deep in your example, you may want to look into python dictionary for converting numbers to text for starter \$\endgroup\$ Commented Sep 25 at 14:57
  • \$\begingroup\$ Since you are a new user: What should I do when someone answers my question?, especially about vote/accept. \$\endgroup\$
    – toolic
    Commented Nov 18 at 18:24

2 Answers 2

6
\$\begingroup\$

Error

I get an indentation error on my version of Python. Perhaps you are using a more forgiving version or you had a problem copying your code into the question.

DRY

Yes, the repeated code can be simplified greatly using a dictionary to map the input numerical guesses to strings for the output display and by factoring the code into a function. Here is an alternate version with these changes:

import random

random_number = random.randint(1,3)
try:
  input = int(input("1 for rock, 2 for paper, 3 for scissors: "))
except ValueError:
  print("You didn't enter a number. You lose.")

def print_result(result):
    guess_string = {
        1 : "Rock",
        2 : "Paper",
        3 : "Scissors"
    }
    print(f"You chose {guess_string[input]} and the computer chose {guess_string[random_number]}. You {result}.")

if input == random_number:
  print_result('Tie')
elif (input==1 and random_number==2) or (input==2 and random_number==3) or (input==3 and random_number==1):
  print_result('Lose')
elif (input==1 and random_number==3) or (input==2 and random_number==1) or (input==3 and random_number==2):
  print_result('Win')
else:
  if type(input) is int:
    print("You chose an invalid number. You Lose.")

Naming

You could give the variables more meaningful names. For example, random_number might be better as computer_guess, and input as user_guess.

input is a poor name for a variable because it matches the builtin function of the same name.

Comments

The comment can be deleted because it is redundant with the input function prompt message.

Documentation

The code should have a header docstring comment describing the purpose of the code:

"""
Rock, paper scissors game.
Here's how it works...
"""
\$\endgroup\$
1
  • 2
    \$\begingroup\$ This condition (input==1 and random_number==2) or (input==2 and random_number==3) or (input==3 and random_number==1) translates to random_number - (input % 3) == 1. Same for the winning condition. \$\endgroup\$ Commented Sep 25 at 15:22
6
\$\begingroup\$

1. Variable name

Do not use input as the variable name. Since input is also a function, if you define a variable name input you can no longer call the input function.

Use more descriptive names for variables. In my example, I use computer_choice and player_choice to represent the number generated and user enter respectively.

2. Repetition

When you find that you need to repeat your code, try to check your control flow and condition. Most of the time you can avoid those repetitions; in my example, I compute the stuff that needs to be computed before going to one level of nesting.

3. Learn more about data structure

There are a lot of useful data structures e.g. lists, dictionaries, sets, that can help you simplify complex tasks. In my example, I use list to store the text of the Rock, Paper, and Scissors, to make a shortcut to converting number to str.

4. Function and early return

One of the ways to avoid nesting is to extract code into functions; that way you can early return. In your code, if user didn't enter a number, you catch the exception but didn't exit gracefully and will continue to run and meet another error (you can use quit() to exit the program). In my example, I put the codes into a function and can early return.

Example

import random
def main():
    # Random Computer Choice
    computer_choice = random.randint(1,3)

    # Player Input Choice
    try:
        player_choice = int(input("1 for rock, 2 for paper, 3 for scissors: "))
    except ValueError:
        print("You didn't enter a number. You lose.")
        return
    
    # We define some win condition
    # They are tuple define as (player_choice, computer_choice)
    computer_win_condition = [(1, 2), (2, 3), (3, 1)]

    # We first check if player and computer choice are the same
    # if so, result is Tie
    if computer_choice == player_choice:
        game_result = "Tie"
    # then we check for the computer win condition
    # if the tuple is in computer_win_condition, we know player lose
    elif (player_choice, computer_choice) in computer_win_condition:
        game_result = "Lose"
    # If it is not tie and lose, it mean that the player wins
    else:
        game_result = "Win"

    # We create a new list such that rps[1] = "Rock" ...
    # This will allow us to easily convert integer to responding str
    rps = ["", "Rock", "Paper", "Scissors"]
    computer_str = rps[computer_choice]
    player_str = rps[player_choice]

    print(f"You chose {player_str} and the computer chose {computer_str}. You {game_result}.")

if __name__ == "__main__":
    main()
\$\endgroup\$

Your Answer

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

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