# I made a Rock paper scissors game with Python 3.8

If you could rate my code, 1-10. What will it be and provide reasoning on why you gave that answer, i feel like i could of written this code better but i don't know what i am missing or what i could have done to make it better

import random
print('Lets play Rock Paper Scissors')

user_point = 0     #To keep track of the points
bot_point = 0

for tries in range (1,4):

try:
user_guess = input('Rock Paper Scissors? ')
choices = ['Rock','Paper','Scissors']

bot_guess  = random.choice(choices) #Will randomly pick from the list 'choices'

while user_guess not in choices:#if the user tries to put in anything other then the choices given
print('Please enter the choices above!')
user_guess = input('Rock Paper Scissors? ')
except ValueError:
print('Please choose from the choices above ')  #Just in case user tries to put a different value type
user_guess = input('Rock Paper Scissors? ')

#DEBUG = "The bot did " + bot_guess

#print(DEBUG)

if user_guess == bot_guess:
print('Tie!')
elif user_guess == "Rock" and bot_guess == "Paper":
print('The bot earns a point!')
bot_point += 1
elif user_guess == 'Paper' and bot_guess == "Rock":
print('The user earns a point!')
user_point += 1
elif user_guess == 'Paper' and  bot_guess == 'Scissors':
print('The bot earns a point')
bot_point += 1
elif user_guess == 'Scissors' and bot_guess == 'Paper':
print('The user earns a point')
user_point += 1
elif user_guess == 'Rock' and  bot_guess == 'Scissors':
print('The user earns a point')
user_point += 1
elif user_guess == 'Scissors' and bot_guess == 'Rock':
print('The bot earns a point')
bot_point += 1

print('After ' + str(tries) + ' tries. ' + ' The score is')
print('The User: ' + str(user_point))
print('The Bot: ' + str(bot_point))

if user_point > bot_point:
print('THE USER IS THE WINNER!!!')
else:
print('THE BOT IS THE WINNER!!!')


I give it a 0 because I tied the bot and the bot still wins.

Just kidding.

