Learn to Code via Tutorials on Repl.it

← Back to all posts
2
Rock Paper Scissors Game in 60 lines (Python3)
sharpvik (36)

To build our Rock Paper Scissors game we are going to use some elements of OOP, in fact, we are just going to create one class that is going to do all of it. So, without further ado...

  1. import function choice from random module
  2. declare class RPS
  3. create an instance of this class called game
from random import choice

class RPS:
    def __init__(self):
        pass
        
    # some more functions will go here
    
game = RPS()

Inside the __init__ function, we are going to have 4 variables:

  • opt is a list of options
  • usr_score and cpu_score are self-explanatory
  • rules is a dict that is going to help us decide who won without the need for extensive if / else statements

The last line of __init__ is going to be a call to some function match that also belongs to the class RPS.

# from now on we concentrate on the RPS class itself
class RPS:
    def __init__(self):
        self.opt = ['rock', 'paper', 'scissors']
		self.usr_score = 0
		self.cpu_score = 0
		self.rules = {
			'rock' 		  : 'scissors',
			'paper'		  : 'rock',
			'scissors'	: 'paper'
		}
		self.match()
        
    # some more functions will go here
    
    def match(self):
        pass

Now, before we start implementing the match function, let's declare some useful 'helper' functions. I really like using functions in my code because they make debugging really easy, so do not be surprised when you see a function that is one line long...

# from now on we concentrate on the RPS class itself
class RPS:
    def __init__(self):
        self.opt = ['rock', 'paper', 'scissors']
		self.usr_score = 0
		self.cpu_score = 0
		self.rules = {
			'rock' 		  : 'scissors',
			'paper'		  : 'rock',
			'scissors'	: 'paper'
		}
		self.match()
        
    def err(self, msg):
		print(f"ERROR: {msg}")

	def disp_scores(self):
		print(f"SCORES:\n\tYOU: {self.usr_score}\n\tCPU: {self.cpu_score}\n")

	def tie(self):
		print("It's a tie")
		self.usr_score += 1
		self.cpu_score += 1

	def usr_win(self):
		print("You won!")
		self.usr_score += 1

	def cpu_win(self):
		print("CPU won!")
		self.cpu_score += 1
	
	def ask(self):
		pass
    
    def match(self):
        pass

These 'helper' functions are going to be called each time we run the match function. You may have also noticed the ask function almost at the very end of the class definition. This function has to make sure that we get user input in the correct format before evaluating the results. This function, in case of invalid user input becomes recursive, so "Yaaay!". Let's see...

First of all, in the ask function, we want to display the options. For user's convenience, we are going to enumerate them:

# now concentrating on the ask function
def ask(self):
    for i in range( len(self.opt) ): print(f"{i + 1}. {self.opt[i]}")
    # it's incomplete, we're gonna write some more here!

Now, we are going to ask user for input:

# now concentrating on the ask function
def ask(self):
    for i in range( len(self.opt) ): print(f"{i + 1}. {self.opt[i]}")
    usr = input("\nSelect one option: ")
    # it's incomplete, we're gonna write some more here!

We, as software developers, have to think ahead and always assume that user is an idiot who always makes mistakes (but we still love him). Therefore, next few lines are going to deal with exceptions that may arise if an invalid input is given:

# now concentrating on the ask function
def ask(self):
    for i in range( len(self.opt) ): print(f"{i + 1}. {self.opt[i]}")
    usr = input("\nSelect one option: ")
    try: usr = int(usr) - 1
	except ValueError: 
		self.err("INPUT INVALID! YOU MUST INPUT A NUMBER!\n")
		return self.ask()
	if -1 < usr < len(self.opt): return self.opt[usr]
	else:
		self.err( "INPUT INVALID! YOU MUST INPUT A NUMBER BETWEEN 1 AND {len(self.opt)}!\n" )
		return self.ask()

Note that whenever we encounter an error, we let user know by displaying an error message and then we return self.ask(). This is because we want to run function ask again and again until user would be so kind as to provide us with a valid input value which we are then going to return. At this point, we have actually completed three fourth of our game! Congrats!

Now the last bit: the match function. The match function is a lazy dude that uses other functions' labour to fulfill its own purpose, but we aren't angry at it... after all, we've designed it this way :)
First two lines will select CPU's choice and ask user to input their answer. Let's also print those, so that the user knows what CPU's choice was. By the way, for those of you who don't know how random.choice() function works, it is a pseudo-random function that returns one value from a given list (in this case, the opt list).

# now concentrating on the match function
def match(self):
	cpu = choice(self.opt)
	usr = self.ask()
	print(f"You chose {usr.upper()} and CPU chose {cpu.upper()}")

When we have those choices, we can evaluate and decide who is the winner. As I said earlier on, the dict called rules will help us with it. How does it work then? Well, if we take a look at the rules...

self.rules = {
    'rock' 		: 'scissors',
    'paper'	    : 'rock',
    'scissors'  : 'paper'
}

...we can see that item on the left always beats items on the right and this is very useful in this case. For every pair of choices, there are only 3 possible outcomes:

  1. Both choices are the same and thus, it is a tie
  2. User wins
  3. CPU wins

Therefore, logically, the first thing to do is to check whether it is a tie (it's also the easiest one). If we use user's choice as a key and request its value from the rules and this value is equal to CPU's choice then we know that user won since we've designed rules in such way the any key 'beats' its value. If it is not a tie and user didn't win, then we must give point to the CPU. This is how it looks in code:

# focusing on the match function
def match(self):
	cpu = choice(self.opt)
	usr = self.ask()
	print(f"You chose {usr.upper()} and CPU chose {cpu.upper()}")
	if usr == cpu: self.tie()
	else:
		if self.rules[usr] == cpu: self.usr_win()
		else: self.cpu_win()

The match function is almost complete now: only 5 lines to go. We want to display scores, which is easily done using the disp_scores function. And the last bit: we want to know whether the user wants to play one more time or quit the game, so we declare a bool variable that is going to be the answer to this question and its value will, once more, depend on the user input. If it is True, we'll call our match function again, otherwise we'll print("Bye-bye!").

# focusing on the match function
def match(self):
	cpu = choice(self.opt)
	usr = self.ask()
	print(f"You chose {usr.upper()} and CPU chose {cpu.upper()}")
	if usr == cpu: self.tie()
	else:
		if self.rules[usr] == cpu: self.usr_win()
		else: self.cpu_win()
    self.disp_scores()
	endit = input("If you want to stop, enter 'q'. Otherwise, press ENTER. ").lower() == 'q'
	print()    # this is just for spacing
	if not endit: self.match()
	else: print("Bye-bye!")

That's it fellas. We are officially done now. Hope it was fun.
There you have the Link to the Repl containing my source code for this game.

Commentshotnewtop
1
timmy_i_chen (934)

Nice! Thanks for sharing! :)