In this chapter, you’re going to make a Guess the Number game. The computer will think of a secret number from 1 to 20 and ask the user to guess it. After each guess, the computer will tell the user whether the number is too high or too low. The user wins if they can guess the number within six tries.
This is a good game to code because it covers many programming concepts in a short program. You’ll learn how to convert values to different data types and when you would need to do this. Since this program is a game, from now on we’ll call the user the player.
Here’s what the Guess the Number program looks like to the player when it’s run. The player’s input is marked in bold.
Hello! What is your name?
Albert
Well, Albert, I am thinking of a number between 1 and 20.
Take a guess.
10
Your guess is too high.
Take a guess.
2
Your guess is too low.
Take a guess.
4
Good job, Albert! You guessed my number in 3 guesses!
Open a new file editor window by clicking File New Window. In the blank window that appears, enter the source code and save it as guess.py. Then run the program by pressing F5.
When you enter this code into the file editor, be sure to pay attention to the spacing at the front of the lines. Some lines need to be indented four or eight spaces.
If you get errors after entering this code, compare the code you typed to the book’s code with the online diff tool at https://www.nostarch.com/inventwithpython#diff.
guess.py
1. # This is a Guess the Number game.
2. import random
3.
4. guessesTaken = 0
5.
6. print('Hello! What is your name?')
7. myName = input()
8.
9. number = random.randint(1, 20)
10. print('Well, ' + myName + ', I am thinking of a number between 1 and 20.')
11.
12. for guessesTaken in range(6):
13. print('Take a guess.') # Four spaces in front of "print"
14. guess = input()
15. guess = int(guess)
16.
17. if guess < number:
18. print('Your guess is too low.') # Eight spaces in front of "print"
19.
20. if guess > number:
21. print('Your guess is too high.')
22.
23. if guess == number:
24. break
25.
26. if guess == number:
27. guessesTaken = str(guessesTaken + 1)
28. print('Good job, ' + myName + '! You guessed my number in ' +
guessesTaken + ' guesses!')
29.
30. if guess != number:
31. number = str(number)
32. print('Nope. The number I was thinking of was ' + number + '.')
Let’s take a look at the first two lines of this program:
1. # This is a Guess the Number game.
2. import random
The first line is a comment, which you saw in Chapter 2. Remember that Python will ignore everything after the # character. The comment here just reminds us what this program does.
The second line is an import statement. Remember, statements are instructions that perform some action but don’t evaluate to a value like expressions do. You’ve already seen the assignment statement, which stores a value in a variable.
While Python includes many built-in functions, some functions are written in separate programs called modules. You can use these functions by importing their modules into your program with an import statement.
Line 2 imports the random module so that the program can call the randint() function. This function will come up with a random number for the player to guess.
Now that you’ve imported the random module, you need to set up some variables to store values your program will use later.
Line 4 creates a new variable named guessesTaken:
4. guessesTaken = 0
You’ll store the number of guesses the player has made in this variable. Since the player hasn’t made any guesses at this point in the program, store the integer 0 here.
6. print('Hello! What is your name?')
7. myName = input()
Lines 6 and 7 are the same as the lines in the Hello World program in Chapter 2. Programmers often reuse code from other programs to save themselves work.
Line 6 is a function call to print(). Remember that a function is like a mini-program inside your program. When your program calls a function, it runs this mini-program. The code inside print() displays the string argument you passed it on the screen.
Line 7 lets the player enter their name and stores it in the myName variable. Remember, the string might not really be the player’s name; it’s just whatever string the player types. Computers are dumb and follow their instructions, no matter what.
Now that your other variables are set up, you can use the random module’s function to set the computer’s secret number:
9. number = random.randint(1, 20)
Line 9 calls a new function named randint() and stores the return value in number. Remember, function calls can be part of expressions because they evaluate to a value.
The randint() function is provided by the random module, so you must call it with random.randint() (don’t forget the period!) to tell Python that the function randint() is in the random module.
randint() will return a random integer between (and including) the two integer arguments you pass it. Line 9 passes 1 and 20, separated by commas, between the parentheses that follow the function name. The random integer that randint() returns is stored in a variable named number—this is the secret number the player is trying to guess.
Just for a moment, go back to the interactive shell and enter import random to import the random module. Then enter random.randint(1, 20) to see what the function call evaluates to. It will return an integer between 1 and 20. Repeat the code again, and the function call will return another integer. The randint() function returns a random integer each time, just as rolling a die will result in a random number each time. For example, enter the following into the interactive shell. The results you get when you call the randint() function will probably be different (it is random, after all!).
>>> import random
>>> random.randint(1, 20)
12
>>> random.randint(1, 20)
18
>>> random.randint(1, 20)
3
>>> random.randint(1, 20)
18
>>> random.randint(1, 20)
7
You can also try different ranges of numbers by changing the arguments. For example, enter random.randint(1, 4) to get only integers between 1 and 4 (including both 1 and 4). Or try random.randint(1000, 2000) to get integers between 1000 and 2000.
Enter this code in the interactive shell and see what numbers you get:
>>> random.randint(1, 4)
3
>>> random.randint(1000, 2000)
1294
You can change the game’s code slightly to make the game behave differently. In our original code, we use an integer between 1 and 20:
9. number = random.randint(1, 20)
10. print('Well, ' + myName + ', I am thinking of a number between 1 and 20.')
Try changing the integer range to (1, 100) instead:
9. number = random.randint(1, 100)
10. print('Well, ' + myName + ', I am thinking of a number between 1 and 100.')
Now the computer will think of an integer between 1 and 100 instead of 1 and 20. Changing line 9 will change the range of the random number, but remember to also change line 10 so that the game tells the player the new range instead of the old one.
You can use the randint() function whenever you want to add randomness to your games. You’ll use randomness in many games. (Think of how many board games use dice.)
After the computer assigns number a random integer, it greets the player:
10. print('Well, ' + myName + ', I am thinking of a number between 1 and 20.')
On line 10, print() welcomes the player by name and tells them that the computer is thinking of a random number.
At first glance, it may look like there’s more than one string argument in line 10, but examine the line carefully. The + operators between the three strings concatenate them into one string. And that one string is the argument passed to print(). If you look closely, you’ll see that the commas are inside the quotes and part of the strings themselves.
In previous chapters, the program execution started at the top instruction in the program and moved straight down, executing each instruction in order. But with the for, if, else, and break statements, you can make the execution loop or skip instructions based on conditions. These kinds of statements are flow control statements, since they change the flow of the program execution as it moves around your program.
Line 12 is a for statement, which indicates the beginning of a for loop:
12. for guessesTaken in range(6):
Loops let you execute code over and over again. Line 12 will repeat its code six times. A for statement begins with the for keyword, followed by a new variable name, the in keyword, a call to the range() function that specifies the number of loops it should do, and a colon. Let’s go over a few additional concepts so that you can work with loops.
Several lines of code can be grouped together in a block. Every line in a block of code begins with at least the number of spaces as the first line in the block. You can tell where a block begins and ends by looking at the number of spaces at the front of the lines. This is the line’s indentation.
Python programmers typically use four additional spaces of indentation to begin a block. Any following line that’s indented by that same amount is part of the block. The block ends when there’s a line of code with the same indentation as before the block started. There can also be blocks within other blocks. Figure 3-1 shows a code diagram with the blocks outlined and numbered.
Figure 3-1: An example of blocks and their indentation. The gray dots represent spaces.
In Figure 3-1, line 12 has no indentation and isn’t inside any block. Line 13 has an indentation of four spaces. Since this line is indented more than the previous line, a new block starts here. Every line following this one with the same amount of indentation or more is considered part of block ➊. If Python encounters another line with less indentation than the block’s first line, the block has ended. Blank lines are ignored.
Line 18 has an indentation of eight spaces, which starts block ➋. This block is inside block ➊. But the next line, line 20, is indented only four spaces. Because the indentation has decreased, you know that line 18’s block ➋ has ended, and because line 20 has the same indentation as line 13, you know it’s in block ➊.
Line 21 increases the indentation to eight spaces again, so another new block within a block has started: block ➌. At line 23, we exit block ➌, and at line 24 we enter the final block within a block, block ➍. Both block ➊ and block ➍ end on line 24.
The for statement marks the beginning of a loop. Loops execute the same code repeatedly. When the execution reaches a for statement, it enters the block that follows the for statement. After running all the code in this block, the execution moves back to the top of the block to run the code all over again.
Enter the following into the interactive shell:
>>> for i in range(3):
print('Hello! i is set to', i)
Hello! i is set to 0
Hello! i is set to 1
Hello! i is set to 2
Notice that after you typed for i in range(3): and pressed ENTER, the interactive shell didn’t show another >>> prompt because it was expecting you to type a block of code. Press ENTER again after the last instruction to tell the interactive shell you are done entering the block of code. (This applies only when you are working in the interactive shell. When writing .py files in the file editor, you don’t need to insert a blank line.)
Let’s look at the for loop on line 12 of guess.py:
12. for guessesTaken in range(6):
13. print('Take a guess.') # Four spaces in front of "print"
14. guess = input()
15. guess = int(guess)
16.
17. if guess < number:
18. print('Your guess is too low.') # Eight spaces in front of "print"
19.
20. if guess > number:
21. print('Your guess is too high.')
22.
23. if guess == number:
24. break
25.
26. if guess == number:
In Guess the Number, the for block begins at the for statement on line 12, and the first line after the for block is line 26.
A for statement always has a colon (:) after the condition. Statements that end with a colon expect a new block on the next line. This is illustrated in Figure 3-2.
Figure 3-2: The for loop’s flow of execution
Figure 3-2 shows how the execution flows. The execution will enter the for block at line 13 and keep going down. Once the program reaches the end of the for block, instead of going down to the next line, the execution loops back up to the start of the for block at line 13. It does this six times because of the range(6) function call in the for statement. Each time the execution goes through the loop is called an iteration.
Think of the for statement as saying, “Execute the code in the following block a certain number of times.”
Lines 13 and 14 ask the player to guess what the secret number is and let them enter their guess:
13. print('Take a guess.') # Four spaces in front of "print"
14. guess = input()
That number the player enters is stored in a variable named guess.
Line 15 calls a new function called int():
15. guess = int(guess)
The int() function takes one argument and returns the argument’s value as an integer.
Enter the following into the interactive shell to see how the int() function works:
>>> int('42')
42
The int('42') call will return the integer value 42.
>>> 3 + int('2')
5
The 3 + int('2') line shows an expression that uses the return value of int() as part of an expression. It evaluates to the integer value 5:
Even though you can pass a string to int(), you cannot pass it just any string. Passing 'forty-two' to int() will result in an error:
>>> int('forty-two')
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
int('forty-two')
ValueError: invalid literal for int() with base 10: 'forty-two'
The string you pass to int() must be made of numbers.
In Guess the Number, we get the player’s number using the input() function. Remember, the input() function always returns a string of text the player entered. If the player types 5, the input() function will return the string value '5', not the integer value 5. But we’ll need to compare the player’s number with an integer later, and Python cannot use the < and > comparison operators to compare a string and an integer value:
>>> 4 < '5'
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
4 < '5'
TypeError: unorderable types: int() < str()
Therefore, we need to convert the string into an integer:
14. guess = input()
15. guess = int(guess)
On line 14, we assign the guess variable to the string value of whatever number the player typed. Line 15 overwrites the string value in guess with the integer value returned by int(). The code int(guess) returns a new integer value based on the string it was provided, and guess = assigns that new value to guess. This lets the code later in the program compare whether guess is greater than, less than, or equal to the secret number in the number variable.
The float() and str() functions will similarly return float and string versions of the arguments passed to them. Enter the following into the interactive shell:
>>> float('42')
42.0
>>> float(42)
42.0
When the string '42' or the integer 42 is passed to float(), the float 42.0 is returned.
Now try using the str() function:
>>> str(42)
'42'
>>> str(42.0)
'42.0'
When the integer 42 is passed to str(), the string '42' is returned. But when the float 42.0 is passed to str(), the string '42.0' is returned.
Using the int(), float(), and str() functions, you can take a value of one data type and return it as a value of a different data type.
Every value in Python belongs to one data type. The data types that have been introduced so far are integers, floats, strings, and now Booleans. The Boolean data type has only two values: True or False. Boolean values must be entered with an uppercase T or F and the rest of the value’s name in lowercase.
Boolean values can be stored in variables just like the other data types:
>>> spam = True
>>> eggs = False
In this example, you set spam to True and eggs to False. Remember to capitalize the first letter.
You will use Boolean values (called bools for short) with comparison operators to form conditions. We’ll cover comparison operators first and then go over conditions.
Comparison operators compare two values and evaluate to a True or False Boolean value. Table 3-1 lists all of the comparison operators.
Table 3-1: Comparison Operators
Operator |
Operation |
< |
Less than |
> |
Greater than |
<= |
Less than or equal to |
>= |
Greater than or equal to |
== |
Equal to |
!= |
Not equal to |
You’ve already read about the +, -, *, and / math operators. Like any operator, comparison operators combine with values to form expressions such as guessesTaken < 6.
Line 17 of the Guess the Number program uses the less than comparison operator:
17. if guess < number:
We’ll discuss if statements in more detail shortly; for now, let’s just look at the expression that follows the if keyword (the guess < number part). This expression contains two values (the values in the variables guess and number) connected by an operator (the <, or less than, sign).
A condition is an expression that combines two values with a comparison operator (such as < or >) and evaluates to a Boolean value. A condition is just another name for an expression that evaluates to True or False. One place we use conditions is in if statements.
For example, the condition guess < number on line 17 asks, “Is the value stored in guess less than the value stored in number?” If so, then the condition evaluates to True. If not, the condition evaluates to False.
Say that guess stores the integer 10 and number stores the integer 16. Because 10 is less than 16, this condition evaluates to the Boolean value of True. The evaluation would look like this:
Enter the following expressions in the interactive shell to see their Boolean results:
>>> 0 < 6
True
>>> 6 < 0
False
The condition 0 < 6 returns the Boolean value True because the number 0 is less than the number 6. But because 6 isn’t less than 0, the condition 6 < 0 evaluates to False.
Notice that 10 < 10 evaluates to False because the number 10 isn’t smaller than the number 10:
>>> 10 < 10
False
The values are the same. If Alice were the same height as Bob, you wouldn’t say that Alice is taller than Bob or that Alice is shorter than Bob. Both of those statements would be false.
Now enter these expressions into the interactive shell:
>>> 10 == 10
True
>>> 10 == 11
False
>>> 11 == 10
False
>>> 10 != 10
False
In this example, 10 is equal to 10, so 10 == 10 evaluates to True. But 10 is not equal to 11, so 10 == 11 is False. Even if the order is flipped, 11 is still not equal to 10, so 11 == 10 is False. Finally, 10 is equal to 10, so 10 != 10 is False.
You can also evaluate string expressions with comparison operators:
>>> 'Hello' == 'Hello'
True
>>> 'Goodbye' != 'Hello'
True
>>> 'Hello' == 'HELLO'
False
'Hello' is equal to 'Hello', so 'Hello' == 'Hello' is True. 'Goodbye' is not equal to 'Hello', so 'Goodbye' != 'Hello' is also True.
Notice that the last line evaluates to False. Upper- and lowercase letters are not the same in Python, so 'Hello' is not equal to 'HELLO'.
String and integer values will never be equal to each other. For example, enter the following into the interactive shell:
>>> 42 == 'Hello'
False
>>> 42 != '42'
True
In the first example, 42 is an integer and 'Hello' is a string, so the values are not equal and the expression evaluates to False. In the second example, the string '42' is still not an integer, so the expression “the integer 42 is not equal to the string '42'” evaluates to True.
Be careful not to confuse the assignment operator, =, and the equal to comparison operator, ==. The equal sign, =, is used in assignment statements to store a value to a variable, whereas the double equal sign, ==, is used in expressions to see whether two values are equal. It’s easy to accidentally use one when you mean to use the other.
It might help to remember that both the equal to comparison operator, ==, and the not equal to comparison operator, !=, have two characters.
Line 17 is an if statement:
17. if guess < number:
18. print('Your guess is too low.') # Eight spaces in front of "print"
The code block following the if statement will run if the if statement’s condition evaluates to True. If the condition is False, the code in the if block is skipped. Using if statements, you can make the program run certain code only when you want it to.
Line 17 checks whether the player’s guess is less than the computer’s secret number. If so, then the execution moves inside the if block on line 18 and prints a message telling the player their guess was too low.
Line 20 checks whether the player’s guess is greater than the secret number:
20. if guess > number:
21. print('Your guess is too high.')
If this condition is True, then the print() function call tells the player that their guess is too high.
The if statement on line 23 checks whether the number the player guessed is equal to the secret number. If it is, the program runs the break statement on line 24:
23. if guess == number:
24. break
A break statement tells the execution to jump immediately out of the for block to the first line after the end of the for block. The break statement is found only inside loops, such as in a for block.
The for block ends at the next line of code with no indentation, which is line 26:
26. if guess == number:
The execution leaves the for block either because it has looped six times (when the player runs out of guesses) or because the break statement on line 24 has executed (when the player guesses the number correctly).
Line 26 checks whether the player guessed correctly. If so, the execution enters the if block at line 27:
27. guessesTaken = str(guessesTaken + 1)
28. print('Good job, ' + myName + '! You guessed my number in ' +
guessesTaken + ' guesses!')
Lines 27 and 28 execute only if the condition in the if statement on line 26 is True (that is, if the player correctly guessed the computer’s number).
Line 27 calls the str() function, which returns the string form of guessesTaken + 1 (since the range function goes from 0 to 5 instead of 1 to 6). Line 28 concatenates strings to tell the player they have won and how many guesses it took. Only string values can concatenate to other strings. This is why line 27 had to change guessesTaken + 1 to the string form. Otherwise, trying to concatenate a string with an integer would cause Python to display an error.
If the player runs out of guesses, the execution will go to this line of code:
30. if guess != number:
Line 30 uses the not equal to comparison operator != to check whether the player’s last guess is not equal to the secret number. If this condition evaluates to True, the execution moves into the if block on line 31.
Lines 31 and 32 are inside the if block, executing only if the condition on line 30 is True:
31. number = str(number)
32. print('Nope. The number I was thinking of was ' + number + '.')
In this block, the program tells the player what the secret number was. This requires concatenating strings, but number stores an integer value. Line 31 overwrites number with a string so that it can be concatenated to the 'Nope. The number I was thinking of was ' and '.' strings on line 32.
At this point, the execution has reached the end of the code, and the program terminates. Congratulations! You’ve just programmed your first real game!
You can adjust the game’s difficulty by changing the number of guesses the player gets. To give the player only four guesses, change the code on line 12:
12. for guessesTaken in range(4):
By passing 4 to range(), you ensure that the code inside the loop runs only four times instead of six. This makes the game much more difficult. To make the game easier, pass a larger integer to the range() function call. This will cause the loop to run a few more times and accept more guesses from the player.
Programming is just the action of writing code for programs—that is, creating programs that can be executed by a computer.
When you see someone using a computer program (for example, playing your Guess the Number game), all you see is some text appearing on the screen. The program decides what text to display on the screen (the program’s output) based on its instructions and on the text that the player typed with the keyboard (the program’s input). A program is just a collection of instructions that act on the user’s input.
There are a few kinds of instructions:
• Expressions are values connected by operators. Expressions are all evaluated down to a single value. For example, 2 + 2 evaluates to 4 or 'Hello' + ' ' + 'World' evaluates to 'Hello World'. When expressions are next to the if and for keywords, you can also call them conditions.
• Assignment statements store values in variables so you can remember the values later in the program.
• The if, for, and break statements are flow control statements that can make the execution skip instructions, loop over instructions, or break out of loops. Function calls also change the flow of execution by jumping to the instructions inside of a function.
• The print() and input() functions display text on the screen and get text from the keyboard. Instructions that deal with the input and output of the program are called I/O (pronounced eye oh).
That’s it—just those four things. Of course, there are many details to be learned about those four types of instructions. In later chapters, you’ll read about more data types and operators, more flow control statements, and many other functions that come with Python. There are also different types of I/O beyond text, such as input from the mouse and sound and graphics output.