Without considering some of the ways this could be made simpler and more compact (ie. strictly from a style guide point of view), this would be rated exactly a 4.88/10 (at least, that's what pylint is claiming):

************* Module rps
rps.py:3:13: C0303: Trailing whitespace (trailing-whitespace)
rps.py:6:47: C0303: Trailing whitespace (trailing-whitespace)
rps.py:7:13: C0303: Trailing whitespace (trailing-whitespace)
rps.py:9:19: C0326: No space allowed before bracket
for tries in range (1,4):
rps.py:9:21: C0326: Exactly one space required after comma
for tries in range (1,4):
rps.py:13:25: C0326: Exactly one space required after comma
choices = ['Rock','Paper','Scissors']
rps.py:13:33: C0326: Exactly one space required after comma
choices = ['Rock','Paper','Scissors']
rps.py:15:19: C0326: Exactly one space required before assignment
bot_guess  = random.choice(choices) #Will randomly pick from the list 'choices'
rps.py:17:0: C0301: Line too long (106/100) (line-too-long)
rps.py:21:110: C0303: Trailing whitespace (trailing-whitespace)
rps.py:21:0: C0301: Line too long (110/100) (line-too-long)
rps.py:32:22: C0303: Trailing whitespace (trailing-whitespace)
rps.py:35:23: C0303: Trailing whitespace (trailing-whitespace)
rps.py:38:22: C0303: Trailing whitespace (trailing-whitespace)
rps.py:41:23: C0303: Trailing whitespace (trailing-whitespace)
rps.py:44:23: C0303: Trailing whitespace (trailing-whitespace)
rps.py:45:58: C0303: Trailing whitespace (trailing-whitespace)
rps.py:59:37: C0303: Trailing whitespace (trailing-whitespace)
rps.py:1:0: C0114: Missing module docstring (missing-module-docstring)
rps.py:6:0: C0103: Constant name "user_point" doesn't conform to UPPER_CASE naming style (invalid-name)
rps.py:7:0: C0103: Constant name "bot_point" doesn't conform to UPPER_CASE naming style (invalid-name)

-----------------------------------
Your code has been rated at 4.88/10


It is OK to ignore the last 2 messages. Pylint thinks variable that are declared outside functions are supposed to be constants. But in this case the script is so short that creating functions doesn't make sense.

• formatting on the trailing comments:
bot_guess  = random.choice(choices) #Will randomly pick from the list 'choices'
while user_guess not in choices:#if the user tries to put in anything other then the choices given


much nicer to do: <code><one space>#<one space><comment>

bot_guess  = random.choice(choices) # will randomly pick from the list 'choices'
while user_guess not in choices: # if the user tries to put in anything other then the choices given

• The if-elif statements used to determine the winner can be simplified quite a bit. Think about it like this: there are only 3 outcomes, so you should only need 3 checks, at most. There are several ways to do it, but here is one I thought of:
    if user_guess == bot_guess:
print('Tie!')
elif choices.index(user_guess) == (choices.index(bot_guess) + 2) % 3:
print('The bot earns a point!')
bot_point += 1
else:
print('The user earns a point')
user_point += 1

• The list choices = ['Rock','Paper','Scissors'] is treated as a constant, so declare it at the top of the file, right after the import statements (and it actually should be in all UPPER CASE). Since the content won't change, it would be good practice to use a tuple instead of a list (just swap the square brackets [...] for parens (...)).

• Python 3.4 introduced a feature called f-strings that make string formatting a lot cleaner. Read the link for all †he details, but the main takeaway from it is that if you prefix a string literal with an f, it allows for string interpolation "on the fly":

print('After ' + str(tries) + ' tries. ' + ' The score is') # NO!!!
print(f'After {tries} tries, the score is') # YES!!!!

• The try-except block is not needed. You can replace it with:
user_guess = ''
bot_guess  = random.choice(choices)
while True:
user_guess = input('Rock Paper Scissors? ')
if user_guess in choices:
break
else:
print("you must pick a choice from the list!")

• You could also combine the user_point and bot_point into a single points variable, and assign negative points for the bot and positive points for the user. This is kind of like taking the users side: you earn points by winning, and lose them when the bot wins. The downside is that you can't keep track of how many points each player has earned, only the difference between the 2.

So in the end, I get this:

#!/usr/bin/env python3

import random

CHOICES = ('Rock', 'Paper', 'Scissors')
points = 0
print('Lets play Rock Paper Scissors')
for tries in range(1, 4):
user_guess = ''
bot_guess = random.choice(CHOICES)
while True:
user_guess = input('Rock Paper Scissors? ')
if user_guess in CHOICES:
break
else:
print("you must pick a choice from the list!")
print(f"The bot did {bot_guess}")
if user_guess == bot_guess:
print('Tie!')
elif CHOICES.index(user_guess) == (CHOICES.index(bot_guess) + 2) % 3:
print('The bot earns a point!')
points -= 1
else:
print('The user earns a point!')
points += 1
if points > 0:
print(f'After {tries} tries, THE USER IS THE WINNER BY {points}!!!')
elif points == 0:
print(f'After {tries} tries, IT\'S A TIE!!!')
else:
print(f'After {tries} tries, THE BOT IS THE WINNER BY {points * -1}!!!')

• the part about the CHOICES.index(user_guess) == (CHOICES.index(bot_guess) + 2) % 3: , May you explain it, im not understanding how it works. @Z4-tier May 8, 2020 at 1:18
• Sure, that one was a little tricky. if you have an array ['R', 'P', 'S'] then R is index 0, P index 1 and S index 2. It just happens that this array is ordered in a way such that, whichever option you choose, if you move 2 index positions to the right (wrapping around from S back to R) you always land on the item that will lose to the one you picked. So this basically says "If the user chooses the item that is 2 to the right of whatever the bot picks, then the bot wins". May 8, 2020 at 2:01
• And actually, looking at it now, CHOICES should probably be a tuple and not a list, since it should be immutable. I'll change it :) May 8, 2020 at 2:02
• Ohhhhhhh Thank you so much for clarification, but one more question, if the guess wraps around by two, always putting up the winning match up then what is the point of the % 3 part @Z4-tier May 8, 2020 at 2:27
• % is the remainder operator, it's what is making the guess wrap around. If you break that line down for a specific set up values, it works like this: say bot_guess = 'Scissors'. then CHOICES.index(bot_guess) == 2 since 'Scissors' is at index 2. So we get (CHOICES.index(bot_guess) + 2) % 3 == (2 + 2) % 3 == 4 % 3 == 1. If the user had picked the item at index 1 (paper) they would lose, but if they had picked the item at index 0 (rock), they win. In general, n % m will give the remainder after integer division of n divided by m. (2%4=2, 4%4=0, 6%4=2, 8%4=0) May 8, 2020 at 19:02