PROJECT 3

Guessing Game

Guess what? You’re going to create a game where the computer chooses a number and the player guesses the number.

image

This project teaches you how to get input from the user and how numbers work in Python (they’re different from strings). You create a random number and in the process reuse someone else’s code in your own projects. You also do a little bit of debugging and tracking down logical errors.

Plan the Game

In the guessing game, Python thinks of a random number. The player guesses the number.

  • If the player guesses correctly, Python says so.
  • If the player guesses incorrectly, Python says whether the number is higher or lower.
  • The player keeps guessing until the player gets the right number.

If you did Project 2, you already know how to tell the player something — that’s what print is for. However, what you don’t know about the game at the moment is how to get Python to think of a random number, or how to get a guess from the player.

Get Input from the Player

In practice, your program will always need some kind of input from the user. You’re still using the command line right now, so text is the only way to get input. You get text from a user by using a special built-in called raw_input. It waits for the user to type something and returns to Python what the user types.

Open a Python (command line) prompt by clicking the Python (command line) application that you pinned to your Start menu in Project 1 and try it now:

  1. Type raw_input() at the prompt.
  2. Press Enter.

    You get a blank line.

  3. Type a response.
  4. Press Enter.

What you typed in Step 1 will echo back to you:

>>> raw_input()

I am typing a response. Python won't see this until I press Enter.

"I am typing a response. Python won't see this until I press Enter."

When you type your response and press Enter, whatever you typed is echoed back to the terminal surrounded by single or double quotes. Python was echoing your literals the same way when you entered literals in Project 2. Does this give you an idea how to capture input?

tip In the printout "This is me typing a response. Python won't see this until I press Enter.", double quotes echo my input. This is because I included a ' (won't) in my response.

Ask for Input

You can make raw_input() friendlier by giving it a literal. raw_input() prints the literal to the screen before getting the player's response. In this code, "What is your guess?" is the literal.

tip A line starting with >>> or means that you need to type the rest of the text on that line.

>>> raw_input("What is your guess?")

What is your guess?17

'17'

Python does exactly what you tell it to do, and in this case that’s not so great. It doesn’t insert a space between your string prompt and where the player starts typing. To make it friendlier still, insert your own space at the end of the prompt.

>>> raw_input("What is your guess? ")

What is your guess? 17

'17'

The literal name is between the parentheses. You could replace the name with a variable pointing to a literal:

>>> prompt = 'What is your guess? '

>>> raw_input(prompt)

What is your guess? 17

'17'

tip Including a space at the end of the string makes the player's response easier to read.

How do you capture what the user types? Well, you do the same as you do for any other literal — you name it. In the following code, it’s named players_guess.

>>> prompt = 'What is your guess? '

>>> players_guess = raw_input(prompt)

What is your guess? 17

>>>

>>> players_guess

'17'

The number 17 isn’t echoed immediately because it has been stored in the variable named players_guess. That means you can use that response later in your program.

Make Sure Things Are Equal

tip Your game needs to check whether the guess is the same as the computer’s number. This is a kind of comparison. If you want to test whether a is equal to 1, you can’t write if a= 1: because the equals sign assigns a value to a variable. Python would read this as “if take the value 1 and give it the name a.” Python rightly objects that this is nonsense.

Python uses a special symbol to test whether two things are equal. That symbol is two equals signs together, like this: ==. To test whether the name a contains the value 1 you would type: a == 1. Try it yourself:

>>> a = 1

>>> a == 1

True

>>> a = 2

>>> a == 1

False

Just to reinforce the point that = means an assignment, try these:

>>> 1 == 1

True

>>> 1 == 2

False

>>> 1 = 2

  File "<stdin>", line 1

SyntaxError: can't assign to literal

The first and third lines of code ask Python if 1 is equal to 1 (1 == 1) and if 1 is equal to 2 (1 == 2). In the fifth line you’re telling Python to take the value 2 and store it in the value 1 (1 = 2).

You get a syntax error because 1 isn’t (and can’t be) the name of a variable. You can see that the error text explains that Python can't assign to literal.

When Python sees ==, it compares the value on the left against the value on the right. If they’re equal, Python replaces the entire statement with the value True. If they aren’t equal, Python replaces the entire statement with the value False.

Call the Operators

The equals sign and doubled equals sign are called operators. They work, or operate, on the things on either side of them. Table 3-1 has more common operators. Whenever you want to compare, add, subtract, and so on, use an operator. You need them a lot.

