Game programming is a bang-up manner to learn how to program. You use many tools that y'all'll run into in the real world, plus you get to play a game to test your results! An platonic game to start your Python game programming journeying is rock paper pair of scissors.

In this tutorial, you'll learn how to:

  • Code your own rock paper scissors game
  • Take in user input with input()
  • Play several games in a row using a while loop
  • Clean up your code with Enum and functions
  • Ascertain more than complex rules with a dictionary

What Is Stone Paper Scissors?

You may have played rock paper scissors before. Maybe yous've used information technology to decide who pays for dinner or who gets first choice of players for a team.

If yous're unfamiliar, stone newspaper scissors is a paw game for two or more players. Participants say "rock, newspaper, scissors" and so simultaneously form their easily into the shape of a rock (a fist), a piece of paper (palm facing downward), or a scissors (two fingers extended). The rules are straightforward:

  • Rock smashes scissors.
  • Newspaper covers rock.
  • Pair of scissors cutting paper.

Now that you take the rules downward, y'all tin can start thinking about how they might translate to Python code.

Play a Single Game of Rock Paper Pair of scissors in Python

Using the description and rules above, you can brand a game of stone paper pair of scissors. Earlier y'all dive in, you're going to need to import the module y'all'll apply to simulate the computer's choices:

Crawly! Now you're able to use the dissimilar tools inside random to randomize the computer's actions in the game. At present what? Since your users volition besides need to exist able to choose their actions, the first logical thing you need is a manner to accept in user input.

Take User Input

Taking input from a user is pretty straightforward in Python. The goal here is to ask the user what they would like to choose equally an action and then assign that choice to a variable:

                                                  user_action                  =                  input                  (                  "Enter a option (rock, paper, pair of scissors): "                  )                              

This will prompt the user to enter a selection and save it to a variable for later on utilise. Now that the user has selected an activity, the computer needs to determine what to practice.

Make the Computer Cull

A competitive game of stone paper scissors involves strategy. Rather than trying to develop a model for that, though, you can save yourself some time by having the calculator select a random action. Random selections are a nifty way to accept the calculator cull a pseudorandom value.

You lot can apply random.choice() to have the estimator randomly select between the actions:

                                                  possible_actions                  =                  [                  "rock"                  ,                  "paper"                  ,                  "scissors"                  ]                  computer_action                  =                  random                  .                  option                  (                  possible_actions                  )                              

This allows a random chemical element to be selected from the list. You can besides print the choices that the user and the figurer made:

                                                  print                  (                  f                  "                  \due north                  You chose                                    {                  user_action                  }                  , figurer chose                                    {                  computer_action                  }                  .                  \n                  "                  )                              

Printing the user and estimator actions tin can be helpful to the user, and it tin also aid y'all debug afterwards on in case something isn't quite correct with the outcome.

Determine a Winner

Now that both players accept fabricated their pick, yous but need a way to decide who wins. Using an ifelifelse cake, you can compare players' choices and decide a winner:

                                                  if                  user_action                  ==                  computer_action                  :                  print                  (                  f                  "Both players selected                                    {                  user_action                  }                  . Information technology'southward a tie!"                  )                  elif                  user_action                  ==                  "rock"                  :                  if                  computer_action                  ==                  "scissors"                  :                  print                  (                  "Stone smashes pair of scissors! You lot win!"                  )                  else                  :                  print                  (                  "Paper covers rock! You lose."                  )                  elif                  user_action                  ==                  "paper"                  :                  if                  computer_action                  ==                  "rock"                  :                  print                  (                  "Paper covers rock! You win!"                  )                  else                  :                  impress                  (                  "Scissors cuts paper! Yous lose."                  )                  elif                  user_action                  ==                  "scissors"                  :                  if                  computer_action                  ==                  "newspaper"                  :                  print                  (                  "Scissors cuts paper! You win!"                  )                  else                  :                  print                  (                  "Rock smashes scissors! You lose."                  )                              

By comparing the tie status offset, you become rid of quite a few cases. If you didn't practice that, then you'd demand to check each possible action for user_action and compare it against each possible action for computer_action. By checking the tie condition first, you're able to know what the computer chose with only ii provisional checks of computer_action.

