# Simple Rock Paper Scissors game in Python

I am trying to write a simple rock paper scissors game in pycharm using classes and pygame. So far, I have not incorporated pygame yet. My idea is to import images that change in regards to the user's choice and the computer's random choice.

This is what I have so far:

import random

class RockPaperScissors:

def __init__(self):

self.wins = 0
self.losses = 0
self.ties = 0
self.options = {'rock': 0, 'paper': 1, 'scissors': 2}

def random_choice(self):
return random.choice(list(self.options.keys()))

def check(self, player, machine):

result = (player - machine) % 3
if result == 0:
self.ties += 1
print("It is a tie!")
elif result == 1:
self.wins += 1
print("You win!")
elif result == 2:
self.losses += 1
print("The machine wins! Do you wish to play again?")

def score(self):

print(f"You have {self.wins} wins, {self.losses} losses, and "
f"{self.ties} ties.")

def play(self):

while True:
user = input("What would you like to choose? (The choices are ROCK,PAPER,SCISSORS): ").lower()
if user not in self.options.keys():
print("Invalid input, try again!")
else:

machine_choice = self.random_choice()
print(f"You've picked {user}, and the computer picked {machine_choice}.")
self.check(self.options[user], self.options[machine_choice])

def re_do(self):
retry = input('Do you wish to play again? (y/n): ').lower()
if retry == 'n':
exit()
elif retry == 'y':
self.play()
else:
print("Invalid input")

if __name__ == "__main__":
game = RockPaperScissors()
while True:
game.play()
game.score()
game.re_do()


In the future, I would like to convert this to use pygame.

• Could you double check your indentation? If you highlight everything and click {}, that should get you started. Otherwise, your last few lines aren't rendering correctly. Dec 2 '21 at 21:18

# Good things

You mostly follow PEP8 styling conventions, making your code quite readable. The only exception I see is an extra blank line at the beginning of the score and play methods.

Also, it is good thinking to wrap your game state into a class for future integration into a more complex project. It is also a good use of a main guard at the end.

However, there are things that need to be improved to reach your end goal.

# Things to improve

## Game loop logic

Your game loop logic fails completely: execution loops forever inside the play() method, and thus the game.score() and game.re_do() are never called. The game never ends and the total score is never diplayed.

You should remove one of the infinite loop, and handle it properly.

I would have a run(self) instance method that goes something like this:

class RockPaperScissors

# some stuff

def run(self):
play_again = True
while play_again:
player_move = get_player_input()
machine_move = get_machine_input()
winner = get_winner(player_move, machine_move)
show_message(winner, score)
play_again = get_yes_no_input()

if __name__ == "__main__":
game = RockPaperScissors()
game.run()


It still has some issues I'll address later (for later integration in a PyGame project), but at it should behave as expected potential issues can be worked on one at a time, in each of the method called.

## Separation of concern

Although you tried to separate logic (by implementing a game class) from display, you failed and mix both all over the code.

For example, the check() method should return the winner instead of displaying a message. Further down the line, if you want to implement a GUI with PyGame, you can handle a function return, or query the state of member variables, but a print output will be no use.

Same goes from getting input. Eventually, inputs will be supplied by a PyGame instance through widgets or something. You should put all console-related actions (print and input) in separate methods that you should be able to override, depending on how you want to use the game class.