Day 3: Rock Paper Scissors GUI In Python

Welcome to Day Three of my 21-day project series!

Today I’ll make a rock paper scissors game with a GUI interface in python that has nothing special. Except for a different code implementation.

But then why am I making it?

Because:

I love to play it.

And I thought of a different way to implement this instead of an if elif ladder.

Project Contents

I’ll make a simple GUI interface to play rock paper scissors using customtkinter. Which looks like this:

rock paper scissors gui game in python
Why do I always lose🥺

I wouldn’t get into the step-by-step explanation of the code as the article becomes super long. (And I guess boring too.)

But I would post an explanatory article for it soon.

Full Source Code

Here’s the full source code of the rock paper scissors game.

# FILE: rock_paper_scissors.py
import random

def game(your_choice: int) -> list:
    """
    Function to play a single round of Rock-Paper-Scissors game.

    Parameters:
    your_choice (int): The player's choice. Should be an integer between 0 and 2,
                       where 0 represents 'rock', 1 represents 'paper', and
                       2 represents 'scissors'.

    Returns:
    list: A list containing the results of the game round.
          The list elements are as follows:
          1. The player's choice.
          2. The computer's choice.
          3. The result of the round, which can be one of the following strings:
             - "Tie🤝" if the player and computer made the same choice.
             - "You won" if the player's choice beats the computer's choice.
             - "You lost" if the player's choice loses to the computer's choice.
    """
    choices = ["rock", "paper", "scissors"]
    computer_choice = random.randint(0, 2)
    
    # Create a dictionary to map the player's and computer's choices to outcomes
    outcomes = {
        (0, 0): "It's a Tie",
        (0, 1): "You lost",
        (0, 2): "You won",
        (1, 0): "You won",
        (1, 1): "It's a Tie",
        (1, 2): "You lost",
        (2, 0): "You lost",
        (2, 1): "You won",
        (2, 2): "It's a Tie",
    }

    result = [f"Your choice:\n{choices[your_choice]}", f"Computer's choice:\n{choices[computer_choice]}", outcomes[(your_choice, computer_choice)]]
    return result

GUI Code:

# FILE: rock_paper_scissors_gui.py
from customtkinter import *
from PIL import Image
from rock_paper_scissors import game


class RPS(CTk):
    """
    A class representing the Rock Paper Scissors game GUI.

    Inherits from customtkinter.CTk.

    Attributes:
    None

    Methods:
    __init__: Initializes the GUI and sets up the game window.
    check: Function to handle the player's choice and display the game result.

    Usage:
    app = RPS()
    app.mainloop()
    """
    def __init__(self) -> None:
        """
        Initializes the Rock Paper Scissors GUI.

        Creates and configures the main game window.

        Parameters:
        None

        Returns:
        None
        """
        super().__init__()
        self.title("Rock Paper Scissors")
        self.geometry("500x600")

        self.Label = CTkLabel(self, text="Choose Rock Paper or Scissors").grid(row=0,column=2,padx=150)

        # Create an instance of the CTkImage class for the 'rock' choice image
        # using the light_image parameter to load the image file from the given path.
        # The size parameter is set to (100, 100) to resize the image to the specified dimensions.
        self.rock_img = CTkImage(light_image=Image.open("images/rock.png"), size=(100,100))
        # Create an instance of the CTkButton class for the 'rock' choice button.
        # The image parameter is set to the previously created CTkImage instance,
        # so the button will display the 'rock' image as its icon.
        # The text parameter is set to an empty string to hide any text on the button.
        # The fg_color parameter is set to "#242424", which represents the foreground color (text color) of the button.
        # The hover_color parameter is set to "#242424", which represents the background color of the button when hovered.
        # The command parameter is set to a lambda function that calls the 'self.check()' method with argument 0,
        # representing the 'rock' choice, when the button is clicked.
        self.ilr = CTkButton(self, image=self.rock_img, text="", fg_color="#242424", hover_color="#242424", command=lambda: self.check(0))
        # Position the 'rock' choice button in the grid layout at row 1 and column 2.
        # The padx parameter is set to 150 to add horizontal padding around the button to create spacing.
        self.ilr.grid(row=1,column=2,padx=150)

        self.paper_img = CTkImage(light_image=Image.open("images/paper.png"), size=(100,100))
        self.ilp = CTkButton(self, image=self.paper_img, text="", fg_color="#242424", hover_color="#242424", command=lambda: self.check(1))
        self.ilp.grid(row=2,column=2,padx=150)

        self.scissors_img = CTkImage(light_image=Image.open("images/scissors.png"), size=(100,100))
        self.ils = CTkButton(self, image=self.scissors_img, text="",fg_color="#242424", hover_color="#242424", command=lambda: self.check(2))
        self.ils.grid(row=3,column=2,padx=150)


        self.qb = CTkButton(self, text="Exit", fg_color="red", hover_color="pink", text_color="white", command=self.quit)
        self.qb.grid(row=4,column=2,padx=150,pady=10)

    def check(self, player_choice: int) -> None:
        """
        Function to handle the player's choice and display the game result.

        Parameters:
        player_choice (int): The player's choice. Should be an integer between 0 and 2,
                             where 0 represents 'rock', 1 represents 'paper', and
                             2 represents 'scissors'.

        Returns:
        None
        """
        result = game(player_choice)
        res1 = CTkLabel(self, text=result[0],text_color ="#ADD8E6")
        res1.grid(row=5,column=2,padx=150,pady=10)
        res2 = CTkLabel(self, text=result[1], text_color="pink")
        res2.grid(row=6,column=2,padx=150,pady=10)
        res3 = CTkLabel(self, text=result[2])
        res3.grid(row=7,column=2,padx=150,pady=10)


if __name__ == "__main__":
    app = RPS()
    app.mainloop()

The code is well documented and well written it would be easy to understand.

Here are the links to topics within the rock paper scissors mini-project. You can check them if you have any doubts or confusion:

So how is the To-Do List interface?

Possible Improvements (That I’ll add after 21 days)

  1. Score Tracking
  2. Different Difficulty Levels
  3. Sound Effects
  4. Animated GUI
  5. Multiplayer Mode
  6. Light dark theme options

And yes, a better-looking GUI. I know now why my sista never lets me choose what to wear…

Experience of the day

In case you don’t know this project is a part of the brand new series that I have started. #21days21projects in python. To read more about it you can check out this page.

And for those who already know here’s my experience of the day.

Okay, so today’s experience was quite hectic. However, other than a random mood swing or a new web series😅😆😉 there was no chance to miss out on today’s challenge.

And I guess I should have started with some design inspiration beforehand it would have been much better.

But it’s ok I won’t repeat this mistake next time.

About the making of this game. I first started off with opening the result in a new window. But with GPT’s kind suggestion to improve user-friendliness, I decided to place it on the same window.

And I guess I wasted more than needed time on finding images only. Like ya, that was a super exciting task I just couldn’t stop myself.

As a result, I didn’t focus much on GUI and yes that’s why it sucks.

So, what do you think about the rock paper scissors game? Any more improvement suggestions on it?

And most importantly how was your DAY 3?

I hope it was fun. And remember it’s perfectly awesome if you missed out. Continue from tomorrow.

And today just write one line of code as simple as making a variable or printing something.

Your suggestions are welcomed!

Happy coding…

And wait, if you have some ideas for the upcoming projects do let me know that too.

Leave a Reply