And that's it! All combined, your code should at present look like this:

                                                  import                  random                  user_action                  =                  input                  (                  "Enter a pick (rock, paper, pair of scissors): "                  )                  possible_actions                  =                  [                  "rock"                  ,                  "paper"                  ,                  "scissors"                  ]                  computer_action                  =                  random                  .                  choice                  (                  possible_actions                  )                  print                  (                  f                  "                  \n                  You chose                                    {                  user_action                  }                  , computer chose                                    {                  computer_action                  }                  .                  \north                  "                  )                  if                  user_action                  ==                  computer_action                  :                  print                  (                  f                  "Both players selected                                    {                  user_action                  }                  . It'south a necktie!"                  )                  elif                  user_action                  ==                  "stone"                  :                  if                  computer_action                  ==                  "scissors"                  :                  print                  (                  "Stone smashes scissors! You win!"                  )                  else                  :                  impress                  (                  "Paper covers rock! You lose."                  )                  elif                  user_action                  ==                  "paper"                  :                  if                  computer_action                  ==                  "rock"                  :                  print                  (                  "Paper covers rock! You win!"                  )                  else                  :                  print                  (                  "Scissors cuts newspaper! You lose."                  )                  elif                  user_action                  ==                  "scissors"                  :                  if                  computer_action                  ==                  "paper"                  :                  print                  (                  "Scissors cuts paper! Yous win!"                  )                  else                  :                  print                  (                  "Rock smashes scissors! You lose."                  )                              

You've now written code to take in user input, select a random action for the computer, and decide the winner! But this just lets you play one game earlier the program finishes running.

Play Several Games in a Row

Although a single game of rock paper scissors is super fun, wouldn't it exist better if you could play several games in a row? Loops are a great style to create recurring events. In item, y'all can apply a while loop to play indefinitely:

                                            import                random                                  while                  Truthful                  :                                user_action                =                input                (                "Enter a choice (rock, paper, scissors): "                )                possible_actions                =                [                "rock"                ,                "newspaper"                ,                "scissors"                ]                computer_action                =                random                .                selection                (                possible_actions                )                print                (                f                "                \north                You chose                                {                user_action                }                , computer chose                                {                computer_action                }                .                \n                "                )                if                user_action                ==                computer_action                :                print                (                f                "Both players selected                                {                user_action                }                . It's a tie!"                )                elif                user_action                ==                "rock"                :                if                computer_action                ==                "scissors"                :                print                (                "Rock smashes scissors! You lot win!"                )                else                :                print                (                "Newspaper covers rock! Yous lose."                )                elif                user_action                ==                "paper"                :                if                computer_action                ==                "rock"                :                impress                (                "Paper covers rock! You win!"                )                else                :                print                (                "Scissors cuts newspaper! You lose."                )                elif                user_action                ==                "scissors"                :                if                computer_action                ==                "paper"                :                print                (                "Pair of scissors cuts newspaper! Y'all win!"                )                else                :                print                (                "Rock smashes scissors! You lose."                )                                  play_again                  =                  input                  (                  "Play again? (y/due north): "                  )                                                  if                  play_again                  .                  lower                  ()                  !=                  "y"                  :                                                  break                                          

Notice the highlighted lines above. Information technology'south of import to check if the user wants to play over again and to break if they don't. Without that check, the user would be forced to play until they terminated the panel using Ctrl + C or a similar method.

The check for playing again is a check against the cord "y". But checking for something specific like this might make information technology harder for the user finish playing. What if the user types "yeah" or "no"? Cord comparison is often tricky because you never know what the user might enter. They might do all lowercase, all uppercase, or even a mixture of the two.

Here are the results of a few different string comparisons:

>>>

                                            >>>                                play_again                =                "yes"                >>>                                play_again                ==                "n"                Simulated                >>>                                play_again                !=                "y"                True                          

Hmm. That's not what you lot want. The user might non be too happy if they enter "aye" expecting to play once again merely are kicked from the game.

Describe an Action With enum.IntEnum

Because cord comparisons can crusade bug like you saw above, information technology's a expert idea to avoid them whenever possible. One of the get-go things your program asks, all the same, is for the user to input a string! What if the user inputs "Rock" or "rOck" by mistake? Capitalization matters, and so they won't be equal:

>>>

                                            >>>                                impress                (                "rock"                ==                "Stone"                )                Fake                          

