Опубликован: 12.07.2013 | Доступ: свободный | Студентов: 985 / 36 | Длительность: 37:41:00
Лекция 9:

Hangman

The random. choice () Function

Now we will have to change our getRandomWord() function so that it chooses a random word from a dictionary of lists of strings, instead of from a list of strings. Here is what the function originally looked like:

61. def getRandomWord(wordList):
62.     # This function returns a random string from the passed list of strings.
63.     wordIndex = random.randint(0, len(wordList) - 1)
64.     return wordList[wordIndex]
Change the code in this function so that it looks like this:
64. def getRandomWord(wordDict):
65.     # This function returns a random string from the passed dictionary of lists of strings, and the key also.
66.     # First, randomly select a key from the dictionary:
67.     wordKey = random.choice(list(wordDict.keys())) 68 .
69.     # Second, randomly select a word from the key's list in the dictionary:
70.     wordIndex = random.randint(0, len(wordDict[wordKey]) -1)
71.
72.     return [wordDict[wordKey] [wordIndex], wordKey]

Line 61 just changes the name of the parameter to something a little more descriptive. Now instead of choosing a random word from a list of strings, first we choose a random key from the dictionary and then we choose a random word from the key's list of strings. Line 65 calls a new function in the random module named choice(). The choice() function has one parameter, a list. The return value of choice() is an item randomly selected from this list each time it is called.

Remember that randint(a, b) will return a random integer between (and including) the two integers a and b and choice(a) returns a random item from the list a. Look at these two lines of code, and figure out why they do the exact same thing:

random.randint(0, 9) 
random.choice(list(range(0, 10)))

Line 64 (line 70 in the new code) has also been changed. Now instead of returning the string wordList[wordIndex], we are returning a list with two items. The first item is wordDict[wordKey][wordIndex]. The second item is wordKey. We return a list because we actually want the getRandomWord() to return two values, so putting those two values in a list and returning the list is the easiest way to do this.

Evaluating a Dictionary of Lists

wordDict[wordKey][wordIndex] may look kind of complicated, but it is just an expression you can evaluate one step at a time like anything else. First, imagine that wordKey had the value 'Fruits' (which was chosen on line 65) and wordIndex has the value 5 (chosen on line 68). Here is how wordDict[wordKey][wordIndex] would evaluate:

wordDict[wordKey][wordIndex]

wordDict['Fruits'][5]

['apple', 'orange', 'lemon', 'lime', 'pear',
'watermelon', 'grape', 'grapefruit', 'cherry',
'banana', 'cantalope', 'mango', 'strawberry',
'tomato'][5]

'watermelon'

In the above case, the item in the list this function returns would be the string 'watermelon'. (Remember that indexes start at 0, so [5] refers to the 6th item in the list.)

There are just three more changes to make to our program. The first two are on the lines that we call the getRandomWord() function. The function is called on lines 109 and 145 in the original program:

108.             correctLetters = ''
109.              secretWord = getRandomWord(words)
110.             gameIsDone = False
...
144.             gameIsDone = False
145.              secretWord = getRandomWord(words)
146.         else:

Because the getRandomWord() function now returns a list of two items instead of a string, secretWord will be assigned a list, not a string. We would then have to change the code as follows:

108. correctLetters = ' '
109.  secretWord = getRandomWord(words)
110.  secretKey = secretWord [1]
111.  secretWord = secretWord[0]
112. gameIsDone = False
...
144. gameIsDone = False
145.  secretWord = getRandomWord(words)
146.  secretKey = secretWord[1]
147.  secretWord = secretWord[0]
148. else:

With the above changes, secretWord is first a list of two items. Then we add a new variable named secretKey and set it to the second item in secretWord. Then we set secretWord itself to the first item in the secretWord list. That means that secretWord will then be a string.

Multiple Assignment

But there is an easier way by doing a little trick with assignment statements. Try typing the following into the shell:

>>> a, b, c = ['apples', 'cats', 42]
>>> a
'apples'
>>> b
'cats'
>>> c
42 
>>>

The trick is to put the same number of variables (delimited by commas) on the left side of the = sign as are in the list on the right side of the = sign. Python will automatically assign the first item's value in the list to the first variable, the second item's value to the second variable, and so on. But if you do not have the same number of variables on the left side as there are items in the list on the right side, the Python interpreter will give you an error.

>>> a, b, c, d = ['apples', 'cats', 42]
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module> a, b, c, d = ['apples', 'cats', 42] ValueError: need more than 3 values to unpack
>>> a, b, c, d = ['apples', 'cats']
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module> a, b, c = ['apples', 'cats'] ValueError: need more than 2 values to unpack 
>>>

So we should change our code in Hangman to use this trick, which will mean our program uses fewer lines of code.

118. correctLetters = ''
119. secretWord, secretKey = getRandomWord(words)
120. gameIsDone = False
...
155. gameIsDone = False
156. secretWord, secretKey = getRandomWord(words)
157. else:

Printing the Word Category for the Player

The last change we will make is to add a simple print() call to tell the player which set of words they are trying to guess. This way, when the player plays the game they will know if the secret word is an animal, color, shape, or fruit. Add this line of code after line 112. Here is the original code:

112. while True:
113.     displayBoard(HANGMANPICS, missedLetters , correctLetters, secretWord)
Add the line so your program looks like this:
122. while True:
123.     print('The secret word is in the set: ' + secretKey)
124.     displayBoard(HANGMANPICS, missedLetters, correctLetters, secretWord)

Now we are done with our changes. Instead of just a single list of words, the secret word will be chosen from many different lists of words. We will also tell the player which set of words the secret word is from. Try playing this new version. You can easily change the words dictionary on line 59 to include more sets of words.

Summary

We're done with Hangman. This has been a long chapter, and several new concepts have been introduced. But Hangman has been our most advanced game yet. As your games get more and more complex, it'll be a good idea to sketch out a flow chart on paper of what happens in your program.

Methods are functions that are associated with values. The return values of methods depend on the values that the method is associated with.

for loops iterate over the items in a list. The range() function is often used with for loops because it is an easy way to create lists of sequential numbers.

Else if statements (which use the elif keyword) will execute their block if their condition is True and the previous if and elif conditions are False

Dictionaries are very similar to lists except that they can use any value for an index. The indexes in dictionaries are called keys. Keys can be strings, integers, or any value of any data type.