Table 3-1 Common Python Operators

Operator

Name

Effect

Examples

+

Plus

Add two numbers.

Join two strings together.

Add: >>> 1+1

2

Join: >>> 'a'+'b'

'ab'

Minus

Subtract a number from another.

Can’t use for strings.

>>> 1-1

0

*

Times

Multiply two numbers.

Make copies of a string.

Multiply: >>> 2*2

4

Copy: >>> 'a'*2

'aa'

/

Divide

Divide one number by another.

Can’t use for strings.

Python uses / because there’s no ÷ on your keyboard.

Ermagaaard! It’s complicated. See the next section.

%

Remainder (Modulo)

Give the remainder when dividing the left number by the right number.

Formatting operator for strings. (See Project 8.)

>>> 10%3

1

**

Power

x**y means raise x to the power of y.

Can’t use for strings.

>>> 3**2

9

=

Assignment

Assign the value on the right to the variable on the left.

>>> a = 1

==

Equality

Is the left side equal to the right side? True if so; is False otherwise.

>>> 1 == 1

True

>>> 'a' == 'a'

True

!=

Not equal

Is the left side not equal to the right side? True if so; is False otherwise.

>>> 1 != 1

False

>>> 1 != 2

True

>>> 'a' != 'A'

True

>

Greater than

Is the left side greater than the right side?

>= means greater than or equal to

>>> 2 > 1

True

<

Less than

Is the left side less than the right side?

<= means less than or equal to

>>> 1 < 2

True

& (or and)

And

Are both left and right true?

Usually for complex conditions where you want to do something if everything is true:

while im_hungry and you_have_food:

>>> True & True

True

>>> True and False

False

>>> True & (1 == 2)

False

| (or or)

Or

Is either left or right true?

Usually for complex conditions where you want at least one thing to be true:

while im_bored or youre_bored:

>>> True | False

True

>>> True or False

True

>>> False | False

False

>>> (1 == 1) | False

True

Divide in Python

Division in Python 2.7 is a little complicated. Python tries to be helpful when you divide, but usually it hinders more than helps. The reason is that Python changes the answer if one of your numbers has a decimal point in it.

Python treats decimal numbers — called floats, short for floating point numbers — differently from numbers that don’t have decimals. (A number without a decimal is called an integer, a whole number, or an int.) If you try to divide an integer by an integer in Python 2.7, the answer is rounded down to the nearest integer. Ironic, since it’s Python 2.7 and all.

When you want to divide something in Python, use the / operator, like this:

>>> 3/2

1

>>> -3/2

-2

You didn’t get 1.5 or -1.5. You got 1 and -2. You get -2 because Python rounds the negative number -1.5 down and the next integer less than -1.5 is -2.

tip You can avoid rounding by adding a decimal point to either number. Adding the decimal point makes the number a float. If Python’s operating on a float, it does what you’d expect it to do.

In this exercise make sure you add a dot (a period, full stop, decimal point — whatever you want to call it) after either the 3 or the 2 (or after both):

>>> 3/2.

1.5

If the number’s an integer and is stored in a variable, you don’t have anywhere to put your decimal point. In that case, use the float() built-in to convert it to a float, like you see here with 3/float(a):

>>> a=2

>>> 3/a

1

>>> 3/float(a)

1.5

>>>

Compare the Guess to a Number

Remember this code (you don’t need to retype this):

>>> prompt = 'What is your guess? '

>>> raw_input(prompt)

What is your guess? 17

'17'

When Python echoes the input back, the input is in single or double quotes. This should be a flag to you that Python sees these responses as strings. Python doesn’t even see the '17' as a number.

A quick way to test whether Python thinks something is a number is by trying to add a number to it:

>>> a=1

>>> a+1

2

First you store 1 in a. Then you add 1 to it. No problem, because a has a number in it. However, when you try to add 1 to players_guess:

>>> players_guess = raw_input(prompt)

What is your guess? 17

>>> players_guess+1

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

TypeError: cannot concatenate 'str' and 'int' objects

Problem! Something’s wrong with players_guess. Python tells you that it “cannot concatenate 'str' and 'int' objects”. Python isn’t even trying to add them — concatenate means to join them. Confirm what players_guess is by printing it out:

>>> players_guess

'17'

As you expect, players_guess is '17'. (Note the single quotes.) The ones around 17 keep Python from understanding it as a number.

