Learn-by-example lessons with games and puzzles

Guessing Game

The Guessing Game

Create a new Python file (called a "module") with the name "guess.py".  In that file, type in the following short program code.  If you have a friend with you, print the code and take turns having one read the code out loud while the other types.  About halfway through, switch jobs so that you both get a chance to get comfortable with the editor and naming the different symbols that are typed.  For now, you can ignore the comment lines that begin with "#".  We'll talk more about comments later.

When a line is indented by some number of tabs and spaces, make sure you use the exact same number of tabs/spaces for other lines that are indented the same.  This is how code is grouped into code blocks in Python.  The idle editor helps you with this, guessing where you want to indent to after you press Enter at the end of the line.  You'll usually only need to do a Tab or Backspace here or there.

When you're done typing, save the file and run the module.  Does the game work correctly?  If so, it should look something like this when you play:

If not, carefully check your code line-by-line.  Select all of your code and remove all tabs (replacing with spaces) with Alt-6 (or menu Format → Untabify Region).  Read error messages carefully, paying attention to line numbers and other possible clues hinting at the location and type of error you are seeking.

Once you've entered in the program, have some fun playing with it.  Enjoy your work.  Feel free to change the messages that are printed to be something more like what you would say if you were playing.  Next, we'll look at the program part by part to see what it does. 

The first think to notice is that several of the line start with the number sign "#".  The number sign lets Python know that it should ignore everything else to the end of the line.  This allows programmers to leave each other comments.  Comments are helpful messages and information that help another programmer understand what a program does, how it works, how to use it, who wrote it, etc.  When you are writing a program, you are writing for two audiences.  The first audience is the computer.  The computer cares only that you have written legal instructions according to the rules of the programming language.  The second audience is programmers.  Comments help other programmers understand how you've solved a problem and why.  They make it easier for others to fix, change, and extend your code.  Also, your comments can help you when you return to your code at a later time and don't remember your thoughts as your created it.  Finally, it is often good for programmers to outline code with comments in the same way a good writer outlines a paper before writing.

The first program statement that Python pays attention to is this:

import random
Python has many useful programs (called modules) available for use, but the programmer needs to import a module in order to use it.  The random module allows us to generate random numbers for choosing secret numbers, simulating dice, and many other useful tasks.
lowest = 1
highest = 100
Next, we set the lowest and the highest numbers that can be chosen for guessing.  The statement "lowest = 1" is a variable assignment.  The variable "lowest" is a named place in the computer's memory where we can store a value.  When you see the equal sign "=", don't think about mathematical equality.  Think about the value to the right of the "=" being placed in the location to the left.  So, the statement "lowest = 1" places the value 1 in variable "lowest", and the statement "highest = 100" places the value 100 in variable "highest".  In the next lines, you'll see that we can now refer to these values using their names.  This makes the program code easier to understand.  (Well-chosen variable names are as important as good comments.)  It also keeps us from having unexplained values scattered here and there throughout the program.
secret = random.randint(lowest, highest)
Here we assign a new variable "secret", but the value that appears on the right hand side is more complicated that what we have seen.  With "random.randint(lowest, highest)", we are sending a message requesting a value to be assigned to secret.  The message is send to the random module, calling out for a random integer (randint) with lowest and highest being the lowest and highest possible values for that integer.  Don't be concerned if you don't understand this kind of function call at first.  Starting out, it is more important that you know that your program can send messages requesting information or computation, and how some of these messages are put together.  This message gets a secret random number in our given range.  This value is then stored in variable "secret".  The next line has a different kind of message:  
print('I am thinking of a number from {0} to {1}.'.format(lowest, highest))
This message is a request for Python to print information for the user to read.  The message is a string of characters inside of parenthesis, so our string here is "'I am thinking of a number from {0} to {1}.'.format(lowest, highest)".   Actually, this is a string expression.  Just as an arithmetic expression such as (1 + 2) is evaluated to 3 and can be replaced by 3, this string expression lets Python know how the string should be put together into a string value that is printed.  The first part, 'I am thinking of a number from {0} to {1}.', is a string with placeholders {0} and {1} to let the format function know where information should be placed in the string.  That information is inserted by sending a message to format with a list (inside of parentheses) of items to be inserted.  When you see a curly brace placeholder such as {1}, that tells you where to find your item in the list.  Point your finger to the first item, and then count that many items to the right.  So for {1}, we look 1 item to the right of the first item, that is, the second item.  For {0}, we look 0 (no) items to the right of the first item.  That is, we want the first item.  In this way, the lowest and highest values are inserted into our string so that what Python prints is 'I am thinking of a number from 1 to 100.'  If different values were in lowest and highest, those different values would be inserted.  Variables give us flexibility to change program behavior.
gameOver = False
In addition to integers and strings, we also have Boolean (logical) values True and False.   Here we assign False to variable gameOver.  This will help us keep track of whether the game is over and we are done taking turns.
while not gameOver: 
    <take a turn>
Here, I am using <take a turn> as a placeholder for all of the remaining indented code after the while line.  In general, I will use the less-than and greater-than symbols (sometimes called "angle brackets"), to mark parts of code and present them simply.  The while indicates a loop, a part of code that allows code to be executed again and again as long as some condition is met.  In this case, all the code that follows (<take a turn>) is executed again and again as long as not gameOver is True.  In the previous line, we assigned False to variable gameOver.  When Python first executes the while, the expression not gameOver evaluates as not False, which is True, so the first turn is taken.  In the turn-taking code, we can simply assign True to variable gameOver whenever the game is over and we do not wish to have any more turns.
    guess = int(input('Your guess? '))  
