Python is currently one of the most in-demand and versatile programming languages out there. Because it’s so heavily used across so many different industries, sectors, and technologies, that trend is expected to continue for the foreseeable future. Python is also one of the easiest programming languages to learn. Learning Python is an investment that will pay off for you for years to come.

I am a firm believer that the best way to learn anything is to not only dive in and get your hands dirty with it, but also to do something that’s fun. Instead of slogging though hours of lectures, let’s instead dive right in. And what better way to have fun than to code your own game? Today, you’re going to learn how to code a simple Rock-Paper-Scissors game using Python.

Rock-Paper-Scissors

In addition to being a great application to learn Python, Rock-Paper-Scissors is a simple, fun, and entertaining game for 2 players. Each player chooses rock, paper, or scissors. They simultaneously reveal their choice in a face off-style showdown to determine the winner. Rock-Paper-Scissors is often played as a Best-of-3.

  • Rock crushes Scissors
  • Scissors cuts Paper
  • Paper covers Rock

Plan Out the Python Script for the Rock-Paper-Scissors Game

Before writing any code, you need to sit down any plan out your program first. Without proper planning, your code will be bloated, slow, and inefficient. Break the task into a series of blocks or modules to start. Then, you can dive into the details and work out the exact logic of each module.

Think about how you might modularize the Rock-Paper-Scissors game. What steps or sections did you come up with? Here’s what I have.

  1. Input the User’s Move
  2. The Computer Makes Its Move
  3. Determine Which Player Won
  4. Inform the User Who Won

Break the Logic Down into the Smallest Nuts and Bolts You Can Think Of

Planning the logic is the hardest part of writing any program. The first version of logic for any program will likely not be the most efficient. It’s much easier to patch flaws and inefficiencies in your logic before you’ve written any code. We’ll write our logic out in a form of pseudocode before translating it into Python.

Thankfully, the simplicity of Rock-Paper-Scissors severely limits opportunities for bad logic. However, it does not eliminate them.

Input the User’s Move

Put your design hat on for a second. How you would input the user’s move? Think about games you’ve played before. What did you come up with? I thought of the following.

  • Prompt the user to enter their move by typing it in
  • Display three buttons and have the user click on a button

Since our Rock-Paper-Scissors game will initially not have a graphical user interface (GUI), let’s go with the first option. Adding a GUI is beyond the scope of this tutorial and will be covered is a future, more advanced lesson. When we prompt the user for their move, we’ll have them enter “R” for rock, “P” for paper, and “S” for scissors.

USER INPUT PROMPT: ENTER "R", "P", or "S"

Before we go any further, there’s already a flaw in the logic, here. Any guesses as to what it might be?

Fixing the Flaw in the User Input Logic

Have you figured out what the flaw is? What happens if you enter something other than “R”, “P”, or “S”? The program will crash. The easiest fix is to stick the input into a while loop to validate the user’s input. A while loop will repeat until one of the conditions it’s given is met. In our case, that loop will break when the user enters “R”, “P”, or “S”.

SET user_input TO ""
WHILE user_input NOT EQUAL TO "R", "P", or "S" THEN
    PROMPT TO SET user_input: ENTER "R", "P", or "S"
END WHILE

The Computer’s Turn

If you’re unsure of how to program the computer’s turn, you’re in luck. The logic is very simple. First, think about the last time you played Rock-Paper-Scissors. When it was your turn, what steps did you go through to make your move? I bet they looked something like this:

  1. Choose rock, paper, or scissors at random.
  2. Put your hand out in the shape of which item you chose

This is exactly how we’re going to code up the computer’s turn. We’ll map the numbers 1, 2, and 3 to “R”, “P”, and “S”, respectively. The computer will choose a number between 1 and 3 at random, and its selection will be compared to the user’s input to determine which player won.

SET rps_map TO [
    1 => "R",
    2 => "P",
    3 => "S",
]
SET computer_number TO RANDOM NUMBER BETWEEN 1 AND 3
SET computer_input TO rps_map[computer_number]

Determine Which Player Won

To determine which player won, simply compare the user’s choice (user_input) to the computer’s choice (computer_input). Before we do that, write out all possible outcomes.

