Python Forum

Full Version: Another Rock, Paper, Scissors
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
import random


class GameItem:

    def __eq__(self, other):
        return type(other) == type(self)


class Rock(GameItem):
    name = 'Rock'
    win = 'Rock blunts Scissors'

    def __gt__(self, other):
        return isinstance(other, Scissors)


class Paper(GameItem):
    name = 'Paper'
    win = 'Paper covers Rock'

    def __gt__(self, other):
        return isinstance(other, Rock)


class Scissors(GameItem):
    name = 'Scissors'
    win = 'Scissors cuts Paper'

    def __gt__(self, other):
        return isinstance(other, Paper)


items_dict = {'R': Rock, 'P': Paper, 'S': Scissors}


class Player:
    def __init__(self, name):
        self.name = name
        self.wins = 0
        self.choice = None

    def choice_str(self):
        return f'{self.name} choose: {self.choice.name}'

    def score_str(self):
        return f'{self.name}\'s score: {self.wins}'

    def win_str(self):
        return f'{self.name} won because {self.choice.win}'


class HumanPlayer(Player):

    def make_choice(self):
        choices = ', '.join(item.name for item in items_dict.values())
        letter_choices = ', '.join(items_dict.keys())
        text = (f'{self.name} please choose from {choices}\n'
                f'Enter ({letter_choices}) ')
        while True:
            result = input(text).upper()
            item_choice = items_dict.get(result)

            if item_choice:
                self.choice = item_choice()
                return

            print('Incorrect choice!')


class ComputerPlayer(Player):

    def make_choice(self):
        choice = random.choice(tuple(items_dict.values()))
        self.choice = choice()


class Game:
    def __init__(self, player1, player2):
        self.player1 = player1
        self.player2 = player2
        self.ties = 0
        self.last_winner = None

    def check_result(self):
        if self.player1.choice == self.player2.choice:
            self.last_winner = None
            self.ties += 1
            return
        elif self.player1.choice > self.player2.choice:
            self.last_winner = self.player1
        else:
            self.last_winner = self.player2

        self.last_winner.wins += 1

    def output_result(self):
        print(f'{self.player1.choice_str()}, {self.player2.choice_str()}')

        if self.last_winner:
            print(self.last_winner.win_str())
        else:
            print('It was a tie!')

        print((f'{self.player1.score_str()}\n'
               f'{self.player2.score_str()}\n'
               f'Ties: {self.ties}\n'))

    def play(self):
        self.player1.make_choice()
        self.player2.make_choice()
        self.check_result()
        self.output_result()

    def main_loop(self):
        while True:
            self.play()
            result = input('Another round, Enter \'y\' ').upper()
            if result != 'Y':
                break


class GameMenu:
    def __init__(self):
        self.game = None
        self.mode_choices = tuple(number for number in range(4))
        self.modes_text = (f'\nPlease choose a game mode:\n'
                           '1 for human Vs computer\n'
                           '2 for computer VS computer\n'
                           '3 for human Vs human\n'
                           'or 0 to exit game'
                           f'Please choose from {self.mode_choices} ')
        print('Welcome to Rock, Paper, Scissors')

    def mode1(self, name):
        self.game = Game(
            HumanPlayer(name), ComputerPlayer('Computer1'))

    def mode2(self):
        self.game = Game(
            ComputerPlayer('Computer1'), ComputerPlayer('Computer2'))

    def mode3(self, name1, name2):
        self.game = Game(
            HumanPlayer(name1), HumanPlayer(name2))

    def main_loop(self):
        while True:
            result = input(self.modes_text)
            if result not in (str(number) for number in self.mode_choices):
                print('\nIncorrect choice!')
                continue
            if result == '0':
                print('Thank you, goodbye')
                break
            elif result == '1':
                self.mode1(
                    input('\nPlease enter your name Player 1 ').capitalize())
            elif result == '2':
                self.mode2()
            elif result == '3':
                self.mode3(
                    input('\nPlease enter your name Player 1 ').capitalize(),
                    input('Please enter your name player 2 ').capitalize())
            self.game.main_loop()


if __name__ == "__main__":
    GameMenu().main_loop()

Added another mainloop to enable the choice of another mode
Is there any way we get to quit to change from one mode to another? I had to quit the game to do so.
Sure I could make a change to it so that when you chose not to have another round, it goes back to the game mode option with the option to quit the game from there.
Very cool, thank you for sharing this! I've learned a few new concepts just reading through the code and figuring out how it works.
(Jun-29-2020, 04:46 PM)pyzyx3qwerty Wrote: [ -> ]Is there any way we get to quit to change from one mode to another? I had to quit the game to do so.
I have added the requested functionality