At the start of the turn, we first input (or read) the user's guess for the secret number.  This is accomplished with input('Your guess? '), a message to read input from the user after printing the given string 'Your guess? '.  Suppose the user enters '50'.  The value we receive back from this message is a string with the characters '5' and '0'.   But we don't want a string.  We want a number.  Happily, using the expression int(<string>), we can take any string of an integer value and convert it to an integer (int).  So this line causes Python to print 'Your guess? ', wait for the user's typed input, convert that input to an integer, and store it in a new variable guess.  Again, don't feel that you need to understand everything at this stage.  For now, think of this as an example of how you ask the user for an integer, get it, and store it in a variable.  If you were writing a program and wanted to ask the person for their age, you could look at this example and make a few changes to get an appropriate statement such as age = int(input('What is your age? ')).   In this style of learning, simply notice the patterns that are used in programs again and again.  Over time, start to imitate the patterns, use them, and make them your own.  Over time and experience, you will gain a deeper understanding.
    if guess == secret:  
        print('Correct!')
        gameOver = True
Now that we have the user's guess, we want to respond differently depending on whether the guess was correct, too high, or too low.  This code essentially says, "If the user's guess is the same as the secret number, tell the user it is correct and signal the end of the game."  This is an example of an if decision.  If decisions are of the form "if <true/false condition>:" followed by an intended section of code that is executed if the condition is True.  In this case the condition is "guess == secret".  Note that this is not an assignment.  The double-equals (==) are for comparing two values to see if they are equal.  Assignment uses a single equal.  If guess and secret have the same value then the Boolean expression guess == secret has the value True, and the indented code after the if <true/false condition>: is executed.  In this case, the string 'Correct!' is printed and gameOver is assigned True.  However, if guess and secret do not have the same value, then the condition is False and the indented code is not executed.  But that's not the end of the story.  If the user's guess is not correct, there are still two other possibilities to consider.
    elif guess > secret:
        print('Lower.')
This is an optional add-on part to the if decision.  If the condition to the first if is False (e.g. The user's guess was not correct.), we sometimes want to consider other cases (e.g. Was the guess too high?  Was the guess too low?).  Here elif is short for "else if", and can be thought of as "otherwise, if".  Looking at the previous program lines with these, the code essentially says, "If the user's guess was correct (which it was not), tell the user it is correct and signal the end of the game, otherwise, if the user's guess is greater than the secret number, print 'Lower.'.  We can use  to handle case after possible case in our code.  Eventually, when there is only one remaining case, we sometimes want to have some code execute without condition.  That happens with the else:
    else:
        print('Higher.')
If the user wasn't correct, and their guess was not too high, then we know the guess had to be too low, so we have Python print 'Higher.'.  Notice the importance of indentation to let Python know which lines are part of the while loop, and which lines are the response to each if/elif/else case.  If the indentation of a sequence of lines is the same, the lines are treated as a group, so be careful with your indentation!

After this else section, there is no more code in the module.  What happens when Python has complete executing the end of the indented group of while code?  Python returns to the while to check the condition again.  If the condition is still True, the indented code is executed again.  If not, we continue execution after the while loop.  If there is no code after the while loop, as in this case, the execution is complete and the program stops (terminates).  We're done.

Right now would be a good time to play the game while looking at the code in a separate window.  Try to understand the connection between the code and what you see happening during the program's execution.  Save your work, and don't be afraid to experiment with the program.  Play with it.  Modify it.  See how you can affect its behavior.  When you feel comfortable, consider trying some of the Challenge Problems below to test and stretch your understanding of this program.  At first, you may only be able to complete a few of the simplest challenges.  The greater challenges will be waiting for you to enjoy when you have more experience and have seen more programming patterns.  Enjoy!

Challenge Problems

When you understand programming fundamentals and how the program above works, try the following challenge problems.  Even your mistakes will teach you and help you become a better problem solver.

Challenge 1:  At the start of the program, ask the user to input the highest possible secret number.

Challenge 2:  Count the number of player guesses. At the end of the game, print the number of player guesses.

Challenge 3:  Before each guess, provide the user with the range of possible numbers the secret number could be. For example, suppose the range starts as 1-100. If the initial guess of 50 is too low, then before the next guess, the range is reported as 51-100. If the next guess of 75 is too high, then before the next guess, the range is reported as 51-74.

Challenge 4:  After each game, allow the user to quit or play another game with the same secret number range.

Challenge 5:  Modify your Challenge 3 program so that it plays automatically.  Instead of asking the user for a guess, calculate a guess that is in the middle of the range for challenge 3.  Hint: In computing the average of the range minimum and maximum, don't forget to use integer division (//).  Have the program print each guess as if the user was typing  it.

Challenge 6:  As with Challenge 5, the program will do the guessing, except this time you will create a whole new program that asks the user to think of a number from 1 to 100, makes guesses and asks the user for feedback of higher (">"), lower ("<"), or correct ("=="). 


© 2009 Todd Neller