tip raw_input always returns a string. Whatever the player types, even if it’s just a number, you’re going to get a string from raw_input. To compare the guess, you need to convert (change) the player's guess into a number.

Say that the computer has come up with 17. To compare the variable players_input to this number, follow these steps:

  1. Store the value in a variable:

    >>> computers_number = 17

  2. Compare the player's guess with the number the computer came up with by using the equality operator ==:

    >>> computers_number == players_guess

    False

    This code — computers_number == players_guess — asks if 17 is equal to '17'. At the moment, the comparison is False. That's because the player's guess is still stored as a string and a string is never equal to a number. So the comparison will always be False.

  3. Convert the player's guess into a number by using the int() built-in:

    >>> computers_number == int(players_guess)

    True

The int built-in takes a string that has a whole number and changes it into something Python recognizes as a number. The int() built-in will fail if the string has a decimal number or doesn't have a number. Empty spaces before and after the number are okay.

Here are some examples:

>>> int('1.0')

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

ValueError: invalid literal for int() with base 10: '1.0'

tip You get an error because 1.0 isn’t an integer. int doesn’t know how to convert decimal numbers. In the next example, Python gets confused by the words fine day in the string:

>>> int('1 fine day')

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

ValueError: invalid literal for int() with base 10: '1 fine day'

Finally, int can deal with extra spaces around an otherwise valid number:

>>> int('        17        ')

17

Compare the Player’s Guess to the Computer’s Number

When you can compare the guess with the answer, you can print a response for the player.

tip Remember whenever you’re coding:

  • The colon (:) means that a new code block is about to follow.
  • On the line after the colon, and every other line in the block, you need to start with four spaces.

Check out this block of code:

>>> if computers_number == int(players_guess):

…        print("Correct!")

Correct!

The if statement is here in all its glory. This if is another one of Python’s keywords. The statement is followed immediately by a condition: Is computers_number equal to players_guess after it’s converted to an integer? This is followed by a colon, also known as “Hey Python, expect a code block.”

If the condition is true, Python executes (runs) the code block. If it isn’t true, Python skips the code block and continues execution at the next statement after the end of the code block. You can think of if like an if … then phrase in English (minus the then).

tip Try the following example, but remember:

  • Each colon signals that a new code block is about to follow.
  • On the line after the colon, and every other line in the block, start with four spaces.

    >>> if 1==2:

    …      print("Correct!")

    >>> if 1==1:

    …      print("Correct!")

    Correct!

In the first example, since 1 isn’t equal to 2, the print statement ("Correct!") was skipped. Nothing happened. If there were more to the code block, the whole code block would be skipped. In the second example, 1 is equal to 1, so the print statement is executed. You get a big, juicy Correct!

Tell Players If the Guess Is Wrong

What happens if the player guesses the wrong answer? Python’s got your back on that too.

tip Always be thinking of how to give players feedback for their actions, even in simple programs.

In the following code block, you see the if keyword. The else keyword changes the operation of the if keyword. Unlike if, else doesn’t take a condition. It’s always executed when a preceding if code block isn’t executed. You use if/else where you want to execute one of two code blocks, but not both.

The following code continues from where you left off. It assumes that computers_number = 17 and players_guess = '17'.

>>> if computers_number == int(players_guess)+1:

…        print('Correct!')

… else:

…        print('Wrong! Guess again')

Wrong! Guess again

In this code I added +1 to make the values different on purpose. Otherwise, the else: code block won’t execute.

You can see that else is followed by a colon and — not much of a surprise here — a code block. You know it’s a code block because it’s indented by four spaces from the indent level of the else. (Speaking of indentation: Line up the beginning of the else keyword with the beginning of the if keyword before it.)

If the if condition is True, then its code block is executed and the code block following the else is ignored. The keyword else means “Otherwise, do this stuff.” If the condition is False, then the code block following the if is ignored and the one after the else is executed.

Even this doesn’t say why the guess is wrong. You have to show players whether the guess is too high or too low.

What you need is a test. (I know, a test is probably the last thing you really need.) The test tells players whether they’re right on, too low, or too high.

>>> if computers_number == int(players_guess):

…        print('Correct!')

… elif computers_number > int(players_guess):

…        print('Too low')

… else:

…        print('Too high')

Correct!

tip It turns out if has one last trick up its sleeve — elif. You use elif (short for else if) after an if to test other things when the first condition isn’t satisfied. You can string together as many elifs in a row as you like.

