Learn How to Build the Rock, Paper, Scissors Game in Python: Absolute Beginners Tutorial

Rock, Paper, Scissors is one of the best first projects you can build in Python. It is small enough to finish in one sitting, but it touches every skill that actually matters at the beginner level: getting input from the user, making decisions with conditionals, using the standard library, and keeping a program running with a loop.

By the end of this tutorial you will have a working terminal game that plays multiple rounds, tracks a score, and lets the player quit whenever they want. Every line of the final code is explained so you understand not just what it does but why it is written that way.

What the Program Will Do

Before writing any code, it helps to know what you are building. The finished program will do the following when run:

  1. Ask the player to type rock, paper, scissors, or quit.
  2. Have the computer pick a move at random.
  3. Compare the two moves, print who won the round, and update the score.
  4. Repeat until the player types quit, then print the final score.

That is four distinct behaviors, and each one maps to a specific Python concept. Asking for input maps to the input() function. Picking randomly maps to the random module. Comparing moves maps to if/elif/else. Repeating maps to a while loop. This is why game projects are so effective for learning: the game requirements drive you toward real-world patterns.

Prerequisites

This tutorial assumes you have Python 3 installed and can run a .py file from the terminal or an IDE like VS Code. You do not need any prior experience with the random module or game logic.

The Game Logic at a Glance

Rock beats scissors. Scissors beats paper. Paper beats rock. If both players choose the same thing, the round is a tie. That is all the domain logic this game requires, and you will represent it entirely with conditional statements.

Player Choice Computer Choice Result
rockscissorsPlayer wins
rockpaperComputer wins
rockrockTie
paperrockPlayer wins
paperscissorsComputer wins
scissorspaperPlayer wins
scissorsrockComputer wins
code builder click a token to place it

Build the correct Python function signature for a winner-checking function that takes two arguments:

your code will appear here...
computer return determine_winner ( def player : , ) class
Why: A Python function definition always starts with the keyword def, followed by the function name, then parentheses containing any parameters, and ends with a colon. class and return are not used in a function signature — class defines a class, and return belongs inside the function body.

The random Module and random.choice()

The random module is part of Python's standard library, which means it ships with Python and you never need to install it. To use it, you add one line at the top of your script:

python
import random

The function you will use is random.choice(). It takes a sequence — any list, tuple, or string — and returns one element chosen at random. Here is the only call you need for the computer's move:

python
choices = ["rock", "paper", "scissors"]
computer_choice = random.choice(choices)

Every time that line runs, computer_choice will be one of the three strings. random.choice() does not remove the chosen item from the list, so all three options remain available on the next call. That is the only randomness this program needs.

Pro Tip

You can test random.choice() in the Python REPL before writing your full program. Open a terminal, type python3, then run import random followed by random.choice(["rock", "paper", "scissors"]) a few times to see the output change.

Why a List and Not Three Separate Variables?

Storing the choices in a list has two advantages. First, random.choice() needs a sequence — it cannot pick from three separate variables. Second, the list makes input validation effortless. You can check whether what the player typed is valid with a single expression: player_choice in choices. If the player types something unexpected, that expression evaluates to False and you handle the error before any other logic runs.

What it returns
A single randomly selected element from a non-empty sequence.
Use in this project
Pick one of "rock", "paper", or "scissors" for the computer's move each round.
What it returns
A random integer N such that a <= N <= b. Both endpoints are included.
Use in this project
Not needed here, but you could use it to pick an index (0, 1, or 2) and then look up the corresponding choice in the list.
What it returns
A new list of k unique elements chosen from the population without replacement.
Use in this project
Not appropriate here since you only need one selection at a time, but useful if you ever build a card game that deals multiple unique cards from a deck.

Getting Player Input and Validating It

The input() function pauses the program and waits for the user to type a line and press Enter. It always returns a string, regardless of what the user types. For this game, you want to normalize the input so that typing Rock or ROCK works the same as typing rock:

python
player_choice = input("Enter rock, paper, scissors, or quit: ").strip().lower()

Two string methods are chained here. .strip() removes any leading or trailing whitespace the player may have accidentally typed. .lower() converts the entire string to lowercase. Chaining them means both transformations happen in one line before the value is stored in player_choice.

After normalizing, check whether the player wants to quit, and then check whether the input is valid:

python
if player_choice == "quit":
    break

if player_choice not in choices:
    print("Invalid choice. Please type rock, paper, or scissors.")
    continue

The break statement exits the while loop immediately. The continue statement skips the rest of the current loop iteration and jumps back to the top, which means the invalid input never reaches the winner-determination logic.

spot the bug click the line that contains the bug

The code below tries to read and normalize user input, then check if it is valid. One line contains a bug. Find it.

1 choices = ["rock", "paper", "scissors"]
2 player_choice = input("Your move: ").strip().upper()
3 if player_choice not in choices:
4 print("Invalid. Please type rock, paper, or scissors.")
5 continue
The fix: Change .upper() to .lower() on line 2. The choices list contains lowercase strings ("rock", "paper", "scissors"), so converting the input to uppercase means the not in choices check on line 3 will always be True and every valid input will be treated as invalid.

Putting It All Together: The Complete Game

Here is the full program. Read through it once before moving on to the step-by-step build section below.

python
import random

choices = ["rock", "paper", "scissors"]
player_score = 0
computer_score = 0