User ChoiceComputer ChoiceWinner
Same as ComputerSame as UserTie
RockPaperComputer
RockScissorsUser
PaperRockUser
PaperScissorsComputer
ScissorsPaperUser
ScissorsRockComputer
All Possible Outcomes of Rock, Paper, Scissors

We can write the logic for each outcome in a series of if/else statements. The easiest way to group the statements is to look at the user’s input, and then compare the computer’s move for each scenario.

IF user_input = computer_input THEN
    IT'S A TIE
ELSE IF user_input = ROCK THEN
    IF computer_input = PAPER THEN COMPUTER WINS
    ELSE IF computer_input = SCISSORS THEN USER WINS
    END IF
ELSE IF user_input = PAPER THEN
    IF computer_input = ROCK THEN USER WINS
    ELSE IF computer_input = SCISSORS THEN COMPUTER WINS
    END IF
ELSE IF user_input = SCISSORS THEN
    IF computer_input = PAPER THEN USER WINS
    ELSE IF computer_input = ROCK THEN COMPUTER WINS
    END IF
END IF

Notify the User of the Result

Our Python script will output the results of the game to the Terminal window. However, before we can output anything, we first need to set the message that the user will see at the end of the game. When we determine which player won the game, we’ll set the final results output message as well.

SET result_msg TO ""
IF user_input = computer_input THEN
    SET result_msg TO "We both chose {rock/paper/scissors}. It's a tie!"
ELSE IF user_input = ROCK THEN
    IF computer_input = PAPER THEN 
        SET result_msg TO "Paper covers Rock. I win!"
    ELSE IF computer_input = SCISSORS THEN 
        SET result_msg TO "Rock crushes Scissors. You win!"
    END IF
ELSE IF user_input = PAPER THEN
    IF computer_input = ROCK THEN 
        SET result_msg TO "Paper covers Rock. You win!"
    ELSE IF computer_input = SCISSORS THEN
        SET result_msg TO "Scissors cuts Paper. I win!"
    END IF
ELSE IF user_input = SCISSORS THEN
    IF computer_input = PAPER THEN 
        SET result_msg TO "Scissors cuts Paper. You win!"
    ELSE IF computer_input = ROCK THEN 
        SET result_msg TO "Rock crushes Scissors. I win!"
    END IF
END IF

PRINT result_msg TO TERMINAL WINDOW

Translate Your Pseudocode into Python

Now, it’s time for the fun part. Writing out your logic in pseudocode comes with more benefits than just clean and optimized code. Once your logic is finalized, it’s incredibly easy to translate it into any programming language. While we’re using Python, you can just as easily translate it to PHP, Java, R, Perl, C#, or any other language of your choosing. Additionally, separating the logic design from the programming makes it easier to learn Python, since you can focus exclusively on Python.

Python Modules You Need to Import

Before you write any code, go through your pseudocode and see if any Python modules need to be installed and/or imported. For the Rock-Paper-Scissors game, you’ll need to import Python’s built-in random module. The random module generates the random numbers we need for the computer to take its turn.

#!/usr/bin/env python3
import random

The User’s Turn

To prompt the user for their turn, we’ll use Python’s input() function. Don’t forget to wrap it in a while loop to keep the program from crashing. Additionally, we’ll use the .lower() method to make the user’s input case-insensitive. The .lower() method converts a string to all lowercase.

user_input = ""
acceptable_inputs = ["r", "p", "s"]
user_prompt = "Make Your Move. Enter 'R' for rock, 'P' for paper, or 'S' for scissors: "

while user_input not in acceptable_inputs:
    user_input = input(user_prompt)
    user_input = user_input.lower()

The Computer’s Turn

Before we do anything, we need to first define the map that maps the number 1, 2, and 3 to rock, paper, and scissors, respectively. While you can easily use a list or array to define the map, it’s much easier to understand how the map works if we use a dictionary to define the map.

rps_map = {
   1: "R",
   2: "P",
   3: "S",
}

Next, we need to choose a random number. This is where the random module we imported comes into play. The randint() method chooses an integer at random based on the range you pass it. For example, to choose a random number between 30 and 70, use randint(30, 70). In the Rock-Paper-Scissors game, the computer is choosing a random number between 1 and 3.

computer_number = random.randint(1, 3).