Since capitalization matters, "r" and "R" aren't equal. 1 possible solution would exist to use numbers instead. Assigning each activity a number could save you some problem:

                                            ROCK_ACTION                =                0                PAPER_ACTION                =                i                SCISSORS_ACTION                =                2                          

This allows yous to reference unlike deportment by their assigned number. Integers don't suffer the same comparison issues as strings, and so this could work. At present y'all can have the user input a number and compare information technology directly against those values:

                                            user_input                =                input                (                "Enter a option (rock[0], paper[1], scissors[2]): "                )                user_action                =                int                (                user_input                )                if                user_action                ==                ROCK_ACTION                :                # Handle ROCK_ACTION                          

Because input() returns a string, y'all need to convert the render value to an integer using int(). Then you can compare the input to each of the actions to a higher place. This works well, but information technology might rely on you naming variables correctly in order to continue track of them. A better way is to apply enum.IntEnum and define your own action form!

Using enum.IntEnum allows y'all to create attributes and assign them values similar to those shown in a higher place. This helps make clean up your code by group deportment into their own namespaces and making the code more expressive:

                                            from                enum                import                IntEnum                form                Action                (                IntEnum                ):                Rock                =                0                Paper                =                ane                Pair of scissors                =                2                          

This creates a custom Action that you can use to reference the different types of actions you support. It works by assigning each attribute within it to a value you specify.

Comparisons are still straightforward, and now they take a helpful course proper noun associated with them:

>>>

                                            >>>                                Activeness                .                Rock                ==                Action                .                Rock                Truthful                          

Because the member values are the same, the comparison is equal. The class names as well make it more obvious that y'all desire to compare 2 deportment.

You tin even create an Action from an int:

>>>

                                            >>>                                Activity                .                Rock                ==                Action                (                0                )                True                >>>                                Action                (                0                )                <Action.Rock: 0>                          

Action looks at the value passed in and returns the appropriate Action. This is helpful because now y'all can take in the user input every bit an int and create an Action from it. No more worrying about spelling!

The Menstruum(chart) of Your Program

Although rock newspaper pair of scissors might seem uncomplicated, it's of import to carefully consider the steps involved in playing information technology and then that yous can be sure your programme covers all possible scenarios. For any project, even small ones, it's helpful to create a flowchart of the desired behavior and implement code effectually information technology. You could achieve a similar result using a bulleted list, but it'd be harder to capture things like loops and conditional logic.

Flowcharts don't accept to be overly complicated or fifty-fifty apply real code. Just describing the desired beliefs ahead of time tin can help you set problems before they happen!

Here's a flowchart that describes a unmarried game of stone paper scissors:

Flow chart for a single game of rock paper scissors

Each player selects an activeness and and so a winner is determined. This flowchart is accurate for a single game every bit you've coded it, simply information technology's not necessarily authentic for existent-life games. In existent life, the players select their deportment simultaneously rather than one at a time like the flowchart suggests.

In the coded version, however, this works because the role player's choice is hidden from the computer, and the computer's choice is hidden from the player. The two players can make their choices at unlike times without affecting the fairness of the game.

Flowcharts help yous catch possible mistakes early on and besides let you see if you want to add together more functionality. For example, here'south a flowchart that describes how to play games repeatedly until the user decides to stop:

Flow chart for playing repeated games of rock paper scissors until the user decides to stop.

Without writing code, you can come across that the first flowchart doesn't accept a way to play again. This arroyo allows you to tackle issues like these before programming, which helps you lot create neater, more manageable lawmaking!

Divide Your Code Into Functions

Now that you've outlined the flow of your plan using a flowchart, you tin try to organize your lawmaking and then that information technology more closely resembles the steps you've identified. One natural way to do this is to create a function for each stride in the flowchart. Functions are a slap-up fashion to separate larger chunks of code into smaller, more than manageable pieces.

You don't necessarily need to create a role for the conditional check to play again, but you can if you'd like. Y'all can beginning by importing random if you haven't already and defining your Activity grade:

                                            import                random                from                enum                import                IntEnum                class                Action                (                IntEnum                ):                Stone                =                0                Paper                =                1                Pair of scissors                =                ii                          