def determine_winner(player, computer):
    if player == computer:
        return "tie"
    wins_against = {"rock": "scissors", "paper": "rock", "scissors": "paper"}
    if wins_against[player] == computer:
        return "player"
    return "computer"

print("Rock, Paper, Scissors — type 'quit' to exit.\n")

while True:
    player_choice = input("Your move (rock/paper/scissors): ").strip().lower()

    if player_choice == "quit":
        break

    if player_choice not in choices:
        print("Invalid choice. Please type rock, paper, or scissors.\n")
        continue

    computer_choice = random.choice(choices)
    print(f"Computer chose: {computer_choice}")

    result = determine_winner(player_choice, computer_choice)

    if result == "tie":
        print("It's a tie!")
    elif result == "player":
        player_score += 1
        print("You win this round!")
    else:
        computer_score += 1
        print("Computer wins this round.")

    print(f"Score — You: {player_score}  Computer: {computer_score}\n")

print(f"\nFinal score — You: {player_score}  Computer: {computer_score}")
print("Thanks for playing.")
"Simple things should be simple, complex things should be possible." — Alan Kay

How to Build Rock, Paper, Scissors in Python

Follow these five steps to construct the game from scratch. Each step introduces one concept and adds it to the file you are building.

  1. Import the random module

    Create a new file called rps.py. On the very first line, write import random. This line tells Python to load the random module so that random.choice() is available later in the script. Imports always go at the top of a Python file.

  2. Define the valid choices and score variables

    After the import, declare choices = ["rock", "paper", "scissors"]. Then add player_score = 0 and computer_score = 0. These three names are used throughout the rest of the program, so they need to exist before the loop starts.

  3. Write the game loop with input validation

    Add while True: to start an infinite loop. Inside it, call input() and chain .strip().lower() to normalize what the player types. Check for "quit" first, then check whether the input is in choices. Use break to exit on quit and continue to skip invalid input.

  4. Have the computer choose and determine the winner

    After input validation passes, call random.choice(choices) and store the result. Then call determine_winner(player_choice, computer_choice). The function uses a dictionary to map each choice to what it beats, which is cleaner than nine separate if branches. Increment the right score variable based on what the function returns.

  5. Display results and print the final score

    After updating the score, print the round result and the running score inside the loop so the player sees it after each round. After the loop ends (when the player types quit), print the final score with a closing message. The code after a while loop runs once the loop exits, which is exactly what you need here.

Common Mistake

A while True loop without a break or an exit condition runs forever. Always make sure at least one code path inside the loop calls break. For this game, the only exit path is the player typing quit.

Understanding the wins_against Dictionary

The wins_against dictionary inside determine_winner encodes all three win conditions in one data structure:

python
wins_against = {"rock": "scissors", "paper": "rock", "scissors": "paper"}

Reading it: rock beats scissors, paper beats rock, scissors beats paper. The function checks whether wins_against[player] equals the computer's choice. If it does, the player wins. If neither the tie nor the win condition is true, the computer wins. This is a useful pattern to remember: when you have a fixed set of relationships between values, a dictionary is often cleaner than a long chain of elif statements.

Python Learning Summary Points

  1. import random loads the random module, which provides random.choice() for selecting a random element from a list.
  2. The input() function always returns a string. Chaining .strip().lower() normalizes the input so case and whitespace do not cause unexpected failures.
  3. A while True loop runs indefinitely until a break statement is reached, which is the standard pattern for terminal-based game loops in Python.
  4. The continue statement skips the rest of the current loop iteration. Using it after detecting invalid input prevents bad data from reaching the logic that depends on valid data.
  5. A dictionary can replace a long chain of elif statements when you are mapping one value to another. The wins_against pattern here is worth remembering for any project involving fixed rule sets.

From here, there are a number of natural extensions you can try: add a round limit so the game ends after five rounds, track win streaks, allow the player to choose how many rounds to play, or add a "best of N" mode. Each extension introduces a new concept without requiring you to rewrite what you have already built.

check your understanding question 1 of 4

Frequently Asked Questions

Building Rock, Paper, Scissors in Python teaches the random module, the input() function, if/elif/else conditional logic, a while loop for game replay, and basic function design. These are foundational control flow concepts every Python beginner needs.

Python uses random.choice() from the built-in random module. You pass it a list such as ["rock", "paper", "scissors"] and it returns one element at random each time it is called.

Use a while True loop and check the player's input after each round. When the player types quit, call break to exit the loop. This pattern is called a game loop and it is standard for terminal-based Python games.

input() is a built-in Python function that pauses the program and waits for the user to type something and press Enter. It always returns a string, so you may need to convert the result if you expect a number.

Use a conditional check before processing the input. For this game, check whether the player's choice is in the valid options list using the in operator. If it is not, print an error message and use continue to restart the loop iteration without processing the invalid round.

Yes, but functions make the code easier to read and reuse. Wrapping the win/lose/tie logic inside a determine_winner() function means you write that logic once instead of repeating it. Starting with inline code and then refactoring into functions is a good learning exercise.

random.choice() returns a single element selected at random from a non-empty sequence such as a list or a tuple. It does not remove the element from the sequence, so the same element can be selected again on the next call.

Declare integer variables such as player_score and computer_score before the game loop, then increment them with += 1 each time the respective player wins a round. Print the scores at the end of each round or when the player quits.