Code Review for Paper, Rock, Scissors

Larry Hudson orgnut at
Wed Oct 15 09:56:49 CEST 2014

On 10/14/2014 01:04 AM, Revenant wrote:
> Hi all!
> I'm new to Python and programming in general, and am trying to learn as much as I can about it.
> Anyway, for a basic first program I made a simple game of Paper, Rock, Scissors. For this program, I incorporated a main menu that presented three different options, allowed the user to play a game of Paper, Rock, Scissors, allowed them to play the game again, and most importantly checked the user's input to make sure the program doesn't fail due to errors.
> One thing I want to try to add is a "Press any key to continue" function that occurs at the end of the program when the user decides to quit. I looked at some options online, but haven't quite figured it out yet.
> As previously stated, I am new to Python and would also like to see if any of you programming gurus have some suggestions about how I can simplify code, and also if there are any other good starter programs to work on to improve my skills.
> Thanks for reading! Code is below:

You've already received a lot of good advice, which I'm not going to repeat here.  Rather, I'm 
going to show you the version that I wrote some time ago.  Whether this version is 
good/bad/indifferent is up to someone else to say, but I'm showing it here just as an example of 
a different approach that you might find interesting to study.  Although, being new to Python, 
some of the things here will probably be unfamiliar to you, particularly the new-style string 
formatting which I use a lot.

The key to this approach is to recognize that there are only nine possible combinations.  I 
handle these in the get_result() function by stitching together pieces of strings in a 
dictionary.  This function is interesting because, although it has a total of 34 lines, 17 are 
comments or blanks, 16 are data definitions, and only 1 line is actual code.

The get_rps() function is used to get the player's rock/paper/scissor choice.  It also allows 
'quit' as a fourth choice.  This makes your proposed "Press any key..." unnecessary, because 
this version will continue automatically until you specifically tell it to stop.  Also it 
accepts an empty input as the same as a 'quit' choice.  Whether this is good or bad is 
debatable, but it can easily be written either way.  It returns the choice as a single 
lower-case character, 'r', 'p', 's' or 'q'.

This version also makes heavy use of the constants WIN/LOSE/DRAW, which are defined as globals 
at the top of the program.  They help the clarity of the source.  Normal convention is to make 
the names of constants all upper-case.  This is a convention only, not a requirement.  The 
scores are tracked in a three-element list, which use the WIN/LOSE/DRAW constants as the 
indexes.  The instruction display in my version is very short, but it could easily be replaced 
with a longer version like yours.

FWIW, here is my code...
Note the first line is Linux-specific -- Windows will ignore it, or you can remove it.

#------------  Code starts here  ------------
#!/usr/bin/env python3

# -- Rock, Paper, Scissors game

from random import choice

#   Global constants
WIN  = 0
LOSE = 1
DRAW = 2

def get_result(h, c):
     """Determine who wins this round

         h:  Human's selection (r, p or s)
         c:  Computer's selection (r, p or s)

     Returns a tuple of the WIN/LOSE/DRAW value
         and the string describing the results

     #   Strings used in results
     pr = 'Paper covers Rock.  {}'
     rs = 'Rock smashes Scissors.  {}'
     sp = 'Scissors cuts Paper.  {}'
     ti = 'We both have {}.  {}'

     #   Win/lose/draw strings
     wins = ('You win', 'I win', "It's a draw")

     #   Dictionary defining the results
     res = {
         'rr' : (DRAW, ti.format('rocks', wins[DRAW])),
         'rp' : (LOSE, pr.format(wins[LOSE])),
         'rs' : (WIN,  rs.format(wins[WIN])),
         'pr' : (WIN,  pr.format(wins[WIN])),
         'pp' : (DRAW, ti.format('paper', wins[DRAW])),
         'ps' : (LOSE, sp.format(wins[LOSE])),
         'sr' : (LOSE, rs.format(wins[LOSE])),
         'sp' : (WIN,  sp.format(wins[WIN])),
         'ss' : (DRAW, ti.format('scissors', wins[DRAW]))

     #   Return the result tuple
     return res[h + c]

def get_rps():
     """Get Rock/Paper/Scissor choice."""
     while True:
         select = input('\nDo you choose Rock, Paper or Scissors ').lower()
         #   Check for empty input or quit command
         if not select or select in ['q', 'quit']:
             return 'q'                  #     return quit code
         #   Check for valid input
         if select in ['r', 'rock', 'p', 'paper', 's', 'scissors']:
             return select[0]            #     return first character
         print('What did you say??  Try again please')

#=================  Main Program starts here  ==============
#   Keep track of results:
#       scores[0] = number of human wins
#       scores[1] = number of computer wins
#       scores[2] = number of draws
scores = [0] * 3
things = {'r':'a rock', 'p':'paper', 's':'scissors'}

print("Let's play a game or Rock, Paper, Scissors.\n")
print('Enter "r", "p", "s", "rock", "paper", or "scissors" for your choice.')
print('Use empty input, "q" or "quit" to end the game.')

while True:
     computer = choice('rps')            #   Computer selects
     human = get_rps()                   #   Human selects
     if human == 'q':
     print('You have {}, I have {}.  '.format(
             things[human], things[computer]), end='')
     scr, res = get_result(human, computer)
     scores[scr] += 1                    #   Count win/loss/draw
     print(res)                          #   And show results

#   Show final scores
print('\nTotal scores:')
print('\tYou won {} games'.format(scores[WIN]))
print('\tComputer won {} games'.format(scores[LOSE]))
print('\tThere were {} tie games'.format(scores[DRAW]))
print('\nThanks for playing with me.  Bye now.')

#------------  End of code  --------------

      -=- Larry -=-

More information about the Python-list mailing list