Finally, we use the randomly generated number to determine the computer’s choice from the map. For example, if the computer chooses 1, the map states that rps_map[1] = "R". In other words, the computer chose “rock”.

computer_input = rps_map[computer_number]
computer_input = computer_input.lower()

Determining Who Won

Translating the pseudocode to determine the winner into Python is straight-forward. However, there is still one outstanding item that needs to be addressed. In the event of a tie, we need to output what both players chose. Recall this line from the pseudocode.

SET result_msg TO "We both chose {rock/paper/scissors}. It's a tie!"

Thankfully, Python makes substituting variables into strings very easy. All you need to do is insert a pair of open/closed curly braces where you want to put the variable. Then use the .format() method on the string to tell Python which variable you want to put into the string. You can add as many variables to a string as you wish.

For example, let’s say you prompt the user for their name. You want to say hello to them using their name. This is a perfect place to use variable substitution. If I entered my name at the prompt, it would output “Hello, Matt”.

name = input("Please Enter Your Name: ")
hello_message = "Hello, {}".format(name)
print(hello_message)

Since we are using “r”, “p”, and “s” to denote the user and computer’s choices, we need another map to give the full name of our choices. It would look pretty weird if the message read, “We both chose r. It’s a tie!”. We instead want it to read, “We both chose Rock. It’s a tie!” Define the map just like we did for the computer’s turn.

msg_map = {
   "r": "Rock",
   "p": "Paper",
   "s": "Scissors,
}

Then use variable substitution to generate the message for a tie game.

result_msg = "We both chose {}. It's a tie!".format(msg_map[user_input])

Fully translated into Python, the module determining the winner reads as follows.

result_msg = ""
msg_map = {
    "r": "Rock",
    "p": "Paper",
    "s": "Scissors",
}

if user_input == computer_input:
    result_msg = "We both chose {}. It's a tie!".format(msg_map[user_input])
elif user_input == "r":
    if computer_input == "p":
        result_msg = "Paper covers Rock. I win!"
    elif computer_input == "s":
        result_msg = "Rock crushes Scissors. You win!"
elif user_input == "p":
    if computer_input == "r":
        result_msg = "Paper covers Rock. You win!"
    elif computer_input == "s":
        result_msg = "Scissors cuts Paper. I win!"
elif user_input == "s":
    if computer_input == "p":
        result_msg = "Scissors cuts Paper. You win!"
    elif computer_input == "r":
        result_msg = "Rock crushes Scissors. I win!"

Display the Game’s Result in the Terminal Window

Once we know the result of the game, all we need to do is use Python’s print() function to print the result_msg variable to the Terminal window.

print(result_msg)

Additional Upgrades to Finalize the Script

Even though we have now translated our pseudocode into Python, we’re not done just yet. We still need to clean up and finalize the code, as well as add one more feature.

One Last Feature: The Game Runs Until You Lose

Let’s face it. Restarting the game after every single turn gets old fast. Instead, why not reward yourself for winning and keep taking turns until you lose. All you need to do is wrap the entire script in a while loop that breaks when the computer wins.

First, define a boolean (true/false) variable called user_is_victorious to monitor who wins. Initialize it at the beginning of the script and use it as the condition to determine if the player has won another turn.

#!/usr/bin/env python3
import random

user_is_victorious = True
while user_is_victorious:
    # Game Code Goes Here

How sharp is your logic? If you’re on top of your game, you should have noticed that we introduced another major flaw into the logic here. We initialized the user_is_victorious variable as true, but never set it later in the code. As a result, the while loop will run forever because the user_is_victorious variable never gets set to false, which is the condition necessary to break the loop. In the world of programming, we call that an infinite loop.

To fix it, we need to revise the code that determines which player won the game. Whenever the computer wins the game, just set the user_is_victorious variable to False.

if user_input == computer_input:
    result_msg = "We both chose {}. It's a tie!".format(msg_map[user_input])
elif user_input == "r":
    if computer_input == "p":
        result_msg = "Paper covers Rock. I win!"
        user_is_victorious = False
    elif computer_input == "s":
        result_msg = "Rock crushes Scissors. You win!"
