There are multiple things you could improve in your code.
The name of the game
I feel that it'd be better to call your game
method run_game
. You should also run it multiple times in a while loop, asking the user each time if they want to exit. When they say they want to exit, you can call the results
function to display the results.
The results
Not only do you never use the results
function, but you've indented it too far so it's inside the game
function. Make sure it's top-level so that other modules can use it. Also, you have spaces before the print
statements, but that's a minor thing.
I assume you're designing this module so that other modules can use it, but if not, make the global variables local and get rid of the if
at the end.
Better names for your result variables would be num_wins
, num_losses
, and num_ties
.
Your results
function would also be better if it were named print_results
, since the current name implies that it returns the results.
Storing the choices
First of all, don't name your variables var
. choices
is a better name. Also, you can just use a list instead of a dictionary, and use the indices to calculate who won. You could also reuse your choices
list while taking user input and while choosing a move for the computer.
choices = ['paper', 'scissors', 'rock']
Also, rather than using the names user
and computer
, call the variables where you store the user's and computer's choices something like user_move
and comp_move
user_move = input("Please choice scissors, paper or rock: ")
while user_move not in choices:
user_move = input("Please choice scissors, paper or rock: ")
comp_move = random.choice(choices)
one
and two
and finding the winner
To get the value associated with a key in a dictionary, you can simply do my_dict[my_key]
. It's not necessary to loop through the entire list and not break even once you've found the necessary key. You could have replaced that for loop with this (note that there's no need to use int()
on the value)
one = choices[user_move].index(1)
two = choices[comp_move].index(1)
However, we have changed the choices
variable to be a list of strings, and anyways, your logic won't work in case the user selects "rock" and the computer selects "paper", as @ThisIsAQuestion pointed out.
This way accounts for that error (I also renamed one
and two
to user_ind
and comp_ind
):
user_ind = choices.index(user_move)
comp_ind = choices.index(comp_move)
if user_ind == comp_ind:
num_ties += 1
elif user_ind - comp_ind < 2:
num_wins += 1
else:
num_losses += 1
However, this isn't very clear. A better way to do it would be like this, by checking if the computer's move is one index ahead (after using %
, of course)
if user_move == comp_move:
num_ties += 1
elif choices[(choices.index(user) + 1) % len(choices)] == comp_move:
num_losses += 1
else:
num_wins += 1
This second approach treats choices
like a cycle rather than just a linear list. The %
is to avoid accessing an index beyond the range of the list - it comes back to 0
if it's 3
(You can always hardcode 3
instead of len(choices)
).
The resulting code
import random
num_wins = 0
num_losses = 0
num_ties = 0
def run_game():
choices = ['paper', 'scissors', 'rock']
user_move = input("Please choice scissors, paper or rock: ")
while user_move not in choices:
user_move = input("Please choice scissors, paper or rock: ")
comp_move = random.choice(choices)
if user_move == comp_move:
num_ties += 1
print(f"BOTH with {user_move} - TIE")
elif choices[(choices.index(user) + 1) % len(choices)] == comp_move:
num_losses += 1
print(f"COMPUTER with {comp_move} - WIN!")
else:
num_wins += 1
print(f"USER with {user_move} - WIN!")
def print_results():
print("You win %d times!" % num_wins)
print("You lose %d times!" % num_losses)
print("You tie %d times!" % num_ties)
if __name__ == "main":
continue = 'y'
while continue.lower() == 'y':
run_game()
continue = input('Enter "y"/"Y" to continue')
print_results()
Edit: Using the walrus operator, as Aivar Paalberg suggested, would simplify the while loops.
0<2
\$\endgroup\$