Hangman Game C++ That Plays Again
8
WRITING THE HANGMAN CODE
This chapter's game introduces many new concepts, but don't worry: you'll experiment with them in the interactive shell earlier really programming the game. You lot'll learn about methods, which are functions attached to values. You'll also larn nearly a new information blazon called a listing. In one case you understand these concepts, it volition exist much easier to program Hangman.
Source Code for Hangman
This chapter's game is a scrap longer than the previous games, but much of it is the ASCII art for the hanging man pictures. Enter the post-obit into the file editor and save information technology equally hangman.py. If you become errors later entering the following code, compare the code y'all typed to the book's lawmaking with the online diff tool at https://world wide web.nostarch.com/inventwithpython#diff.
hangman.py
one. import random
two. HANGMAN_PICS = ['''
3. +---+
4. |
5. |
6. |
7. ===''', '''
8. +---+
ix. O |
10. |
11. |
12. ===''', '''
13. +---+
14. O |
15. | |
sixteen. |
17. ===''', '''
18. +---+
19. O |
twenty. /| |
21. |
22. ===''', '''
23. +---+
24. O |
25. /|\ |
26. |
27. ===''', '''
28. +---+
29. O |
thirty. /|\ |
31. / |
32. ===''', '''
33. +---+
34. O |
35. /|\ |
36. / \ |
37. ===''']
38. words = 'ant baboon badger bat bear beaver camel cat clam cobra cougar
coyote crow deer domestic dog donkey duck eagle ferret fox frog caprine animal goose militarist
lion lizard llama mole monkey moose mouse mule newt otter owl panda
parrot pigeon python rabbit ram rat raven rhino salmon seal shark sheep
skunk sloth snake spider stork swan tiger toad trout turkey turtle
weasel whale wolf wombat zebra'.carve up()
39.
twoscore. def getRandomWord(wordList):
41. # This function returns a random string from the passed list of
strings.
42. wordIndex = random.randint(0, len(wordList) - 1)
43. return wordList[wordIndex]
44.
45. def displayBoard(missedLetters, correctLetters, secretWord):
46. impress(HANGMAN_PICS[len(missedLetters)])
47. print()
48.
49. impress('Missed letters:', end=' ')
50. for alphabetic character in missedLetters:
51. print(letter, terminate=' ')
52. print()
53.
54. blanks = '_' * len(secretWord)
55.
56. for i in range(len(secretWord)): # Supervene upon blanks with correctly
guessed letters.
57. if secretWord[i] in correctLetters:
58. blanks = blanks[:i] + secretWord[i] + blanks[i+1:]
59.
lx. for letter in blanks: # Bear witness the secret discussion with spaces in between
each letter.
61. print(letter, stop=' ')
62. print()
63.
64. def getGuess(alreadyGuessed):
65. # Returns the letter the player entered. This role makes certain the
player entered a single letter and not something else.
66. while True:
67. print('Gauge a alphabetic character.')
68. gauge = input()
69. guess = guess.lower()
70. if len(guess) != 1:
71. print('Delight enter a single letter.')
72. elif estimate in alreadyGuessed:
73. print('You accept already guessed that letter. Choose once more.')
74. elif guess non in 'abcdefghijklmnopqrstuvwxyz':
75. print('Please enter a LETTER.')
76. else:
77. render guess
78.
79. def playAgain():
80. # This part returns True if the player wants to play once more;
otherwise, it returns False.
81. print('Practice you want to play again? (yes or no)')
82. return input().lower().startswith('y')
83.
84.
85. print('H A North Thou Thou A Due north')
86. missedLetters = ''
87. correctLetters = ''
88. secretWord = getRandomWord(words)
89. gameIsDone = False
ninety.
91. while True:
92. displayBoard(missedLetters, correctLetters, secretWord)
93.
94. # Permit the role player enter a letter.
95. estimate = getGuess(missedLetters + correctLetters)
96.
97. if guess in secretWord:
98. correctLetters = correctLetters + guess
99.
100. # Check if the player has won.
101. foundAllLetters = True
102. for i in range(len(secretWord)):
103. if secretWord[i] non in correctLetters:
104. foundAllLetters = Simulated
105. suspension
106. if foundAllLetters:
107. print('Yes! The secret discussion is "' + secretWord +
'"! You accept won!')
108. gameIsDone = Truthful
109. else:
110. missedLetters = missedLetters + estimate
111.
112. # Bank check if histrion has guessed likewise many times and lost.
113. if len(missedLetters) == len(HANGMAN_PICS) - 1:
114. displayBoard(missedLetters, correctLetters, secretWord)
115. print('You have run out of guesses!\nAfter ' +
str(len(missedLetters)) + ' missed guesses and ' +
str(len(correctLetters)) + ' correct guesses,
the word was "' + secretWord + '"')
116. gameIsDone = True
117.
118. # Ask the actor if they desire to play once again (but only if the game is
done).
119. if gameIsDone:
120. if playAgain():
121. missedLetters = ''
122. correctLetters = ''
123. gameIsDone = Faux
124. secretWord = getRandomWord(words)
125. else:
126. break
Importing the random Module
The Hangman program randomly selects a secret discussion for the player to guess from a list of words. The random module will provide this ability, so line i imports it.
1. import random
Simply the HANGMAN_PICS variable on line 2 looks a piffling different from the variables we've seen so far. In order to empathise what this code means, we need to learn about a few more concepts.
Constant Variables
Lines 2 to 37 are ane long assignment statement for the HANGMAN_PICS variable.
2. HANGMAN_PICS = ['''
3. +---+
4. |
five. |
6. |
seven. ===''', '''
--snip--
37. ===''']
The HANGMAN_PICS variable'due south proper noun is in all capital letters. This is the programming convention for constant variables. Constants are variables meant to take values that never alter from their first assignment statement. Although you can modify the value in HANGMAN_PICS just equally you can for any other variable, the all-upper-case letter name reminds you not to practise so.
Equally with all conventions, you don't accept to follow this one. Merely doing then makes it easier for other programmers to read your code. They'll know that HANGMAN_PICS will e'er have the value it was assigned from lines two to 37.
The Lists Data Type
HANGMAN_PICS contains several multiline strings. Information technology can do this because it's a list. Lists have a listing value that can contain several other values. Enter this into the interactive vanquish:
>>> animals = ['aardvark', 'anteater', 'antelope', 'albert']
>>> animals
['aardvark', 'anteater', 'antelope', 'albert']
The list value in animals contains four values. Listing values begin with a left square bracket, [, and end with a right square bracket, ]. This is like how strings begin and end in quotation marks.
Commas separate the private values within of a listing. These values are also called items. Each detail in HANGMAN_PICS is a multiline cord.
Lists allow you lot shop several values without using a variable for each one. Without lists, the code would look like this:
>>> animals1 = 'aardvark'
>>> animals2 = 'anteater'
>>> animals3 = 'antelope'
>>> animals4 = 'albert'
This code would exist hard to manage if yous had hundreds or thousands of strings. But a list tin can easily contain any number of values.
Accessing Items with Indexes
You can access an item inside a list past calculation foursquare brackets to the end of the list variable with a number between them. The number betwixt the foursquare brackets is the index. In Python, the index of the first item in a list is 0. The second item is at index 1, the third item is at index 2, and and so on. Considering the indexes begin at 0 and not 1, we say that Python lists are zero indexed.
While we're still in the interactive beat and working with the animals listing, enter animals[0] , animals[1] , animals[2] , and animals[3] to encounter how they evaluate:
>>> animals[0]
'aardvark'
>>> animals[1]
'anteater'
>>> animals[two]
'antelope'
>>> animals[iii]
'albert'
Notice that the first value in the listing, 'aardvark', is stored in alphabetize 0 and not index ane. Each item in the list is numbered in order starting from 0.
Using the square brackets, you can treat items in the listing only like whatever other value. For example, enter animals[0] + animals[ii] into the interactive shell:
>>> animals[0] + animals[2]
'aardvarkantelope'
Both variables at indexes 0 and 2 of animals are strings, so the values are concatenated. The evaluation looks like this:
Out-of-Range Indexes and IndexError
If you try accessing an index that is as well high to exist in the list, you lot'll become an IndexError that will crash your program. To run into an example of this error, enter the following into the interactive shell:
>>> animals = ['aardvark', 'anteater', 'antelope', 'albert']
>>> animals[9999]
Traceback (most contempo call last):
File "", line i, in
animals[9999]
IndexError: list index out of range
Because at that place is no value at index 9999, yous get an fault.
Changing Listing Items with Alphabetize Consignment
You can too change the value of an item in a list using alphabetize assignment. Enter the following into the interactive shell:
>>> animals = ['aardvark', 'anteater', 'antelope', 'albert']
>>> animals[one] = 'ANTEATER'
>>> animals
['aardvark', 'ANTEATER', 'antelope', 'albert']
The new 'ANTEATER' cord overwrites the 2d detail in the animals listing. Then typing animals[1] by itself evaluates to the list'south current 2d item, but using it on the left side of an assignment operator assigns a new value to the list's 2d item.
List Concatenation
You can join several lists into one list using the + operator, just as you can with strings. Doing so is called list concatenation. To encounter this in activeness, enter the following into the interactive beat:
>>> [ane, two, iii, 4] + ['apples', 'oranges'] + ['Alice', 'Bob']
[1, ii, 3, 4, 'apples', 'oranges', 'Alice', 'Bob']
['apples'] + ['oranges'] will evaluate to ['apples', 'oranges']. But ['apples'] + 'oranges' will effect in an fault. You lot can't add a list value and a string value with the + operator. If yous want to add together values to the cease of a list without using list concatenation, use the append() method (described in "The opposite() and append() List Methods" on page 95).
The in Operator
The in operator tin tell you whether a value is in a list or non. Expressions that apply the in operator return a Boolean value: True if the value is in the list and False if it isn't. Enter the following into the interactive shell:
>>> animals = ['aardvark', 'anteater', 'antelope', 'albert']
>>> 'antelope' in animals
Truthful
>>> 'pismire' in animals
False
The expression 'antelope' in animals returns True considering the string 'antelope' is one of the values in the animals listing. It is located at alphabetize 2. But when you enter the expression 'ant' in animals, information technology returns False because the cord 'emmet' doesn't exist in the list.
The in operator likewise works for strings, checking whether one cord exists in some other. Enter the following into the interactive shell:
>>> 'hello' in 'Alice said hello to Bob.'
Truthful
Storing a list of multiline strings in the HANGMAN_PICS variable covered a lot of concepts. For case, you saw that lists are useful for storing multiple values in a single variable. You too learned some techniques for working with lists, such as index assignment and list concatenation. Methods are another new concept yous'll learn how to employ in the Hangman game; we'll explore them next.
Calling Methods
A method is a part attached to a value. To phone call a method, you must adhere it to a specific value using a flow. Python has many useful methods, and we'll use some of them in the Hangman program.
But showtime, allow'due south look at some listing and cord methods.
The opposite() and append() List Methods
The list data type has a couple of methods you'll probably utilise a lot: reverse() and append(). The reverse() method will reverse the club of the items in the list. Attempt inbound spam = [1, 2, 3, 4, 5, 6, 'meow', 'woof'], and and so spam.reverse() to reverse the list. Then enter spam to view the contents of the variable.
>>> spam = [i, ii, three, iv, 5, half-dozen, 'meow', 'woof']
>>> spam.opposite()
>>> spam
['woof', 'meow', 6, v, four, three, 2, i]
The virtually common list method you'll employ is append(). This method will add together the value you lot pass equally an statement to the end of the list. Try entering the following into the interactive shell:
>>> eggs = []
>>> eggs.append('hovercraft')
>>> eggs
['hovercraft']
>>> eggs.append('eels')
>>> eggs
['hovercraft', 'eels']
These methods exercise change the lists they are called on. They don't return a new list. We say that these methods change the list in identify.
The separate() String Method
The string data type has a split() method, which returns a list of strings made from a string that has been split. Try using the split() method by entering the post-obit into the interactive beat:
>>> sentence = input()
My very energetic mother just served united states nachos.
>>> sentence.split()
['My', 'very', 'energetic', 'female parent', 'just', 'served', 'the states', 'nachos.']
The result is a listing of 8 strings, i string for each word in the original string. The splitting occurs wherever at that place is a infinite in the string. The spaces are non included in any of the items in the list.
Line 38 of the Hangman program also uses the split() method, as shown next. The lawmaking is long, just information technology'southward actually just a simple consignment statement that has one long string of words separated by spaces, with a split() method call at the stop. The split() method evaluates to a list with each word in the string equally a single list item.
38. words = 'pismire baboon badger bat carry beaver camel cat clam cobra cougar
coyote crow deer dog donkey duck eagle ferret fox frog goat goose hawk
lion cadger llama mole monkey moose mouse mule newt otter owl panda
parrot pigeon python rabbit ram rat raven rhino salmon seal shark sheep
skunk sloth snake spider stork swan tiger toad trout turkey turtle
weasel whale wolf wombat zebra'.separate()
It's easier to write this program using split(). If you created a list to brainstorm with, you lot would take to type ['ant', 'birdie', 'badger', and so on, with quotes and commas for every word.
Y'all can also add together your own words to the string on line 38 or remove whatever you don't want to be in the game. Simply make sure that spaces separate the words.
Getting a Secret Word from the Word Listing
Line 40 defines the getRandomWord() role. A list argument will be passed for its wordList parameter. This function will return a unmarried underground word from the list in wordList.
twoscore. def getRandomWord(wordList):
41. # This function returns a random string from the passed listing of
strings.
42. wordIndex = random.randint(0, len(wordList) - 1)
43. return wordList[wordIndex]
In line 42, we store a random index for this list in the wordIndex variable by calling randint() with ii arguments. The showtime argument is 0 (for the get-go possible index), and the second is the value that the expression len(wordList) - 1 evaluates to (for the last possible alphabetize in a wordList).
Call up that listing indexes starting time at 0, non 1. If you have a list of three items, the alphabetize of the starting time item is 0, the index of the second item is 1, and the index of the tertiary detail is ii. The length of this list is 3, but index 3 would be after the last index. This is why line 42 subtracts 1 from the length of wordList. The code on line 42 will work no affair what the size of wordList is. Now you can add or remove strings in wordList if you similar.
The wordIndex variable will be fix to a random index for the list passed every bit the wordList parameter. Line 43 will return the chemical element in wordList at the integer stored in wordIndex.
Let'due south pretend ['apple tree', 'orange', grape'] was passed as the argument to getRandomWord() and that randint(0, ii) returned the integer ii. That would mean that line 43 would evaluate to return wordList[2], and then evaluate to render 'grape'. This is how getRandomWord() returns a random string in wordList.
So the input to getRandomWord() is a listing of strings, and the return value output is a randomly selected string from that list. In the Hangman game, this is how a cloak-and-dagger discussion is selected for the histrion to estimate.
Displaying the Board to the Player
Next, you need a function to print the Hangman lath on the screen. It should also display how many letters the player has correctly (and incorrectly) guessed.
45. def displayBoard(missedLetters, correctLetters, secretWord):
46. print(HANGMAN_PICS[len(missedLetters)])
47. print()
This code defines a new role named displayBoard(). This function has three parameters:
missedLetters A string of the messages the player has guessed that are not in the secret word
correctLetters A string of the letters the role player has guessed that are in the secret give-and-take
secretWord A string of the surreptitious word that the histrion is trying to guess
The commencement print() part call will display the board. The global variable HANGMAN_PICS has a listing of strings for each possible board. (Remember that global variables can be read from within a function.) HANGMAN_PICS[0] shows an empty gallows, HANGMAN_PICS[1] shows the head (when the player misses ane letter), HANGMAN_PICS[ii] shows the head and trunk (when the player misses ii letters), and then on until HANGMAN_PICS[vi], which shows the full hanging man.
The number of letters in missedLetters will reflect how many incorrect guesses the role player has made. Call len(missedLetters) to discover out this number. Then, if missedLetters is 'aetr', then len('aetr') will return four. Press HANGMAN_PICS[4] will brandish the appropriate hanging man motion-picture show for four misses. This is what HANGMAN_PICS[len(missedLetters)] on line 46 evaluates to.
Line 49 prints the string 'Missed letters:' with a space graphic symbol at the end instead of a newline:
49. print('Missed letters:', end=' ')
50. for alphabetic character in missedLetters:
51. impress(letter of the alphabet, end=' ')
52. impress()
The for loop on line 50 will iterate over each grapheme in the string missedLetters and print it on the screen. Remember that cease=' ' will replace the newline character that is printed after the string with a single space character. For example, if missedLetters were 'ajtw', this for loop would display a j t w.
The rest of the displayBoard() function (lines 54 to 62) displays the missed letters and creates the string of the secret word with all of the non-nevertheless-guessed letters as blanks. It does this using the range() function and list slicing.
The list() and range() Functions
When called with one argument, range() will return a range object of integers from 0 up to (but not including) the argument. This range object is used in for loops only can besides be converted to the more than familiar list information type with the list() function. Enter listing(range(10)) into the interactive shell:
>>> listing(range(x))
[0, 1, ii, 3, iv, 5, vi, seven, 8, 9]
>>> listing('Hello')
['H', 'e', 'l', 'l', 'o']
The list() office is like to the str() or int() functions. It takes the value it'southward passed and returns a list. It's easy to generate huge lists with the range() role. For example, enter list(range(10000)) into the interactive shell:
>>> list(range(10000))
[0, one, 2, 3, iv, 5, 6, seven, 8, 9, 10, xi, 12, 13, fourteen, 15,...
--snip--
...9989, 9990, 9991, 9992, 9993, 9994, 9995, 9996, 9997, 9998, 9999]
The list is and so huge, it won't even fit onto the screen. But you lot can store the list in a variable:
>>> spam = list(range(10000))
If you pass two integer arguments to range(), the range object it returns is from the first integer argument upward to (just not including) the 2nd integer statement. Next enter listing(range(10, 20)) into the interactive vanquish as follows:
>>> list(range(10, 20))
[10, eleven, 12, 13, 14, 15, 16, 17, xviii, xix]
As you lot can see, our listing only goes up to 19 and does not include 20.
Listing and Cord Slicing
Listing slicing creates a new list value using a subset of another list's items. To slice a listing, specify two indexes (the beginning and cease) with a colon in the square brackets afterwards the list name. For example, enter the following into the interactive shell:
>>> spam = ['apples', 'bananas', 'carrots', 'dates']
>>> spam[1:3]
['bananas', 'carrots']
The expression spam[ane:3] evaluates to a list with items in spam from alphabetize 1 upwardly to (but not including) index iii.
If you leave out the commencement index, Python will automatically think you want alphabetize 0 for the get-go index:
>>> spam = ['apples', 'bananas', 'carrots', 'dates']
>>> spam[:ii]
['apples', 'bananas']
If yous leave out the second index, Python will automatically retrieve y'all want the rest of the list:
>>> spam = ['apples', 'bananas', 'carrots', 'dates']
>>> spam[2:]
['carrots', 'dates']
You tin besides use slices with strings in the aforementioned style you use them with lists. Each character in the string is similar an item in the list. Enter the following into the interactive shell:
>>> myName = 'Zophie the Fatty Cat'
>>> myName[four:12]
'ie the F'
>>> myName[:10]
'Zophie the'
>>> myName[7:]
'the Fatty Cat'
The next part of the Hangman lawmaking uses slicing.
Displaying the Secret Give-and-take with Blanks
Now y'all want to print the hole-and-corner word, but with blank lines for the letters that haven't been guessed. You can use the underscore character (_) for this. First create a string with nothing but ane underscore for each letter in the surreptitious word. Then replace the blanks for each letter in correctLetters.
Then if the secret word were 'otter', then the blanked-out string would be '_____' (five underscores). If correctLetters were the string 'rt', yous would alter the string to '_tt_r'. Lines 54 to 58 are the part of the code that does that:
54. blanks = '_' * len(secretWord)
55.
56. for i in range(len(secretWord)): # Supercede blanks with correctly
guessed messages.
57. if secretWord[i] in correctLetters:
58. blanks = blanks[:i] + secretWord[i] + blanks[i+1:]
Line 54 creates the blanks variable full of underscores using string replication. Remember that the * operator can be used on a cord and an integer, so the expression '_' * v evaluates to '_____'. This volition ensure that blanks has the same number of underscores equally secretWord has messages.
Line 56 has a for loop that goes through each letter in secretWord and replaces the underscore with the actual letter if it exists in correctLetters.
Let's take another look at the previous example, where the value of secretWord is 'otter' and the value in correctLetters is 'tr'. You would want the cord '_tt_r' displayed to the histrion. Allow's effigy out how to create this string.
Line 56'south len(secretWord) call would return 5. The range(len(secretWord)) call becomes range(5), which makes the for loop iterate over 0, i, ii, 3, and four.
Because the value of i will take on each value in [0, 1, 2, 3, iv], the code in the for loop looks like this:
if secretWord[0] in correctLetters:
blanks = blanks[:0] + secretWord[0] + blanks[1:]
if secretWord[1] in correctLetters:
blanks = blanks[:i] + secretWord[1] + blanks[2:]
--snip--
Nosotros're showing only the first ii iterations of the for loop, simply starting with 0, i will have the value of each number in the range. In the first iteration, i takes the value 0, so the if statement checks whether the letter in secretWord at index 0 is in correctLetters. The loop does this for every letter in the secretWord, one letter at a time.
If you are dislocated about the value of something similar secretWord[0] or blanks[3:], wait at Figure 8-1. It shows the value of the secretWord and blanks variables and the index for each letter in the string.
Figure 8-one: The indexes of the blanks and secretWord strings
If you supercede the listing slices and the list indexes with the values they represent, the loop code looks like this:
if 'o' in 'tr': # Imitation
blanks = '' + 'o' + '____' # This line is skipped.
--snip--
if 'r' in 'tr': # True
blanks = '_tt_' + 'r' + '' # This line is executed.
# blanks now has the value '_tt_r'.
The preceding code examples all practise the aforementioned thing when secretWord is 'otter' and correctLetters is 'tr'. The next few lines of code impress the new value of blanks with spaces between each letter:
sixty. for alphabetic character in blanks: # Testify the secret word with spaces in betwixt
each letter of the alphabet.
61. impress(letter, end=' ')
62. print()
Find that the for loop on line 60 doesn't call the range() function. Instead of iterating on the range object this office call would return, information technology iterates on the string value in the blanks variable. On each iteration, the letter variable takes on a new graphic symbol from the 'otter' cord in blanks.
The printed output afterwards the spaces are added would be '_ t t _ r'.
Getting the Player's Guess
The getGuess() function will be called so that the histrion can enter a alphabetic character to judge. The function returns the letter the player guessed as a string. Further, getGuess() will brand certain that the player types a valid alphabetic character earlier it returns from the function.
64. def getGuess(alreadyGuessed):
65. # Returns the letter of the alphabet the player entered. This function makes certain the
histrion entered a unmarried letter of the alphabet and non something else.
A cord of the letters the player has guessed is passed every bit the argument for the alreadyGuessed parameter. Then the getGuess() role asks the actor to guess a single letter of the alphabet. This unmarried letter volition be getGuess()'s render value. Now, because Python is case sensitive, we need to make sure the player's approximate is a lowercase alphabetic character so we tin check it against the clandestine word. That's where the lower() method comes in.
The lower() and upper() String Methods
Enter 'Hello world!'.lower() into the interactive shell to meet an example of the lower() method:
>>> 'Hello earth!'.lower()
'hi world!'
The lower() method returns a string with all the characters in lowercase. There is also an upper() method for strings, which returns a string with all the characters in majuscule. Try it out by entering 'How-do-you-do world!'.upper() into the interactive shell:
>>> 'Hullo globe!'.upper()
'Howdy WORLD!'
Because the upper() method returns a string, you can also telephone call a method on that string.
Now enter this into the interactive shell:
>>> 'Hello world!'.upper().lower()
'hello world!'
'Hello world!'.upper() evaluates to the string 'HELLO WORLD!', and then the string's lower() method is chosen. This returns the cord 'hello world!', which is the final value in the evaluation:
The order is important. 'Hi globe!'.lower().upper() isn't the same as 'Hullo world!'.upper().lower():
>>> 'Hello earth!'.lower().upper()
'HELLO Globe!'
That evaluation looks like this:
If a string is stored in a variable, you can besides call a string method on that variable:
>>> spam = 'Hello world!'
>>> spam.upper()
'HELLO WORLD!'
This lawmaking does not change the value in spam. The spam variable will notwithstanding comprise 'Hello world!'.
Going back to the Hangman program, we apply lower() when nosotros enquire for the actor's guess:
66. while True:
67. print('Guess a letter.')
68. estimate = input()
69. guess = guess.lower()
Now, fifty-fifty if the player enters an uppercase alphabetic character every bit a judge, the getGuess() role volition render a lowercase letter.
Leaving the while Loop
Line 66's while loop will proceed asking the player for a letter until they enter a single letter that hasn't been guessed previously.
The condition for the while loop is simply the Boolean value True. That ways the only manner the execution will ever leave this loop is by executing a interruption statement, which leaves the loop, or a return statement, which leaves non just the loop but the entire function.
The lawmaking inside the loop asks the player to enter a letter of the alphabet, which is stored in the variable guess. If the thespian entered an uppercase letter, information technology would be overwritten with a lowercase letter on line 69.
elif Statements
The next part of the Hangman programme uses elif statements. You can remember of elif or "else-if" statements every bit saying, "If this is true, do this. Or else if this side by side condition is truthful, do that. Or else if none of them is true, exercise this final thing." Take a look at the following code:
if catName == 'Fuzzball':
print('Your cat is fuzzy.')
elif catName == 'Spots':
print('Your cat is spotted.')
else:
print('Your true cat is not fuzzy or spotted.')
If the catName variable is equal to the string 'Fuzzball', then the if statement's condition is True and the if cake tells the user that their cat is fuzzy. Still, if this condition is Simulated, then Python tries the elif statement'southward condition next. If catName is 'Spots', and then the cord 'Your cat is spotted.' is printed to the screen. If both are False, then the lawmaking tells the user their cat isn't fuzzy or spotted.
You can take equally many elif statements as you desire:
if catName == 'Fuzzball':
print('Your cat is fuzzy.')
elif catName == 'Spots':
impress('Your cat is spotted.')
elif catName == 'Chubs':
print('Your cat is chubby.')
elif catName == 'Puff':
print('Your cat is puffy.')
else:
impress('Your cat is neither fuzzy nor spotted nor stubby nor puffy.')
When one of the elif conditions is Truthful, its code is executed, and then the execution jumps to the first line past the else block. And so one, and just one, of the blocks in the if-elif-else statements volition be executed. You can also leave off the else cake if you don't need one and but accept if-elif statements.
Making Sure the Player Entered a Valid Judge
The guess variable contains the player's letter of the alphabet gauge. The program needs to make sure they entered a valid guess: one, and only one, letter of the alphabet that has not yet been guessed. If they didn't, the execution volition loop back and ask them for a letter once more.
lxx. if len(estimate) != one:
71. print('Please enter a single letter.')
72. elif guess in alreadyGuessed:
73. print('You accept already guessed that alphabetic character. Choose again.')
74. elif approximate not in 'abcdefghijklmnopqrstuvwxyz':
75. print('Please enter a LETTER.')
76. else:
77. render judge
Line 70'southward condition checks whether guess is not one character long, line 72'due south condition checks whether guess already exists inside the alreadyGuessed variable, and line 74'due south condition checks whether estimate is not a letter in the standard English alphabet. If any of these weather condition are Truthful, the game prompts the histrion to enter a new estimate.
If all of these weather condition are Simulated, and then the else statement'south block executes, and getGuess() returns the value in estimate on line 77.
Retrieve, only one of the blocks in an if-elif-else statement will be executed.
Asking the Player to Play Again
The playAgain() function has merely a print() part telephone call and a return statement:
79. def playAgain():
80. # This function returns True if the actor wants to play again;
otherwise, information technology returns Simulated.
81. print('Do you want to play again? (yeah or no)')
82. return input().lower().startswith('y')
The render statement has an expression that looks complicated, but yous tin can suspension it down. Here's a footstep-by-pace look at how Python evaluates this expression if the user enters YES:
The bespeak of the playAgain() role is to let the player enter yeah or no to tell the program if they want to play another round of Hangman. The player should be able to blazon YES, yep, Y, or anything else that begins with a y in order to mean "yes." If the player enters YES, then the return value of input() is the cord 'YES'. And 'Yes'.lower() returns the lowercase version of the fastened string. Then the return value of 'YES'.lower() is 'yes'.
But in that location'southward the second method call, startswith('y'). This function returns True if the associated string begins with the string parameter between the parentheses and False if it doesn't. The render value of 'yep'.startswith('y') is True.
That's it—you evaluated this expression! Information technology lets the player enter a response, sets the response in lowercase, checks whether it begins with the letter y, and then returns True if information technology does and Simulated if it doesn't.
On a side note, in that location'southward also an endswith(someString) cord method that volition return True if the string ends with the cord in someString and Fake if it doesn't. endswith() is sort of like the opposite of startswith().
Review of the Hangman Functions
That's all the functions we're creating for this game! Permit'due south review them:
getRandomWord(wordList) Takes a list of strings passed to it and returns one string from information technology. That is how a word is chosen for the player to guess.
displayBoard(missedLetters, correctLetters, secretWord) Shows the electric current state of the lath, including how much of the secret discussion the thespian has guessed then far and the incorrect messages the player has guessed. This role needs three parameters passed to information technology to piece of work correctly. correctLetters and missedLetters are strings made up of the messages that the player has guessed that are in and not in the clandestine word, respectively. And secretWord is the secret discussion the histrion is trying to guess. This function has no return value.
getGuess(alreadyGuessed) Takes a cord of letters the player has already guessed and will keep asking the player for a letter that isn't in alreadyGuessed. This office returns the cord of the valid letter the role player guessed.
playAgain() Asks if the player wants to play another round of Hangman. This function returns Truthful if the player does, Simulated if they don't.
After the functions, the code for the principal part of the plan begins at line 85. Everything upward to this bespeak has been only function definitions and a large consignment statement for HANGMAN_PICS.
The Game Loop
The master function of the Hangman program displays the name of the game, sets upward some variables, and executes a while loop. This department walks through the rest of the program step past step.
85. impress('H A N Grand Grand A Northward')
86. missedLetters = ''
87. correctLetters = ''
88. secretWord = getRandomWord(words)
89. gameIsDone = Imitation
Line 85 is the offset print() call that executes when the game is run. It displays the title of the game. Next, blank strings are assigned to the variables missedLetters and correctLetters since the player hasn't guessed any missed or correct letters still.
The getRandomWord(words) phone call at line 88 will evaluate to a randomly selected word from the words list.
Line 89 sets gameIsDone to False. The code will set gameIsDone to True when it wants to bespeak that the game is over and ask the role player whether they desire to play again.
Calling the displayBoard() Part
The remainder of the program consists of a while loop. The loop'southward condition is e'er True, which means information technology will loop forever until it encounters a break argument. (This happens later on line 126.)
91. while True:
92. displayBoard(missedLetters, correctLetters, secretWord)
Line 92 calls the displayBoard() function, passing information technology the three variables set on lines 86, 87, and 88. Based on how many letters the player has correctly guessed and missed, this function displays the appropriate Hangman board to the actor.
Letting the Player Enter Their Judge
Next the getGuess() function is called so the histrion can enter their guess.
94. # Let the actor enter a letter of the alphabet.
95. gauge = getGuess(missedLetters + correctLetters)
The getGuess() function requires an alreadyGuessed parameter then it tin can cheque whether the player enters a letter they've already guessed. Line 95 concatenates the strings in the missedLetters and correctLetters variables and passes the consequence as the argument for the alreadyGuessed parameter.
Checking Whether the Letter Is in the Hole-and-corner Word
If the guess string exists in secretWord, then this code concatenates guess to the end of the correctLetters string:
97. if guess in secretWord:
98. correctLetters = correctLetters + guess
This cord will be the new value of correctLetters.
Checking Whether the Thespian Won
How does the program know whether the player has guessed every letter in the underground word? Well, correctLetters has each letter that the actor correctly guessed, and secretWord is the secret word itself. But you can't simply check whether correctLetters == secretWord. If secretWord were the string 'otter' and correctLetters were the cord 'orte', then correctLetters == secretWord would exist Faux even though the player has guessed each letter in the hush-hush discussion.
The just fashion you lot tin be certain the player has won is to iterate over each alphabetic character in secretWord and see if it exists in correctLetters. If, and only if, every letter of the alphabet in secretWord exists in correctLetters has the player won.
100. # Check if the player has won.
101. foundAllLetters = Truthful
102. for i in range(len(secretWord)):
103. if secretWord[i] not in correctLetters:
104. foundAllLetters = False
105. interruption
If you lot find a letter of the alphabet in secretWord that doesn't exist in correctLetters, you lot know that the player has not guessed all the letters. The new variable foundAllLetters is prepare to True on line 101 before the loop begins. The loop starts out assuming that all the messages in the hugger-mugger word have been found. But the loop'southward code on line 104 will change foundAllLetters to Fake the first fourth dimension information technology finds a letter in secretWord that isn't in correctLetters.
If all the messages in the hole-and-corner word have been establish, the player is told they have won, and gameIsDone is set to Truthful:
106. if foundAllLetters:
107. print('Yes! The surreptitious word is "' + secretWord +
'"! You have won!')
108. gameIsDone = Truthful
Handling an Incorrect Guess
Line 109 is the offset of the else cake.
109. else:
110. missedLetters = missedLetters + judge
Remember, the lawmaking in this block will execute if the condition was False. Just which condition? To find out, indicate your finger at the start of the else keyword and movement information technology straight upward. Y'all'll see that the else keyword's indentation is the same as the if keyword's indentation on line 97:
97. if guess in secretWord:
--snip--
109. else:
110. missedLetters = missedLetters + approximate
So if the condition on line 97 (guess in secretWord) were False, then the execution would motility into this else block.
Wrongly guessed letters are concatenated to the missedLetters string on line 110. This is like what line 98 did for letters the player guessed correctly.
Checking Whether the Player Lost
Each time the player guesses incorrectly, the lawmaking concatenates the wrong letter to the string in missedLetters. So the length of missedLetters—or, in code, len(missedLetters)—is too the number of wrong guesses.
112. # Cheque if player has guessed besides many times and lost.
113. if len(missedLetters) == len(HANGMAN_PICS) - one:
114. displayBoard(missedLetters, correctLetters, secretWord)
115. print('You have run out of guesses!\nAfter ' +
str(len(missedLetters)) + ' missed guesses and ' +
str(len(correctLetters)) + ' correct guesses,
the give-and-take was "' + secretWord + '"')
116. gameIsDone = True
The HANGMAN_PICS list has 7 ASCII art strings. So when the length of the missedLetters string is equal to len(HANGMAN_PICS) - 1 (that is, vi), the player has run out of guesses. You know the player has lost considering the hanging man pic will be finished. Remember, HANGMAN_PICS[0] is the start item in the list, and HANGMAN_PICS[6] is the last one.
Line 115 prints the clandestine word, and line 116 sets the gameIsDone variable to Truthful.
118. # Ask the player if they want to play again (but but if the game is
done).
119. if gameIsDone:
120. if playAgain():
121. missedLetters = ''
122. correctLetters = ''
123. gameIsDone = Simulated
124. secretWord = getRandomWord(words)
Ending or Resetting the Game
Whether the thespian won or lost after guessing their alphabetic character, the game should ask the player if they want to play over again. The playAgain() role handles getting a yes or no from the actor, so it is chosen on line 120.
If the player does want to play again, the values in missedLetters and correctLetters must be reset to blank strings, gameIsDone reset to False, and a new cloak-and-dagger discussion stored in secretWord. This way, when the execution loops dorsum to the get-go of the while loop on line 91, the board will be reset to a fresh game.
If the actor didn't enter something that began with y when asked whether they wanted to play again, so line 120'south condition would be Fake, and the else cake would execute:
125. else:
126. pause
The break argument causes the execution to jump to the first instruction afterward the loop. But because in that location are no more instructions later on the loop, the program terminates.
Summary
Hangman has been our near advanced game yet, and y'all've learned several new concepts while making it. As your games get more and more than complex, it's a practiced idea to sketch out a flowchart of what should happen in your program.
Lists are values that can contain other values. Methods are functions attached to a value. Lists have an append() method. Strings accept lower(), upper(), carve up(), startswith(), and endswith() methods. Y'all'll learn about many more information types and methods in the balance of this book.
The elif statement lets you lot add together an "or else-if" clause to the middle of your if-else statements.
Source: https://inventwithpython.com/invent4thed/chapter8.html
0 Response to "Hangman Game C++ That Plays Again"
Post a Comment