4
\$\begingroup\$

This is my Rock Paper Scissors code for Python 3 with score count. I want to make it more readable and concise if possible.

import random


def player_choice(user_choice):  # Register and shows the players choice
    if user_choice == 1:
        print("The player chose rock")
    elif user_choice == 2:
        print("The player chose paper")
    else:
        print("The player chose scissors")


def computer_choice(cpu_choice):  # Register and shows the cpus choice
    if cpu_choice == 1:
        print("The computer chose rock")
    elif cpu_choice == 2:
        print("The computer chose paper")
    else:
        print("The computer chose scissors")


def result(user_choice, cpu_choice, player_score, cpu_score):  # Define the game result
    if user_choice == cpu_choice:
        return [player_score + 0.5, cpu_score + 0.5]
    elif user_choice == 1 and cpu_choice == 3:
        return [player_score + 1, cpu_score]
    elif user_choice == 2 and cpu_choice == 1:
        return [player_score + 1, cpu_score]
    elif user_choice == 3 and cpu_choice == 2:
        return [player_score + 1, cpu_score]
    else:
        return [player_score, cpu_score + 1]


def print_score(p_score, c_score):  # Identifies the result and print the total score
    print("Score:""\nPlayer:", p_score, "\nComputer:", c_score)


def validation_input():  # Validates the input
    while True:
        try:
            user_input = int(input("Put your choice:"))
            if user_input not in range(1, 4):
                print("We only accept commands between 1 and 3, according to the table, type again")
                continue
            if type(user_input) == int:
                break
        except ValueError:
            print("We only accept exact numbers")
            continue
    return user_input


print('''1 - Rock
2 - Paper
3 - Scissors''')  # Printing the instructions
human_score = 0
computer_score = 0
while True:  # The condition is not important since the loop will stop on line 68 if the user wishes so
    user = validation_input()
    player_choice(user)
    ai = random.randint(1, 3)
    computer_choice(ai)
    human_score, computer_score = result(user, ai, human_score, computer_score)  # Accumulate the score
    print_score(human_score, computer_score)
    command = int(input("Type 0 to stop the program, type any another number to keep playing"))
    if command == 0:
        break
\$\endgroup\$
1

1 Answer 1

1
\$\begingroup\$

The result function can be much shorter:

def result(user_choice, cpu_choice):
    game_result = (3 + user_choice - cpu_choice) % 3
    user_score = (0.5, 1.0, 0.0)[game_result]
    return (user_score, 1.0 - user_score)

I changed the following things:

  • Since the result of a single game does not depend on the previous results, it is easier to only compute a single result.
  • The result of a game can be computed by taking the difference of the choices.
  • The 3 + prevents the difference from getting negative. This is done because different programming languages choose to produce different results for the expression -2 % 3. Adding 3 prevents that.
  • game_result is now either 0, 1 or 2
  • This can be used in a small lookup table to produce the correct user_score.
  • Since user_score + cpu_score == 1.0 for a single game, there's no need to do the complicated calculation twice.
  • Returning a tuple (1.0, 0.0) instead of a list [1.0, 0.0] is more appropriate, since lists can change their size. This return value has always size 2, since there are only 2 players.

The code is a little trickier to understand, but it works. And it is more concise.

def choice_to_string(choice):
    return ('rock', 'paper', 'scissors')[choice - 1]

With that function, you can write:

print("{0} chose {1}".format('The player', choice_to_string(2))

The rest of the code is fine, except for the variable names. You are using way too many synonyms.

  • computer, cpu, ai all mean the same. Choose one of them and only use that.
  • human, user, player all mean the same. Choose one of them and only use that.

Writing technical documents and code is very different from writing a novel. In a novel, using different terms for the same thing is generally accepted, in code it is not.

Instead of asking the user alternatingly to type "1 to 3" and "0 or anything else" is too much of a burden. You can combine these into "type 1 to 3 to play, or 0 to quit". This allows a game to be played with 2 key strokes instead of 4.

\$\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.