Hopefully this all looks familiar then far! Now hither's the lawmaking for get_user_selection(), which doesn't accept in whatsoever arguments and returns an Action:

                                            def                get_user_selection                ():                user_input                =                input                (                "Enter a pick (stone[0], paper[1], pair of scissors[ii]): "                )                selection                =                int                (                user_input                )                action                =                Action                (                selection                )                return                activity                          

Notice how you lot take in the user input every bit an int and get back an Action. That long message for the user is a bit cumbersome, though. What would happen if y'all wanted to add more actions? Yous'd accept to add together even more than text to the prompt.

Instead, y'all can use a list comprehension to generate a portion of the input:

                                            def                get_user_selection                ():                choices                =                [                f                "                {                action                .                name                }                [                {                activeness                .                value                }                ]"                for                activeness                in                Activity                ]                choices_str                =                ", "                .                join                (                choices                )                selection                =                int                (                input                (                f                "Enter a choice (                {                choices_str                }                ): "                ))                action                =                Action                (                choice                )                return                action                          

Now you no longer need to worry most adding or removing actions in the future! Testing this out, you tin see how the code prompts the user and returns an activeness associated with the user's input value:

>>>

                                            >>>                                get_user_selection                ()                Enter a pick (rock[0], newspaper[1], scissors[two]): 0                <Activity.Rock: 0>                          

Now yous demand a role for getting the computer's action. Like get_user_selection(), this function should take no arguments and return an Action. Because the values for Activeness range from 0 to 2, you're going to want to generate a random number within that range. random.randint() tin can help with that.

random.randint() returns a random value betwixt a specified minimum and maximum (inclusive). You tin use len() to help effigy out what the upper bound should be in your code:

                                            def                get_computer_selection                ():                selection                =                random                .                randint                (                0                ,                len                (                Activeness                )                -                ane                )                action                =                Action                (                selection                )                return                action                          

Because the Action values offset counting from 0, and len() starts counting from 1, it'due south of import to exercise len(Action) - 1.

When y'all test this, there won't be a prompt. It volition but render the activity associated with the random number:

>>>

                                            >>>                                get_computer_selection                ()                <Activity.Scissors: 2>                          

Looking adept! Next, yous need a way to determine a winner. This function will accept two arguments, the user'southward activity and the reckoner'due south activeness. It doesn't need to return anything since information technology'll just brandish the result to the panel:

                                            def                determine_winner                (                user_action                ,                computer_action                ):                if                user_action                ==                computer_action                :                print                (                f                "Both players selected                                {                user_action                .                name                }                . It's a tie!"                )                elif                user_action                ==                Action                .                Rock                :                if                computer_action                ==                Action                .                Pair of scissors                :                impress                (                "Stone smashes pair of scissors! You win!"                )                else                :                print                (                "Paper covers rock! You lose."                )                elif                user_action                ==                Action                .                Paper                :                if                computer_action                ==                Activeness                .                Rock                :                print                (                "Newspaper covers stone! Y'all win!"                )                else                :                print                (                "Scissors cuts paper! You lose."                )                elif                user_action                ==                Action                .                Scissors                :                if                computer_action                ==                Activity                .                Newspaper                :                print                (                "Scissors cuts paper! Y'all win!"                )                else                :                print                (                "Stone smashes scissors! You lose."                )                          

This is pretty similar to the first comparison you used to determine a winner. At present you lot can just directly compare Action types without worrying about those pesky strings!

You can fifty-fifty test this out by passing different options to determine_winner() and seeing what gets printed:

>>>

                                            >>>                                determine_winner                (                Action                .                Rock                ,                Action                .                Scissors                )                Rock smashes scissors! You win!                          

Since y'all're creating an activity from a number, what would happen if your user tried to create an action from 3? Remember, largest number you lot've defined so far is ii:

>>>

                                            >>>                                Action                (                three                )                ValueError: 3 is not a valid Activity                          

Whoops! You don't want that to happen. Where in the flowchart could you add some logic to ensure the user has entered a valid choice?

It makes sense to include the check immediately after the user has made their choice:

A flow chart for playing rock paper scissors that includes a check for whether or not the user's input is valid.

If the user enters an invalid value, then you repeat the step for getting the user'southward pick. The only real requirement for the user selection is that it's between 0 and 2, inclusive. If the user'due south input is outside this range, then a ValueError exception will be raised. To avert displaying the default error bulletin to the user, yous tin handle the exception.