For example, suppose you want to do different things if a is equal to 1, 2, and 3 respectively. You can use the elif structure to test each individually:

>>> a = 3

>>> if a == 1:

…        print('a is 1!')

… elif a == 2:

…        print('a is 2!')

… elif a == 3:

…        print('a is 3!')

… else:

…        print("I don't know what a is")

a is 3!

tip If you have more than a couple elifs in a row, try solving the problem another way instead.

Test that this elif structure works. Tell the player when the guess is too high or too low:

>>> computers_number = 16

>>> if computers_number == int(players_guess):

…        print('Correct!')

… elif computers_number > int(players_guess):

…        print('Too low')

… else:

…        print('Too high')

Too high

>>> computers_number = 18

>>> if computers_number == int(players_guess):

…        print('Correct!')

… elif computers_number > int(players_guess):

…        print('Too low')

… else:

…        print('Too high')

Too low

Retype that. Yes, really. It’s tedious but life will get easier in Project 4. Other things to notice about this code:

  • All the print statements have the same number of spaces in front of them (indented four spaces or one level).
  • All of the if, elif, and else have the same number of spaces in front of them (no indents).
  • The computer’s number was set lower, then higher, than the guess (17) to test the comparison logic.
  • When the computer’s number is set lower (16), Python prints that the player’s guess is too high.
  • When the computer’s number is set higher (18), Python prints that the player’s guess is too low.

Keep Asking Until the Player Guesses Correctly

Now you know how to ask for the player’s guess, how to convert (change) the answer into a number, and how to compare the player’s answer to the computer’s number.

You still need to set something up so that the computer keeps asking if the player doesn’t guess the number. You do this by

  • Putting the code that asks for the player’s guess and tests its value in a while loop.
  • Using the break statement when the correct answer is given. This lets you break out of the loop.

    >>> computers_number = 17

    >>> prompt = 'What is your guess? '

    >>> while True:

    …        players_guess = raw_input(prompt)

    …        if computers_number == int(players_guess):

    …              print('Correct!')

    …              break

    …        elif computers_number > int(players_guess):

    …              print('Too low')

    …        else:

    …              print('Too high')

    What is your guess? 3

    Too low

    What is your guess? 93

    Too high

    What is your guess? 50

    Too high

    What is your guess? 30

    Too high

    What is your guess? 20

    Too high

    What is your guess? 10

    Too low

    What is your guess? 19

    Too high

    What is your guess? 16

    Too low

    What is your guess? 18

    Too high

    What is your guess? 17

    Correct!

The break statement is bold here so you can see it easily. The break statement allows you to exit any loop that Python’s already in, regardless of conditions on the enclosing loops. For example, say you have a whole heap of colors and want to see if the red is one of them. You’d set up a loop to run through all the colors. But if you found red halfway through (or even on the first try), there’d be no point continuing. You could use break to stop the loop.

tip break is also a keyword. (You’re barreling through all the keywords you need to know!) Only use it inside a loop:

>>> break

  File "<stdin>", line 1

SyntaxError: 'break' outside loop

If you have a loop inside a loop, the break applies to the loop level that the break appears in (or its relevant flow control statement, because it’s almost always subject to a condition).

Here are some examples of how break works. In the next code excerpt:

  • The code uses the built-in str(). The str built-in converts a number to a string. You can join strings together using the + operator. (Operators are in Table 3-1 earlier.)
  • There are two loops — an inner loop on j that counts more quickly, and an outer loop on i that counts more slowly.
  • The break is encountered when the value of i reaches 1 (up from 0). Since the break is in the inner loop’s code block, it only breaks out of the inner loop. You can tell because i keeps counting up to 2, but j resets at 0 when i is 1.

    >>> for i in range(3):

    …        for j in range(3):

    …              print(str(i)+", "+str(j))

    …              if i == 1:

    …                 break

     

     

    0, 0

    0, 1

    0, 2

    1, 0

    2, 0

    2, 1

    2, 2

To break the outer loop, you need to be in the outer loop’s code block. In particular, the code if i == 1: is indented by four spaces, not eight as in the previous example.

Here, the outer loop stops when i is 1. The outer loop never makes it to 2:

>>> for i in range(3):

…        for j in range(3):

…              print(str(i)+", "+str(j))

…        if i == 1:

…              break

 

 

0, 0