elif user_input == "p":
    if computer_input == "r":
        result_msg = "Paper covers Rock. You win!"
    elif computer_input == "s":
        result_msg = "Scissors cuts Paper. I win!"
        user_is_victorious = False
elif user_input == "s":
    if computer_input == "p":
        result_msg = "Scissors cuts Paper. You win!"
    elif computer_input == "r":
        result_msg = "Rock crushes Scissors. I win!"
        user_is_victorious = False

Remove String Literals for Easier Readability and Maintenance

In our initial version of the Rock-Paper-Scissors game, we used a lot of string literals. What is a string literal you ask? It’s any string used directly in the logic.

While a single instance of a unique string literal is perfectly fine, string literals that are repeated throughout the Python script quickly become a nightmare to maintain. What happens if you have to change one of them? You have to go through the code and change every single one of them. If you miss one, your code will break.

To remove them, initialize a constant at the beginning of the script that stores each repeated string literal. Then use that constant in the logic. In the Rock-Paper-Scissors game, the string literals "r", "p", and "s" are the repeat offenders. Let’s define a few constants for them at the beginning of the script.

ROCK = "r"
PAPER = "p"
SCISSORS = "s"

Then, just go through the logic of your script and replace every instance of "r" with ROCK. Anywhere you find "p", put PAPER in its place. Swap out every instance of "s" with SCISSORS. That way, if you ever need to change their values, all you need to do is change them once in the constants at the top of the script. When you choose the constant names correctly, you code is much easier to read as well.

Document the Code for Future Reference

Once the current version of your code is finalized, go back and document it. I cannot stress this enough for anyone who is trying to learn Python. When I first started writing code back in the day, I was horrible at documenting code. I didn’t do it much, and the little bit that I did was next to worthless.

Then, one day, I had to go back and modify some code I hadn’t touched in over a year. You’d be amazed at how much you can forget in just a year. Because the code wasn’t documented properly, I had to spend over a week just rereading the code trying to figure out what the hell it was doing before I could even start editing it. The fact that I was a rookie at the time and the code was pretty crappy and unreadable didn’t help any either, but I digress.

After that incident, I have always made sure to properly document every block of code that I write. In addition, if you write readable code, you will expend far less effort documenting it. I have had clients come to me asking to revise code that I haven’t touched in years. With proper documentation, I can go in, know what the code is doing, and make the edits right away. As a result, turnaround times are measured in hours, not weeks.

To document the Rock-Paper-Scissors game, add a docstring to the top that describes what the script does and how to run it. Then go through the code and add comments anywhere it’s not clear what a block of code does.

The Final Result

You can download or clone the Rock-Paper-Scissors game from my Bitbucket Repository. The syntax is properly highlighted and the lines are numbered.

Run the Game

To run the Rock-Paper-Scissors game, open a Terminal or Command Prompt window and navigate to the folder with the Python script in it. Then execute the following command.

python3 rock-paper-scissors.py
Screenshot of a Terminal window playing the Rock, Paper, Scissors Python game.
What’s your record for consecutive wins?

A Big Bang Theory Challenge

If you think you’ve mastered the tutorial and feel comfortable working with the Python code, I have a challenge for you. Watch the YouTube clip from The Big Bang Theory at the top of this post. Then modify the Python code to create Sheldon’s Rock, Paper, Scissors, Lizard, Spock game. You can download the code from my Bitbucket Repository.

I’ll give you one hint to get started. Stick with entering single letters as the input. Since Scissors and Spock both start with the same letter, I would continue to denote scissors as "s" and use "k" to indicate Spock.

Future Learn Python Tutorials

In future tutorials, we’ll use some more advanced techniques to improve our Rock, Paper, Scissors game.

  • Add a graphical user interface (GUI) using Tkinter
  • Set the number of rounds instead of playing until you lose
  • Let 2 players play against each other instead of the computer

If you want to take a crack at any of those improvements before I can write the tutorials, please be my guest. I’d love to see what you come up with.

Conclusion

Coding your own game is one of the most fun and satisfying ways to learn Python. Because Python is so in-demand, it’s also an incredible investment you can make in yourself. Have you built anything cool with Python recently? Let me know either in the comments or on my Facebook page.

Top Photo: Rugged Cliffs Along the Pacific Coastline
Newport, Oregon – August, 2017

Comments are closed.