Now that you've defined a few functions that reflect the steps in your flowchart, your game logic is a lot more organized and compact. This is all your while loop needs to contain now:

                                            while                Truthful                :                try                :                user_action                =                get_user_selection                ()                except                ValueError                as                e                :                range_str                =                f                "[0,                                {                len                (                Activity                )                -                1                }                ]"                impress                (                f                "Invalid choice. Enter a value in range                                {                range_str                }                "                )                continue                computer_action                =                get_computer_selection                ()                determine_winner                (                user_action                ,                computer_action                )                play_again                =                input                (                "Play once more? (y/n): "                )                if                play_again                .                lower                ()                !=                "y"                :                break                          

Doesn't that wait a lot cleaner? Observe how if the user fails to select a valid range, so you use proceed rather than interruption. This makes the code continue to the side by side iteration of the loop rather than break out of it.

Rock Paper Scissors … Lizard Spock

If y'all've seen The Big Bang Theory, so you may exist familiar with rock paper scissors lizard Spock. If not, then hither's a diagram depicting the game and the rules deciding the winner:

A diagram illustrating the rules of Rock Paper Scissors Lizard Spock

Yous tin can apply the same tools you learned about to a higher place to implement this game. For example, you could add to Activeness and create values for lizard and Spock. And so yous would just need to modify get_user_selection() and get_computer_selection() to contain these options. Updating determine_winner(), however, would be a lot more than piece of work.

Instead of calculation a lot of ifelifelse statements to your code, you tin can apply a lexicon to help show the relationships betwixt actions. Dictionaries are a not bad mode to show a cardinal-value relationship. In this case, the fundamental can be an activeness, similar scissors, and the value can be a list of actions that information technology beats.

And so what would this await like for your determine_winner() with only three options? Well, each Action can trounce merely 1 other Activeness, so the list would contain only a single detail. Here's what your code looked like before:

                                            def                determine_winner                (                user_action                ,                computer_action                ):                if                user_action                ==                computer_action                :                print                (                f                "Both players selected                                {                user_action                .                name                }                . It's a necktie!"                )                elif                user_action                ==                Action                .                Rock                :                if                computer_action                ==                Action                .                Pair of scissors                :                print                (                "Stone smashes scissors! Yous win!"                )                else                :                print                (                "Paper covers stone! You lot lose."                )                elif                user_action                ==                Activity                .                Paper                :                if                computer_action                ==                Action                .                Rock                :                impress                (                "Paper covers rock! Y'all win!"                )                else                :                impress                (                "Pair of scissors cuts paper! You lose."                )                elif                user_action                ==                Action                .                Scissors                :                if                computer_action                ==                Action                .                Paper                :                print                (                "Scissors cuts newspaper! You win!"                )                else                :                print                (                "Rock smashes scissors! You lose."                )                          

Now, instead of comparing to each Action, you can have a lexicon that describes the victory weather condition:

                                            def                determine_winner                (                user_action                ,                computer_action                ):                victories                =                {                Activeness                .                Rock                :                [                Activity                .                Pair of scissors                ],                # Rock beats scissors                Action                .                Newspaper                :                [                Action                .                Stone                ],                # Paper beats stone                Activity                .                Scissors                :                [                Action                .                Paper                ]                # Scissors beats paper                }                defeats                =                victories                [                user_action                ]                if                user_action                ==                computer_action                :                print                (                f                "Both players selected                                {                user_action                .                name                }                . It's a tie!"                )                elif                computer_action                in                defeats                :                print                (                f                "                {                user_action                .                name                }                                  beats                                {                computer_action                .                proper noun                }                ! You win!"                )                else                :                print                (                f                "                {                computer_action                .                proper name                }                                  beats                                {                user_action                .                name                }                ! You lose."                )                          

You nevertheless do the same equally before and check the tie condition first. But instead of comparison each Action, you instead compare the action that the user_input beats against the computer_action. Since the key-value pair is a listing, you lot can apply the membership operator in to check if an element resides inside information technology.

Since you lot no longer employ long ifelifelse statements, information technology's relatively painless to add together checks for these new deportment. You can starting time by calculation lizard and Spock to Activeness:

                                            grade                Activity                (                IntEnum                ):                Rock                =                0                Newspaper                =                1                Scissors                =                two                Cadger                =                3                Spock                =                four                          

Next, add all the victory relationships from the diagram. Make sure to exercise this underneath Activeness so that victories will be able to reference everything in Activeness:

                                            victories                =                {                Action                .                Scissors                :                [                Action                .                Lizard                ,                Action                .                Paper                ],                Action                .                Paper                :                [                Action                .                Spock                ,                Activity                .                Rock                ],                Activeness                .                Rock                :                [                Action                .                Lizard                ,                Activity                .                Scissors                ],                Action                .                Lizard                :                [                Action                .                Spock                ,                Activity                .                Newspaper                ],                Action                .                Spock                :                [                Action                .                Pair of scissors                ,                Action                .                Rock                ]                }                          

Notice how now each Action has a list containing two elements that it beats. In the basic stone newspaper scissors implementation, there was only i element.

Because yous intentionally wrote get_user_selection() to suit new actions, you lot don't take to alter anything about that code. The same is true for get_computer_selection(). Since the length of Activity has inverse, the range of random numbers will also change.

Expect at how much shorter and more manageable the lawmaking is now! To run across the full code for your complete program, expand the box beneath.

                                            import                random                from                enum                import                IntEnum                course                Activity                (                IntEnum                ):                Rock                =                0                Paper                =                1                Scissors                =                ii                Lizard                =                3                Spock                =                4                victories                =                {                Activity                .                Pair of scissors                :                [                Action                .                Cadger                ,                Activity                .                Newspaper                ],                Action                .                Paper                :                [                Action                .                Spock                ,                Action                .                Rock                ],                Action                .                Rock                :                [                Activity                .                Lizard                ,                Action                .                Pair of scissors                ],                Activity                .                Lizard                :                [                Action                .                Spock                ,                Action                .                Paper                ],                Action                .                Spock                :                [                Activity                .                Scissors                ,                Action                .                Rock                ]                }                def                get_user_selection                ():                choices                =                [                f                "                {                action                .                name                }                [                {                action                .                value                }                ]"                for                action                in                Action                ]                choices_str                =                ", "                .                join                (                choices                )                option                =                int                (                input                (                f                "Enter a option (                {                choices_str                }                ): "                ))                action                =                Action                (                pick                )                return                activeness                def                get_computer_selection                ():                selection                =                random                .                randint                (                0                ,                len                (                Activity                )                -                1                )                action                =                Action                (                selection                )                return                action                def                determine_winner                (                user_action                ,                computer_action                ):                defeats                =                victories                [                user_action                ]                if                user_action                ==                computer_action                :                print                (                f                "Both players selected                                {                user_action                .                proper noun                }                . It'south a tie!"                )                elif                computer_action                in                defeats                :                print                (                f                "                {                user_action                .                name                }                                  beats                                {                computer_action                .                name                }                ! You win!"                )                else                :                impress                (                f                "                {                computer_action                .                name                }                                  beats                                {                user_action                .                proper name                }                ! You lose."                )                while                True                :                try                :                user_action                =                get_user_selection                ()                except                ValueError                as                due east                :                range_str                =                f                "[0,                                {                len                (                Action                )                -                1                }                ]"                print                (                f                "Invalid selection. Enter a value in range                                {                range_str                }                "                )                go along                computer_action                =                get_computer_selection                ()                determine_winner                (                user_action                ,                computer_action                )                play_again                =                input                (                "Play again? (y/n): "                )                if                play_again                .                lower                ()                !=                "y"                :                suspension                          

That's it! You've implemented rock paper scissors cadger Spock in Python lawmaking. Double-check to brand sure you didn't miss anything and give it a playthrough.

Conclusion

Congratulations! You just finished your start Python game! You now know how to create rock newspaper scissors from scratch, and you're able to expand the number of possible actions in your game with minimal effort.

In this tutorial, you learned how to:

  • Code your own rock paper scissors game
  • Accept in user input with input()
  • Play several games in a row using a while loop
  • Clean up your code with Enum and functions
  • Describe more circuitous rules with a lexicon

These tools will continue to help you throughout your many programming adventures. If y'all have any questions, and so experience gratis to accomplish out in the comments section below.