Опубликован: 12.07.2013 | Уровень: специалист | Доступ: платный
Лекция 11:

Bagels

< Лекция 10 || Лекция 11: 12 || Лекция 12 >
Аннотация: In this chapter you will learn a few new methods and functions that come with Python.

Topics Covered In This Chapter:

  • Hard-coding
  • Augmented Assignment Operators, +=, -=, *=, /=
  • The random.shuffle() Function
  • The sort() List Method
  • The join() List Method
  • String Interpolation (also called String Formatting)
  • Conversion Specifier %s
  • Nested Loops

In this chapter you will learn a few new methods and functions that come with Python. You will also learn about augmented assignment operators and string interpolation. These concepts don't let you do anything you couldn't do before, but they are nice shortcuts that make typing your code easier.

Bagels is a simple game you can play with a friend. Your friend thinks up a random 3-digit number with no repeating digits, and you try to guess what the number is. After each guess, your friend gives you clues on how close your guess was. If the friend tells you "bagels", that means that none of the three digits you guessed is in the secret number. If your friend tells you "pico", then one of the digits is in the secret number, but your guess has the digit in the wrong place. If your friend tells you "fermi", then your guess has a correct digit in the correct place. Of course, even if you get a pico or fermi clue, you still don't know which digit in your guess is the correct one.

You can also get multiple clues after each guess. Say the secret number is 456, and your guess is 546. The clue you get from your friend would be "fermi pico pico" because one digit is correct and in the correct place (the digit 6), and two digits are in the secret number but in the wrong place (the digits 4 and 5).

Sample Run

I am thinking of a 3-digit number. Try to guess what it is.
Here are some clues:
When I say:    That means:
Pico                   One digit is correct but in the wrong position.
Fermi        One digit is correct and in the right position.
Bagels       No digit is correct. I have thought up a number. You have 10 guesses to get it. Guess #1:

123

Fermi Guess #2:

453

Pico Guess #3:

425

Fermi Guess #4:

326

Bagels Guess #5:

489

Bagels Guess #6:

075

Fermi Fermi Guess #7:

015

Fermi Pico Guess #8:

175

You got it!
Do you want to play again? (yes or no)

no

Bagel's Source Code

bagels.py

This code can be downloaded from http://inventwithpyt.hon.com/bagels.py

If you get errors after typing this code in, compare it to the book's code with the online

diff tool at http://inventwithpython.com/diff or email the author at

al@inventwithpython.com

1.  import random
2. def getSecretNum(numDigits):
3.     # Returns a string that is numDigits long, made up of unique random digits.
4.     numbers = list(range(10))
5.     random.shuffle(numbers)
6.     secretNum = ''
7.     for i in range(numDigits):
8.         secretNum += str(numbers[i])
9.     return secretNum 
10.
11. def getClues(guess, secretNum):
12.     # Returns a string with the pico, fermi, bagels clues to the user.
13.     if guess == secretNum:
14.         return 'You got it!' 
15.
16.     clue = [] 
17.
18.     for i in range(len(guess)):
19.         if guess[i] == secretNum[i]:
20.             clue.append('Fermi')
21.         elif guess[i] in secretNum:
22.             clue.append('Pico')
23.     if len(clue) == 0:
24.         return 'Bagels' 
25.
26.     clue.sort()
27.     return ' '.join(clue) 
28.
29. def isOnlyDigits(num):
30.     # Returns True if num is a string made up only of digits. Otherwise returns False.
31.     if num == '':
32.         return False 
33.
34.     for i in num:
35.         if i not in '0 1 2 3 4 5 6 7 8 9'.split():
36.             return False 
37.
38.     return True 
39.
40. def playAgain():
41.     # This function returns True if the player wants to play again, otherwise it returns False.
42.     print('Do you want to play again? (yes or no)')
43.     return input().lower().startswith('y') 
44.
45. NUMDIGITS = 3
46. MAXGUESS = 10 
47.
48. print('I am thinking of a %s-digit number. Try to guess what it is.' % (NUMDIGITS))
49. print('Here are some clues:')
50. print('When I say:    That means:')
51. print('  Pico                   One digit is correct but in the wrong position.')
52. print('  Fermi                  One digit is correct and in the right position.')
53. print ('  Bagels                No digit is correct.') 
54 .
55. while True:
56.      secretNum = getSecretNum(NUMDIGITS)
57.     print('I have thought up a number. You have %s guesses to get it.' % (MAXGUESS))
58 .
59.     numGuesses = 1
60.     while numGuesses <= MAXGUESS:
61.         guess = ''
62.         while len(guess) != NUMDIGITS or not isOnlyDigits (guess):
63.             print('Guess #%s: ' % (numGuesses))
64.             guess = input() 
65 .
66.         clue = getClues(guess, secretNum)
67.         print(clue)
68.         numGuesses += 1 
69 .
70.          if guess == secretNum:
71.             break
72.          if numGuesses > MAXGUESS:
73.             print('You ran out of guesses. The answer was %s.' % (secretNum))
74 .
75.      if not playAgain() :
76.         break

Designing the Program

Here is a flow chart for this program. The flow chart describes the basic events of what happens in this game, and in what order they can happen:

Flow chart for the Bagels game.

Рис. 11.1. Flow chart for the Bagels game.

And here is the source code for our game. Start a new file and type the code in, and then save the file as bagels.py. We will design our game so that it is very easy to change the size of the secret number. It can be 3 digits or 5 digits or 10 digits. We will do this by using a constant variable named NUMDIGITS instead of hard-coding the integer 3 into our source code.

Hard-coding means writing a program in a way that it changing the behavior of the program requires changing a lot of the source code. For example, we could hard-code a name into a print() function call like: print('Hello, Albert'). Or we could use this line: print('Hello, ' + name) which would let us change the name that is printed by changing the name variable while the program is running.

How the Code Works: Lines 1 to 9

At the start of the program we import the random module and also create a function for generating a random secret number for the player to guess. The process of creating this number isn't hard, and also guarantees that it only has unique digits in it.

1. import random

This game imports the random module so we can use the module's random number functions.

Shuffling a Unique Set of Digits
2. def getSecretNum(numDigits):
3.     # Returns a string that is numDigits long, made up of unique random digits.
4.     numbers = list(range(10))
5.     random.shuffle(numbers)

Our first function is named getSecretNum(), which will generate the random secret number. Instead of having the code only produce 3-digit numbers, we use a parameter named numDigits to tell us how many digits the secret number should have. (This way, we can make the game produce secret numbers with four or six digits, for example, just by passing 4 or 6 as numDigits.)

You may have noticed that the return value of our call to range() was in turn passed to a function called list(). The list() function returns a list value of the value passed to it, much like the str() function returns a string form or the int() function returns an integer form. The reason we do this is because the range() function technically does not return a list but something called an iterator object. Iterators are a topic that you don't need to know at this point, so they aren't covered in this book.

Just about every time we use the range() function it is in a for loop. Iterators are fine to use in for loops (just like lists are), but if we ever want to store a list of integers in a variable, be sure to convert the return value of range() to a list with the list() function first. (Just like we do on line 4.)

< Лекция 10 || Лекция 11: 12 || Лекция 12 >
Марат Хасьянов
Марат Хасьянов
Россия
Роман Дрындик
Роман Дрындик
Россия