0, 1

0, 2

1, 0

1, 1

1, 2

Take a moment to think about what’s happening with these loops, and try some of your own.

Make Python Think of a Random Number

The player’s guessing numbers. How do you get Python to think of a number?

The random integer feature randint is from the random module. It gives you a random number between two numbers that you put in the parenthesis that follows randint. The number will include the lowest or highest number. If you want a number between 6 and 10 (inclusive), use random.randint(6,10).

>>> import random

>>> random.randint(1,100)

67

>>> help(random.randint)

Because this is a new feature, type help(random.randint) at the Python prompt and read what it tells you. If you don’t get back the >>> prompt, press q when you’re finished.

>>> random.randint(1,100)

15

>>> random.randint(1,100)

72

>>> random.randint(1,100)

25

>>> random.randint(1,100)

36

>>> random.randint(1,100)

90

>>> random.randint(1,100)

81

>>> random.randint(1,100)

23

Simple, huh? See how the number is changing?

But you can’t just up and use random.randint like you can with built-ins such as raw_input and str. To use random.randint, you must tell Python that you want to use a function from the random module — import random.

This code example uses a new keyword. The import statement makes a module (in this case the random module) available to Python. You can use all the features in the module after you import it.

remember Why would you want to import a module? Modules are Python’s way of organizing collections of features together. For example, stuff relating to random numbers is in the random module. Stuff for math is in the math module. Stuff related to dates and times is in the datetime module. Stuff for saving your data is in the pickle module. (Wait. What?)

You have already met some features — int, range, and raw_input. But you didn’t need to import anything to use them because they’re built in to Python (which is why they’re called built-ins). They’re always available when Python is running.

The random module isn’t a built-in, so it isn’t always available. You get an error if you start a new Python prompt and try random.randint(1,100):

Python 2.7.3 (default, Apr 14 2012, 08:58:41) [GCC] on linux2

Type "help", "copyright", "credits" or "license" for more information.

>>> random.randint(1,100)

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

NameError: name 'random' is not defined

The random module does come with Python, but unlike the built-ins, it isn’t loaded automatically. The random module is part of the Python standard library. If you need it, you must import it.

Why can’t Python just automatically load everything? Because it would make programming boring. Every time you ran a program, you’d need to wait while it found and loaded all the modules in the standard library.

Besides giving you access to the standard library, the import statement also lets you use modules that someone else has written (called third-party modules). To use those, you have to download and install them on your computer.

Use Namespaces

The dot syntax is another important part of what’s going on in this line of code: >>> random.randint(1,100). You put the random module and the randint feature together with a dot.

The built-ins you saw earlier were referred to directly by their names. This way of referencing (called a namespace) turns out to be one honking great idea.

If you always refer to these features by their names without identifying their modules, then you’d have trouble. What if you had two modules with a feature of the same name? It would be like everyone in class being named Jaden. Python would have the same trouble if you didn’t identify a feature by its module name and its feature name.

Finish Your Guessing Game

It’s time to finish off the guessing game. The final touches on the guessing game turn out to be pretty straightforward. At the start of the program you

  • import the random module
  • Make the computer guess a number using random.randint()
  • Store the computer’s number

When you add these changes to the code, you get this. The first three lines are new:

>>> import random

>>>

>>> computers_number = random.randint(1,100)

>>> prompt = 'What is your guess? '

>>> while True:

…        players_guess = raw_input(prompt)

…        if computers_number == int(players_guess):

…              print('Correct!')

…              break

…        elif computers_number > int(players_guess):

…              print('Too low')

…        else:

…              print('Too high')

What is your guess? 24

Too low

What is your guess? 86

Too low

What is your guess? 94

Too low

What is your guess? 98

Too high

What is your guess? 96

Too high

What is your guess? 95

Correct!

Summary

This project covered:

  • Getting input from a user by prompting for information.
  • Python treating numbers and strings differently, and getting a number from a string (int) and a string from a number (str).
  • Testing whether two things are equal.
  • Python’s operators, including tricky stuff about integer versus floating-point division and how to join strings together with +.
  • Five keywords: break, elif, else, if, and import. (Only 21 to go.)
  • Python code blocks, that you need to align their indent levels, and that each indent level should be four spaces.
  • A couple of built-ins — int and str.
  • How to import modules from the standard library.
  • The random module and its random.randint feature.
  • Another value — False. (One to go.)
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.190.232