A rock paper scissors game in Python fits in about 30 lines: store which move beats which in a dictionary, let the computer pick with random.choice(), and compare. The whole rule set is one line:
BEATS = {"rock": "scissors", "paper": "rock", "scissors": "paper"}
result = "tie" if you == comp else ("you" if BEATS[you] == comp else "computer")
I played the game below in a real Command Prompt on Python 3.12.5, typing my moves, including one bad input on purpose.
We’ll check the rules for every pair, build a best-of-five game with input validation and a score, try a clever modulo version, add Lizard and Spock, and simulate thousands of games.
Rock paper scissors rules in Python
You’ll find a dictionary where each key beats its value makes the logic easy to read and hard to get wrong. Printing all nine matchups is a quick way to test it:
BEATS = {"rock": "scissors", "paper": "rock", "scissors": "paper"} # key beats value
def winner(you, computer):
if you == computer:
return "tie"
return "you" if BEATS[you] == computer else "computer"
for you in BEATS:
for comp in BEATS:
print(f"{you:<8} vs {comp:<8} -> {winner(you, comp)}")
Output:
rock vs rock -> tie
rock vs paper -> computer
rock vs scissors -> you
paper vs rock -> you
paper vs paper -> tie
paper vs scissors -> computer
scissors vs rock -> computer
scissors vs paper -> you
scissors vs scissors -> tie

Testing every combination like this takes seconds and catches logic slips. Nested loops over the dictionary keys do the work; see the Python for loop for more.
Rock paper scissors game in Python: best of five
Your game loop keeps asking until someone reaches three wins. It accepts r, p or s as shortcuts and re-asks on anything else, so a typo never crashes it:
import random
BEATS = {"rock": "scissors", "paper": "rock", "scissors": "paper"} # key beats value
def winner(you, computer):
if you == computer:
return "tie"
return "you" if BEATS[you] == computer else "computer"
SHORT = {"r": "rock", "p": "paper", "s": "scissors"}
def play(best_of=5):
random.seed(42) # fixed seed so this demo is repeatable
score = {"you": 0, "computer": 0}
need = best_of // 2 + 1
while max(score.values()) < need:
move = input("Rock, paper or scissors (r/p/s)? ").strip().lower()
move = SHORT.get(move, move)
if move not in BEATS:
print(" Type r, p or s.")
continue
comp = random.choice(list(BEATS))
result = winner(move, comp)
if result != "tie":
score[result] += 1
print(f" You: {move}, computer: {comp} -> {result.upper() if result == 'tie' else result + ' win' + ('s' if result == 'computer' else '')}"
f" | score {score['you']}-{score['computer']}")
print("You won the match!" if score["you"] == need else "The computer won the match.")
play()
Output:
Rock, paper or scissors (r/p/s)? r
You: rock, computer: scissors -> you win | score 1-0
Rock, paper or scissors (r/p/s)? p
You: paper, computer: rock -> you win | score 2-0
Rock, paper or scissors (r/p/s)? x
Type r, p or s.
Rock, paper or scissors (r/p/s)? r
You: rock, computer: rock -> TIE | score 2-0
Rock, paper or scissors (r/p/s)? p
You: paper, computer: scissors -> computer wins | score 2-1
Rock, paper or scissors (r/p/s)? s
You: scissors, computer: paper -> you win | score 3-1
You won the match!

The random.seed(42) line just makes this demo repeatable; remove it for a real game. The loop pattern is the same as in infinite loops with while, ending when a player wins.
A shorter rock paper scissors winner check with modulo
If you put the moves in a list where each one beats the move before it, there’s a shortcut. Then the difference of their positions, modulo 3, tells you who won:
MOVES = ["rock", "paper", "scissors"] # each move beats the one before it (wrapping around)
def winner(you, computer):
diff = (MOVES.index(you) - MOVES.index(computer)) % 3
return ["tie", "you", "computer"][diff]
print(winner("paper", "rock"), winner("rock", "paper"), winner("scissors", "scissors"))
Output:
you computer tie
It’s neat, but I prefer the dictionary in real code because it says what it means. The % trick is explained in the GCD guide, which leans on the same operator.
Rock paper scissors lizard Spock in Python
The dictionary approach scales nicely, and you won’t need to rewrite the logic. Make each value a dict of the moves it beats and the verb for how, and you get Rock Paper Scissors Lizard Spock with messages:
BEATS = {
"rock": {"scissors": "crushes", "lizard": "crushes"},
"paper": {"rock": "covers", "spock": "disproves"},
"scissors": {"paper": "cuts", "lizard": "decapitates"},
"lizard": {"spock": "poisons", "paper": "eats"},
"spock": {"scissors": "smashes", "rock": "vaporizes"},
}
def describe(a, b):
if a == b:
return f"{a} vs {b}: tie"
if b in BEATS[a]:
return f"{a} {BEATS[a][b]} {b}"
return f"{b} {BEATS[b][a]} {a}"
for pair in [("spock", "rock"), ("lizard", "paper"), ("scissors", "lizard"), ("rock", "spock")]:
print(describe(*pair))
Output:
spock vaporizes rock
lizard eats paper
scissors decapitates lizard
spock vaporizes rock

Is rock paper scissors fair against a random computer?
Yes. If you play against random moves, wins, losses and ties each land near one third. Simulating 30,000 games confirms it:
import random
from collections import Counter
BEATS = {"rock": "scissors", "paper": "rock", "scissors": "paper"} # key beats value
def winner(you, computer):
if you == computer:
return "tie"
return "you" if BEATS[you] == computer else "computer"
random.seed(2026)
moves = list(BEATS)
results = Counter(winner(random.choice(moves), random.choice(moves)) for _ in range(30_000))
for outcome in ("you", "computer", "tie"):
print(f"{outcome:<9} {results[outcome]:>6,} ({results[outcome] / 30_000:.1%})")
Output:
you 10,002 (33.3%)
computer 9,956 (33.2%)
tie 10,042 (33.5%)
Counter tallies the outcomes in one line. To make the computer smarter, you could track the player’s most common move and counter it. For random choices in general, see randomly selecting from a list.
Ideas to extend the game
- Keep score across matches in a file, using
json. - Let the player choose how many rounds to play.
- Make the computer learn the player’s habits.
- Build a GUI with Tkinter buttons; see Tkinter button commands.
More Python games and projects to try:
Frequently asked questions
How do you make a rock paper scissors game in Python?
Store the rules in a dictionary, read the player’s move with input(), pick the computer’s move with random.choice(), and compare them in a loop.
How does the computer choose its move?
With random.choice(["rock", "paper", "scissors"]), which picks each move with equal probability.
How do I handle invalid input?
Check the move against the allowed options and use continue to ask again if it’s not valid.
How do I make it best of three or five?
Track wins in a dictionary and loop until one player reaches best_of // 2 + 1 wins.
Can I make the computer unbeatable?
Not fairly. If it waits to see your move, it’s cheating. Against random play, every strategy averages one third wins.
Where is random.choice documented?
See random.choice in the Python docs.

Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn