How to Determine a Winner
00:00 In the previous lesson, you got started by writing the initial code for rock paper scissors. In this lesson, I’ll show you how to add code that declares the winner in each round.
00:11 Just showing the choice the user made and the random computer choice feels a bit lightweight. Let’s add some code to say who won. You’ll need to encode the logic for each situation of X beats Y, where rock smashes scissors, paper covers rock, and scissors cut paper.
00:30 As the logic for determining who won kind of goes together, it would be best to put this inside of a function. You might even name it something meaningful!
00:41
This is the code inside of winner.py
. It is based on the previous loop.py
, but with the winner determination logic inside of it.
00:50 It is good practice to group related bits of code together in functions. This allows reuse of code, through multiple calls to the function, and clarity of reading your code.
01:00
You don’t have to necessarily read the contents of show_winner()
to know what it might be doing. Line 6 declares the show_winner()
function. It takes two arguments.
01:12
The first is named user_choice
and the second, computer_choice
. Line 7 checks if the user and the computer chose the same value. If so, line 8 prints that there was a tie. Line 9 is an else-if, which will only run if the user and the computer chose different values.
01:30
This line checks if the user chose "rock"
. If they did, there are two sub-cases: The computer chose "scissors"
and therefore the user won, or the computer chose "paper"
and the computer won.
01:44
Remember, if the computer had chosen "rock"
, you wouldn’t get here as that bit of logic is caught by line 7. Line 14 is similar to line 9 but for "paper"
.
01:56
Similar logic is contained within this else-if block, processing the win and lose conditions for "paper"
.
02:03
Then you do it again for "scissors"
and its associated win and lose conditions. Finally, if anything but "rock"
, "paper"
, or "scissors"
was typed, it is caught by the else
clause on line 24. In this case, the user is told their throw was bad.
02:22
Let me just scroll down. The code in the while
loop is pretty close to before, just with the new line that calls the show_winner()
function.
02:31 You’re all set to play now.
02:36
Let me run the game. I’ll type rock
,
02:41 and I lost. Let me play again,
02:46
rock
one more time, and you get the idea.
02:53 A large if-then-else block like I just demonstrated can be a bit hard to read. It only gets worse the more conditions you have to compare. This kind of code is so common that Python 3.10, coming in the fall of 2021, has a new keyword structure called pattern matching.
03:10 This is a new bit of syntax in Python that displays a series of choices based on a pattern. This structure will allow you to write large if-then-else blocks with fewer lines of code. If you’re used to switch statements in other languages, it’s a cousin of that.
03:26 There was some debate over the pattern matching statement, but however you might feel about it, until Python 3.10 is out, you’re stuck with if-then-else. Or are you?
03:35 Let me show you a way of using data structures in your code to help simplify the amount of coding logic and reduce the size of the if-then-else block.
03:45
This is beats.py
. “Beats” as in “rock beats scissors,” not as in “Womphf, womphf, womphf, womphf.” The first change from the previous program is the introduction of the BEATS
dict. This dictionary is storing the what-beats-what conditions. Each key of the dictionary is paired against a list of things it beats. You’ll understand why I used a list in the next lesson.
04:10 Line 7 encodes the fact that rock beats scissors, paper beats rock, and scissors beat paper.
04:19 You could simplify the message to the user by changing the language to say “X beats Y” instead of having the specifics of “rock smashes scissors,” but instead, I’m going to encode the verb describing the winning action inside another dict.
04:34
Each key in this dictionary is a tuple describing what beats what. The first one says that when rock beats scissors, use the word "smashes"
. This could be simplified by just having the winning item be the key to this dictionary, but the next lesson adds some complexity that this prepares for.
04:53 Line 14 encodes that paper covers rock, and 15 that scissors cut paper. Let me scroll down a bit.
05:02
With the game’s rules encoded in dictionaries, the code for show_winner()
becomes a little simpler. Line 19 and 20 are the same as before, checking for the tie condition.
05:13
But then, the chunk of the if-then-else has changed. Previously, the check for bad data was done at the end of the function. I’ve moved it up here. The .keys()
method on the BEATS
dict returns a list of all the valid keys.
05:27
If user_choice
is not in that, it means it wasn’t a valid choice. The else
block that starts on line 23 now contains all the who-beats-what logic.
05:37
Line 25 does a Boolean comparison checking if the computer’s choice is in the list of things that are beat by the user’s choice. If the user chose "rock"
, the key "rock"
is applied to BEATS
, returning the list containing just "scissors"
. If the computer chose "scissors"
, then there is a match and the resulting Boolean comparison is True
.
05:58
This value is stored in user_wins
. Line 27 then evaluates the Boolean called user_wins
. If the user did win, then look up the appropriate verb in the MESSAGES
dict, using the user and computer choice tuple as the key. For the choices of "rock"
and "scissors"
, the result will be "smashes"
. With the verb ready to go, all that is left is to tell the user the good news.
06:26 This f-string shows the user’s choice, the computer’s choice, and the associated verb. Note that inside of the brace brackets for the user’s choice there’s more than just the variable there.
06:38
An f-string allows you to call methods on string objects. The .capitalize()
method returns a new string with the first letter capitalized. This will make the beginning of the sentence look right.
06:49
Of course, the user doesn’t always win. The else
clause does the mirror logic. As the computer has won, the verb is looked up using the reverse of the tuple in the previous block, then the user is told the bad news. This code is a bit shorter than the large if-then-else block from loop.py
. It might not even be worth it in this case, but when the game gets more complicated, you’ll have saved a lot of work.
07:13 That complication will come in the next lesson. In the meantime, let’s look at the game.
07:28 Not much to see here that you haven’t seen before. The code was refactored, but the end result is supposed to be the same. Three-way decision making is just not complex enough.
07:39 There is a variation on rock paper scissors called rock, paper, scissors, lizard, Spock. Two new items makes it a five-way game. Next up, I’ll show you how to add this craziness.
Become a Member to join the conversation.