1
\$\begingroup\$

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.

\$\endgroup\$
1
  • \$\begingroup\$ 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. \$\endgroup\$
    – Teepeemm
    Dec 2 '21 at 21:18
2
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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