-
Notifications
You must be signed in to change notification settings - Fork 11
/
chapter9.html
1610 lines (1228 loc) · 117 KB
/
chapter9.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-5459430-3");
pageTracker._trackPageview();
} catch(err) {}</script>
<meta http-equiv="Content-Type" content="text/html;charset=us-ascii" />
<title>IYOCGwP, Chapter 9 - Hangman</title>
<link rel="stylesheet" href="inventbook.css" type="text/css" media="all" />
</head>
<body class='chapter9body'>
<table border='0' width='100%'><tr><td><a href='chapter8.html'>Go to Chapter 8 - Flow Charts</a></td><td align='right'><a href='chapter10.html'>Go to Chapter 10 - Tic Tac Toe</a></td></tr></table>
<div style='height: 310px;'><a href='http://www.amazon.com/Invent-Your-Computer-Games-Python/dp/0982106017/'><img src='images/buyad.png' align='right'></a></div>
<div style='height: 350px;'><img src='images/chap9.png'></div>
<div class='inthischapter'><h3 id="TopicsCoveredInThisChapter">Topics Covered In This Chapter:</h3>
<ul>
<li>Methods</li>
<li>The <span class='m'>append()</span> list method</li>
<li>The <span class='m'>lower()</span> and <span class='m'>upper()</span> string methods</li>
<li>The <span class='m'>reverse()</span> list method</li>
<li>The <span class='m'>split()</span> string method</li>
<li>The <span class='m'>range()</span> function</li>
<li>The <span class='m'>list()</span> function</li>
<li><span class='m'>for</span> loops</li>
<li>elif statements</li>
<li>The <span class='m'>startswith()</span> and <span class='m'>endswith()</span> string methods.</li>
<li>The dictionary data type.</li>
<li>key-value pairs</li>
<li>The <span class='m'>keys()</span> and <span class='m'>values()</span> dictionary methods</li>
<li>Multiple variable assignment, such as a, b, c = [1, 2, 3]</li>
</ul></div>
<p>This game introduces many new concepts. But don't worry; we'll experiment with these programming concepts in the interactive shell first. Some data types such as strings and lists have functions that are associated with their values called methods. We will learn several different methods that can manipulate strings and lists for us. We will also learn about a new type of loop called a <span class='m'>for</span> loop and a new type of data type called a dictionary. Once you understand these concepts, it will be much easier to understand the game in this chapter: Hangman.</p>
<p>You can learn more from Wikipedia: <a href='http://en.wikipedia.org/wiki/Hangman_(game)'>http://en.wikipedia.org/wiki/Hangman_(game)</a></p>
<h2 id="HangmansSourceCode">Hangman's Source Code</h2>
<p>This chapter's game is a bit longer than our previous games. You can either type in the code below directly into the file editor (which I recommend) or you can obtain the code from this book's website. To grab the code from the web, in a web browser go to the URL <a href='http://inventwithpython.com/chapter9'>http://inventwithpython.com/chapter9</a> and follow the instructions for downloading the source code.</p>
<div class='sourcecode'><span class='sourcecodeHeader'>hangman.py</span><br /><span class='sourcecodeSubHeader'>This code can be downloaded from <a href='http://inventwithpython.com/hangman.py'>http://inventwithpython.com/hangman.py</a><br />If you get errors after typing this code in, compare it to the book's code with the online diff tool at <a href='http://inventwithpython.com/diff'>http://inventwithpython.com/diff</a> or email the author at <a href="mailto:[email protected]">[email protected]</a></span><br /><ol start='1'>
<li>import random</li>
<li>HANGMANPICS = ['''</li>
<li></li>
<li> +---+</li>
<li> | |</li>
<li> |</li>
<li> |</li>
<li> |</li>
<li> |</li>
<li>=========''', '''</li>
<li></li>
<li> +---+</li>
<li> | |</li>
<li> O |</li>
<li> |</li>
<li> |</li>
<li> |</li>
<li>=========''', '''</li>
<li></li>
<li> +---+</li>
<li> | |</li>
<li> O |</li>
<li> | |</li>
<li> |</li>
<li> |</li>
<li>=========''', '''</li>
<li></li>
<li> +---+</li>
<li> | |</li>
<li> O |</li>
<li> /| |</li>
<li> |</li>
<li> |</li>
<li>=========''', '''</li>
<li></li>
<li> +---+</li>
<li> | |</li>
<li> O |</li>
<li> /|\ |</li>
<li> |</li>
<li> |</li>
<li>=========''', '''</li>
<li></li>
<li> +---+</li>
<li> | |</li>
<li> O |</li>
<li> /|\ |</li>
<li> / |</li>
<li> |</li>
<li>=========''', '''</li>
<li></li>
<li> +---+</li>
<li> | |</li>
<li> O |</li>
<li> /|\ |</li>
<li> / \ |</li>
<li> |</li>
<li>=========''']</li>
<li>words = 'ant baboon badger bat bear beaver camel cat clam cobra cougar coyote crow deer dog donkey duck eagle ferret fox frog goat goose hawk 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'.split()</li>
<li></li>
<li>def getRandomWord(wordList):</li>
<li> # This function returns a random string from the passed list of strings.</li>
<li> wordIndex = random.randint(0, len(wordList) - 1)</li>
<li> return wordList[wordIndex]</li>
<li></li>
<li>def displayBoard(HANGMANPICS, missedLetters, correctLetters, secretWord):</li>
<li> print(HANGMANPICS[len(missedLetters)])</li>
<li> print()</li>
<li></li>
<li> print('Missed letters:', end=' ')</li>
<li> for letter in missedLetters:</li>
<li> print(letter, end=' ')</li>
<li> print()</li>
<li></li>
<li> blanks = '_' * len(secretWord)</li>
<li></li>
<li> for i in range(len(secretWord)): # replace blanks with correctly guessed letters</li>
<li> if secretWord[i] in correctLetters:</li>
<li> blanks = blanks[:i] + secretWord[i] + blanks[i+1:]</li>
<li></li>
<li> for letter in blanks: # show the secret word with spaces in between each letter</li>
<li> print(letter, end=' ')</li>
<li> print()</li>
<li></li>
<li>def getGuess(alreadyGuessed):</li>
<li> # Returns the letter the player entered. This function makes sure the player entered a single letter, and not something else.</li>
<li> while True:</li>
<li> print('Guess a letter.')</li>
<li> guess = input()</li>
<li> guess = guess.lower()</li>
<li> if len(guess) != 1:</li>
<li> print('Please enter a single letter.')</li>
<li> elif guess in alreadyGuessed:</li>
<li> print('You have already guessed that letter. Choose again.')</li>
<li> elif guess not in 'abcdefghijklmnopqrstuvwxyz':</li>
<li> print('Please enter a LETTER.')</li>
<li> else:</li>
<li> return guess</li>
<li></li>
<li>def playAgain():</li>
<li> # This function returns True if the player wants to play again, otherwise it returns False.</li>
<li> print('Do you want to play again? (yes or no)')</li>
<li> return input().lower().startswith('y')</li>
<li></li>
<li></li>
<li>print('H A N G M A N')</li>
<li>missedLetters = ''</li>
<li>correctLetters = ''</li>
<li>secretWord = getRandomWord(words)</li>
<li>gameIsDone = False</li>
<li></li>
<li>while True:</li>
<li> displayBoard(HANGMANPICS, missedLetters, correctLetters, secretWord)</li>
<li></li>
<li> # Let the player type in a letter.</li>
<li> guess = getGuess(missedLetters + correctLetters)</li>
<li></li>
<li> if guess in secretWord:</li>
<li> correctLetters = correctLetters + guess</li>
<li></li>
<li> # Check if the player has won</li>
<li> foundAllLetters = True</li>
<li> for i in range(len(secretWord)):</li>
<li> if secretWord[i] not in correctLetters:</li>
<li> foundAllLetters = False</li>
<li> break</li>
<li> if foundAllLetters:</li>
<li> print('Yes! The secret word is "' + secretWord + '"! You have won!')</li>
<li> gameIsDone = True</li>
<li> else:</li>
<li> missedLetters = missedLetters + guess</li>
<li></li>
<li> # Check if player has guessed too many times and lost</li>
<li> if len(missedLetters) == len(HANGMANPICS) - 1:</li>
<li> displayBoard(HANGMANPICS, missedLetters, correctLetters, secretWord)</li>
<li> print('You have run out of guesses!\nAfter ' + str(len(missedLetters)) + ' missed guesses and ' + str(len(correctLetters)) + ' correct guesses, the word was "' + secretWord + '"')</li>
<li> gameIsDone = True</li>
<li></li>
<li> # Ask the player if they want to play again (but only if the game is done).</li>
<li> if gameIsDone:</li>
<li> if playAgain():</li>
<li> missedLetters = ''</li>
<li> correctLetters = ''</li>
<li> gameIsDone = False</li>
<li> secretWord = getRandomWord(words)</li>
<li> else:</li>
<li> break</li>
</ol></div>
<!--
<p>After typing in the source code (don't forget to save!) you can run this game by pressing F5. If any errors come up, be sure you typed the source code in <i>exactly</i> as it appears here. Remember that the indentation is important, and that lines will have zero, four, eight, or even twelve spaces in front of them.</p>
-->
<h2 id="HowtheCodeWorks">How the Code Works</h2>
<blockquote class='sourcecode'>
<ol start=1>
<li>import random</li>
</ol>
</blockquote>
<p>The Hangman program is going to randomly select a secret word from a list of secret words. This means we will need the <span class='m'>random</span> module imported.</p>
<blockquote class='sourcecode'>
<ol start=2>
<li>HANGMANPICS = ['''</li>
<li></li>
<li> +---+</li>
<li> | |</li>
<li> |</li>
<li> |</li>
<li> |</li>
<li> |</li>
<li>=========''', '''</li>
</ol>
<p><i>...the rest of the code is too big to show here...</i></p>
</blockquote>
<p>This "line" of code is a simple variable assignment, but it actually stretches over several real lines in the source code. The actual "line" doesn't end until line 58. To help you understand what this code means, you should learn about multi-line strings and lists:</p>
<h2 id="MultilineStrings">Multi-line Strings</h2>
<p>Ordinarily when you write strings in your source code, the string has to be on one line. However, if you use three single-quotes instead of one single-quote to begin and end the string, the string can be on several lines:</p>
<div class='sourceblurb'>
>>> fizz = '''Dear Alice,<br />
I will return home at the end of the month. I will see you then.<br />
Your friend,<br />
Bob'''<br />
>>> print(fizz)<br />
Dear Alice,<br />
I will return home at the end of the month. I will see you then.<br />
Your friend,<br />
Bob<br />
>>>
</div>
<p>If we didn't have multi-line strings, we would have to use the <span class='m'>\n</span> escape character to represent the new lines. But that can make the string hard to read in the source code, like in this example:</p>
<div class='sourceblurb'>
>>> fizz = 'Dear Alice,\nI will return home at the end of the month. I will see you then.\nYour friend,\nBob'<br />
>>> print(fizz)<br />
Dear Alice,<br />
I will return home at the end of the month. I will see you then.<br />
Your friend,<br />
Bob<br />
>>>
</div>
<p>Multi-line strings do not have to keep the same indentation to remain in the same block. Within the multi-line string, Python ignores the indentation rules it normally has for where blocks end.
<blockquote class='sourceblurb'>def writeLetter():<br/>
# inside the def-block<br/>
print('''Dear Alice,<br/>
How are you? Write back to me soon.<br/>
<br/>
Sincerely,</br>
Bob''') # end of the multi-line string and print() call<br/>
print('P.S. I miss you.') # still inside the def-block<br/>
</br>
writeLetter() # This is the first line outside the def-block.<br/></blockquote>
<h2 id="ConstantVariables">Constant Variables</h2>
<p>You may have noticed that <span class='m'>HANGMANPICS</span>'s name is in all capitals. This is the programming convention for constant variables. <span class='term'>Constants</span> are variables whose values do not change throughout the program. Although we can change <span class='m'>HANGMANPICS</span> just like any other variable, the all-caps reminds the programmer to not write code that does so.</p>
<p>Constant variables are helpful for providing descriptions for values that have a special meaning. Since the multi-string value never changes, there is no reason we couldn't copy this multi-line string each time we needed that value. The <span class='m'>HANGMANPICS</span> variable never varies. But it is much shorter to type <span class='m'>HANGMANPICS</span> than it is to type that large multi-line string.</p>
<p>Also, there are cases where typing the value by itself may not be obvious. If we set a variable <span class='m'>eggs = 72</span>, we may forget why we were setting that variable to the integer <span class='m'>72</span>. But if we define a constant variable <span class='m'>DOZEN = 12</span>, then we could set <span class='m'>eggs = DOZEN * 6</span> and by just looking at the code know that the <span class='m'>eggs</span> variable was set to six dozen.</p>
<p>Like all conventions, we don't <i>have</i> to use constant variables, or even put the names of constant variables in all capitals. But doing it this way makes it easier for other programmers to understand how these variables are used. (It even can help you if you are looking at code you wrote a long time ago.)</p>
<h2 id="Lists">Lists</h2>
<p>I will now tell you about a new data type called a <span class='term'>list</span>. A list value can contain several other values in it. Try typing this into the shell: <span class='m'>['apples', 'oranges', 'HELLO WORLD']</span>. This is a list value that contains three string values. Just like any other value, you can store this list in a variable. Try typing <span class='m'>spam = ['apples', 'oranges', 'HELLO WORLD']</span>, and then type <span class='m'>spam</span> to view the contents of <span class='m'>spam</span>.</p>
<div class='sourceblurb'>
>>> spam = ['apples', 'oranges', 'HELLO WORLD']<br />
>>> spam<br />
['apples', 'oranges', 'HELLO WORLD']<br />
>>>
</div>
<p>Lists are a good way to store several different values into one variable. The individual values inside of a list are also called <span class='term'>items</span>. Try typing: <span class='m'>animals = ['aardvark', 'anteater', 'antelope', 'albert']</span> to store various strings into the variable <span class='m'>animals</span>. The square brackets can also be used to get an item from a list. Try typing <span class='m'>animals[0]</span>, or <span class='m'>animals[1]</span>, or <span class='m'>animals[2]</span>, or <span class='m'>animals[3]</span> into the shell to see what they evaluate to.</p>
<div class='sourceblurb'>
>>> animals = ['aardvark', 'anteater', 'antelope', 'albert']<br />
>>> animals[0]<br />
'aardvark'<br />
>>> animals[1]<br />
'anteater'<br />
>>> animals[2]<br />
'antelope'<br />
>>> animals[3]<br />
'albert'<br />
>>>
</div>
<p>The number between the square brackets is the <span class='term'>index</span>. In Python, the first index is the number 0 instead of the number 1. So the first item in the list is at index 0, the second item is at index 1, the third item is at index 2, and so on. Lists are very good when we have to store lots and lots of values, but we don't want variables for each one. Otherwise we would have something like this:</p>
<div class='sourceblurb'>
>>> animals1 = 'aardvark'<br />
>>> animals2 = 'anteater'<br />
>>> animals3 = 'antelope'<br />
>>> animals4 = 'albert'<br />
>>>
</div>
<p>This makes working with all the strings as a group very hard, especially if you have hundreds or thousands (or even millions) of different strings that you want stored in a list. Using the square brackets, you can treat items in the list just like any other value. Try typing <span class='m'>animals[0] + animals[2]</span> into the shell:</p>
<div class='sourceblurb'>
>>> animals[0] + animals[2]<br />
'aardvarkantelope'<br />
>>>
</div>
<p>Because <span class='m'>animals[0]</span> evaluates to the string <span class='m'>'aardvark'</span> and <span class='m'>animals[2]</span> evaluates to the string <span class='m'>'antelope'</span>, then the expression <span class='m'>animals[0] + animals[2]</span> is the same as <span class='m'>'aardvark' + 'antelope'</span>. This string concatenation evaluates to <span class='m'>'aardvarkantelope'</span>.
<p>What happens if we enter an index that is larger than the list's largest index? Try typing <span class='m'>animals[4]</span> or <span class='m'>animals[99]</span> into the shell:</p>
<div class='sourceblurb'>
>>> animals = ['aardvark', 'anteater', 'antelope', 'albert']<br />
>>> animals[4]<br />
Traceback (most recent call last):<br />
File "<pushell#66>", line 1, in <module><br />
animals[4]<br />
IndexError: list index out of range<br />
>>> animals[99]<br />
Traceback (most recent call last):<br />
File "<pushell#67>", line 1, in <module><br />
animals[99]<br />
IndexError: list index out of range<br />
>>>
</div>
<p>If you try accessing an index that is too large, you will get an <span class='term'>index error</span>.</p>
<h2 id="ChangingtheValuesofListItemswithIndexAssignment">Changing the Values of List Items with Index Assignment</h2>
<p>You can also use the square brackets to change the value of an item in a list. Try typing <span class='m'>animals[1] = 'ANTEATER'</span>, then type <span class='m'>animals</span> to view the list.</p>
<div class='sourceblurb'>
>>> animals = ['aardvark', 'anteater', 'antelope', 'albert']<br />
>>> animals[1] = 'ANTEATER'<br />
>>> animals<br />
['aardvark', 'ANTEATER', 'antelope', 'albert']<br />
>>>
</div>
<p>The second item in the <span class='m'>animals</span> list has been overwritten with a new string.</p>
<h2 id="ListConcatenation">List Concatenation</h2>
<p>You can join lists together into one list with the <span class='m'>+</span> operator, just like you can join strings. When joining lists, this is known as <span class='term'>list concatenation</span>. Try typing <span class='m'>[1, 2, 3, 4] + ['apples', 'oranges'] + ['Alice', 'Bob']</span> into the shell:</p>
<div class='sourceblurb'>
>>> [1, 2, 3, 4] + ['apples', 'oranges'] + ['Alice', 'Bob']<br />
[1, 2, 3, 4, 'apples', 'oranges', 'Alice', 'Bob']<br />
>>>
</div>
<p>Notice that lists do not have to store values of the same data types. The example above has a list with both integers and strings in it. Remember, when you do list concatenation, you must add together two list values. <span class='m'>['apples'] + ['oranges']</span> will evaluate to <span class='m'>['apples', 'oranges']</span>. But <span class='m'>['apples'] + 'oranges'</span> will result in an error because you are adding a list value and string value instead of two list values. If you want to add non-list values to a list, use the <span class='m'>append()</span> method (which is described later).</p>
<h2 id="TheinOperator">The <span class='m'>in</span> Operator</h2>
<p>The <span class='m'>in</span> operator makes it easy to see if a value is inside a list or not. Expressions that use the <span class='m'>in</span> operator return a Boolean value: <span class='m'>True</span> if the value is in the list and <span class='m'>False</span> if the value is not in the list. Try typing <span class='m'>'antelope' in animals</span> into the shell:</p>
<div class='sourceblurb'>
>>> animals = ['aardvark', 'anteater', 'antelope', 'albert']<br />
>>> 'antelope' in animals<br />
True<br />
>>>
</div>
<p>The expression <span class='m'>'antelope' in animals</span> returns <span class='m'>True</span> because the string <span class='m'>'antelope'</span> can be found in the list, <span class='m'>animals</span>. (It is located at index 2.)</p>
<p>But if we type the expression <span class='m'>'ant' in animals</span>, this will return <span class='m'>False</span> because the string <span class='m'>'ant'</span> does not exist in the list. We can try the expression <span class='m'>'ant' in ['beetle', 'wasp', 'ant']</span>, and see that it will return <span class='m'>True</span>.</p>
<div class='sourceblurb'>
>>> animals = ['aardvark', 'anteater', 'antelope', 'albert']<br />
>>> 'antelope' in animals<br />
True<br />
>>> 'ant' in animals<br />
False<br />
>>> 'ant' in ['beetle', 'wasp', 'ant']<br />
True<br />
>>>
</div>
<p>The <span class='m'>in</span> operator also works for strings as well as lists. You can check if one string exists in another the same way you can check if a value exists in a list. Try typing <span class='m'>'hello' in 'Alice said hello to Bob.'</span> into the shell. This expression will evaluate to <span class='m'>True</span>.</p>
<div class='sourceblurb'>
>>> 'hello' in 'Alice said hello to Bob.'<br />
True<br />
>>>
</div>
<h2 id="RemovingItemsfromListswithdelStatements">Removing Items from Lists with <span class='m'>del</span> Statements</h2>
<p>You can remove items from a list with a <span class='m'>del</span> statement. ("del" is short for "delete.") Try creating a list of numbers by typing: <span class='m'>spam = [2, 4, 6, 8, 10]</span> and then <span class='m'>del spam[1]</span>. Type <span class='m'>spam</span> to view the list's contents:</p>
<div class='sourceblurb'>
>>> spam = [2, 4, 6, 8, 10]<br />
>>> del spam[1]<br />
>>> spam<br />
[2, 6, 8, 10]<br />
>>>
</div>
<p>Notice that when you deleted the item at index 1, the item that used to be at index 2 became the new value at index 1. The item that used to be at index 3 moved to be the new value at index 2. Everything above the item that we deleted moved down one index. We can type <span class='m'>del spam[1]</span> again and again to keep deleting items from the list:</p>
<div class='sourceblurb'>
>>> spam = [2, 4, 6, 8, 10]<br />
>>> del spam[1]<br />
>>> spam<br />
[2, 6, 8, 10]<br />
>>> del spam[1]<br />
>>> spam<br />
[2, 8, 10]<br />
>>> del spam[1]<br />
>>> spam<br />
[2, 10]<br />
>>>
</div>
<p>Just remember that <span class='m'>del</span> is a statement, not a function or an operator. It does not evaluate to any return value.</p>
<h2 id="ListsofLists">Lists of Lists</h2>
<p>Lists are a data type that can contain other values as items in the list. But these items can also be other lists. Let's say you have a list of groceries, a list of chores, and a list of your favorite pies. You can put all three of these lists into another list. Try typing this into the shell:</p>
<div class='sourceblurb' style='line-height: 120%;'>
>>> groceries = ['eggs', 'milk', 'soup', 'apples', 'bread']<br />
>>> chores = ['clean', 'mow the lawn', 'go grocery shopping']<br />
>>> favoritePies = ['apple', 'frumbleberry']<br />
>>> listOfLists = [groceries, chores, favoritePies]<br />
>>> listOfLists<br />
[['eggs', 'milk', 'soup', 'apples', 'bread'], ['clean', 'mow the lawn', 'go grocery shopping'], ['apple', 'frumbleberry']]<br />
>>>
</div>
<p>You could also type the following and get the same values for all four variables:</p>
<div class='sourceblurb' style='line-height: 120%;'>
>>> listOfLists = [['eggs', 'milk', 'soup', 'apples', 'bread'], ['clean', 'mow the lawn', 'go grocery shopping'], ['apple', 'frumbleberry']]<br />
>>> groceries = listOfLists[0]<br />
>>> chores = listOfLists[1]<br />
>>> favoritePies = listOfLists[2]<br />
>>> groceries<br />
['eggs', 'milk', 'soup', 'apples', 'bread']<br />
>>> chores<br />
['clean', 'mow the lawn', 'go grocery shopping']<br />
>>> favoritePies<br />
['apple', 'frumbleberry']<br />
>>>
</div>
<p>To get an item inside the list of lists, you would use <i>two</i> sets of square brackets like this: <span class='m'>listOfLists[1][2]</span> which would evaluate to the string <span class='m'>'go grocery shopping'</span>. This is because <span class='m'>listOfLists[1]</span> evaluates to the list <span class='m'>['clean', 'mow the lawn', 'go grocery shopping'][2]</span>. That finally evaluates to <span class='m'>'go grocery shopping'</span>.</p>
<p>Here is another example of a list of lists, along with some of the indexes that point to the items in the list of lists named <span class='m'>x</span>. The red arrows point to indexes of the inner lists themselves. The image is also flipped on its side to make it easier to read:</p>
<p class='centeredImageP createspace'><img width='570' height='374' src='images/9-1.png' alt='' class='centeredImage' /><br />
Figure 9-1: The indexes of a list of lists.</p>
<p class='centeredImageP noncreatespace'><img src='images/9-1.png' alt='' class='centeredImage' /><br />
Figure 9-1: The indexes of a list of lists.</p>
<!-- END OF FIRST HALF -->
<h2 id="Methods">Methods</h2>
<p><span class='term'>Methods</span> are just like functions, but they are always attached to a value. For example, all string values have a <span class='m'>lower()</span> method, which returns a copy of the string value in lowercase. You cannot just call <span class='m'>lower()</span> by itself and you do not pass a string argument to <span class='m'>lower()</span> by itself (as in <span class='m'>lower('Hello')</span>). You must attach the method call to a specific string value using a period.</p>
<h3 id="ThelowerandupperStringMethods">The <span class='m'>lower()</span> and <span class='m'>upper()</span> String Methods</h3>
<p>Try entering <span class='m'>'Hello world!'.lower()</span> into the interactive shell to see an example of this method:</p>
<div class='sourceblurb'>
>>> 'Hello world'.lower()<br />
'hello world!'<br />
>>><br />
</div>
<p>There is also an <span class='m'>upper()</span> method for strings, which changes all the characters in a string to uppercase. Try entering <span class='m'>'Hello world'.upper()</span> into the shell:</p>
<div class='sourceblurb'>
>>> 'Hello world'.upper()<br />
'HELLO WORLD! '<br />
>>><br />
</div>
<p>Because the <span class='m'>upper()</span> method returns a string, you can call a method on <i>that</i> string as well. Try typing <span class='m'>'Hello world!'.upper().lower()</span> into the shell:</p>
<div class='sourceblurb'>
>>> 'Hello world'.upper().lower()<br />
'hello world!'<br />
>>><br />
</div>
<p><span class='m'>'Hello world!'.upper()</span> evaluates to the string <span class='m'>'HELLO WORLD!'</span>, and then we call that string's <span class='m'>lower()</span> method. This returns the string <span class='m'>'hello world!'</span>, which is the final value in the evaluation. The order is important. <span class='m'>'Hello world!'.lower().upper()</span> is not the same as <span class='m'>'Hello world!'.upper().lower()</span>:</p>
<div class='sourceblurb'>
>>> 'Hello world'.lower().upper()<br />
'HELLO WORLD!'<br />
>>><br />
</div>
<p>Remember, if a string is stored in a variable, you can call a string method on that variable. Look at this example:</p>
<div class='sourceblurb'>
>>> fizz = 'Hello world'<br />
>>> fizz.upper()<br />
'HELLO WORLD'<br />
>>><br />
</div>
<h3 id="ThereverseListMethod">The <span class='m'>reverse()</span> and <span class='m'>append()</span> List Methods</h3>
<p>The list data type also has methods. The <span class='m'>reverse()</span> method will reverse the order of the items in the list. Try entering <span class='m'>spam = [1, 2, 3, 4, 5, 6, 'meow', 'woof']</span>, and then <span class='m'>spam.reverse()</span> to reverse the list. Then enter <span class='m'>spam</span> to view the contents of the variable.</p>
<div class='sourceblurb'>
>>> spam = [1, 2, 3, 4, 5, 6, 'meow', 'woof']<br />
>>> spam.reverse()<br />
>>> spam<br />
['woof', 'meow', 6, 5, 4, 3, 2, 1]<br />
>>><br />
</div>
<p>The most common list method you will use is <span class='m'>append()</span>. This method will add the value you pass as an argument to the end of the list. Try typing the following into the shell:</p>
<div class='sourceblurb'>
>>> eggs = []<br />
>>> eggs.append('hovercraft')<br />
>>> eggs<br />
['hovercraft']<br />
>>> eggs.append('eels')<br />
>>> eggs<br />
['hovercraft', 'eels']<br />
>>> eggs.append(42)<br />
>>> eggs<br />
['hovercraft', 'eels', 42]<br />
>>><br />
</div>
<p>Though string and list data types have methods, integers do not happen to have any methods.</p>
<h2 id="TheDifferenceBetweenMethodsandFunctions">The Difference Between Methods and Functions</h2>
<p>You may be wondering why Python has methods, since they seem to act just like functions. Some data types have methods. Methods are functions associated with values of that data type. For example, string methods are functions that can be called on any string. If you have the string value <span class='m'>'Hello'</span>, you could call the string method <span class='m'>upper()</span> like this: <span class='m'>'Hello'.upper()</span>. Or if the string <span class='m'>'Hello'</span> were stored in a variable named <span class='m'>spam</span>, it would look like this: <span class='m'>spam.upper()</span></p>
<p>You cannot call string methods on values of other data types. For example, <span class='m'>[1, 2, 'apple'].upper()</span> would cause an error because <span class='m'>[1, 2, 'apple']</span> is a list and <span class='m'>upper()</span> is a string method.</p>
<!--<p>Methods are associated with a value of a certain data type. Functions are never associated with values. Function calls for functions that are inside modules may look like methods because they have a name and period in front, such as <span class='m'>random.randint()</span>. But random is the name of a module, it is not a value or a variable with a value in it.</p>-->
<p>The values of data types that have methods are also called objects. Object-oriented programming is a bit advanced for this book, and you don't need to understand it to make games. Just understand that objects are another name for a values of data types that have methods. For example, all strings and lists are objects.</p>
<h2 id="ThesplitListMethod">The <span class='m'>split()</span> List Method</h2>
<p>Line 59 is a very long line of code, but it is really just a simple assignment statement. This line also uses the <span class='m'>split()</span> method, which is a method for the string data type (just like the <span class='m'>lower()</span> and <span class='m'>upper()</span> methods).</p>
<div class='sourcecode'><ol start='59'>
<li>words = 'ant baboon badger bat bear beaver camel cat clam cobra cougar coyote crow deer dog donkey duck eagle ferret fox frog goat goose hawk 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'.split()</li>
</ol></div>
<p>As you can see, this line is just one very long string, full of words separated by spaces. And at the end of the string, we call the <span class='m'>split()</span> method. The <span class='m'>split()</span> method changes this long string into a list, with each word making up a single list item. The "split" occurs wherever a space occurs in the string. The reason we do it this way, instead of just writing out the list, is that it is easier for us to type as one long string. If we created it as a list to begin with, we would have to type: <span class='m'>['ant', 'baboon', 'badger',</span>... and so on, with quotes and commas for every single word.</p>
<p>For an example of how the <span class='m'>split()</span> string method works, try typing this into the shell:</p>
<div class='sourceblurb'>
>>> 'My very energetic mother just served us nine pies'.split()<br />
['My', 'very', 'energetic', 'mother', 'just', 'served', 'us', 'nine', 'pies']<br />
>>><br />
</div>
<p>The result is a list of nine strings, one string for each of the words in the original string. The spaces are dropped from the items in the list. Once we've called <span class='m'>split()</span>, the <span class='m'>words</span> list will contain all the possible secret words that can be chosen by the computer for our Hangman game. You can also add your own words to the string, or remove any you don't want to be in the game. Just make sure that the words are separated by spaces.</p>
<h2 id="HowtheCodeWorks">How the Code Works</h2>
<p>Starting on line 61, we define a new function called <span class='m'>getRandomWord()</span>, which has a single parameter named <span class='m'>wordList</span>. We will call this function when we want to pick a single secret word from a list of secret words.</p>
<div class='sourcecode'><ol start='61'>
<li>def getRandomWord(wordList):</li>
<li> # This function returns a random string from the passed list of strings.</li>
<li> wordIndex = random.randint(0, len(wordList) - 1)</li>
<li> return wordList[wordIndex]</li>
</ol></div>
<p>The function <span class='m'>getRandomWord()</span> is passed a list of strings as the argument for the <span class='m'>wordList</span> parameter. On line 63, we will store a random index for this list in the <span class='m'>wordIndex</span> variable. We do this by calling <span class='m'>randint()</span> with two arguments. Remember that arguments in a function call are separated by commas, so the first argument is <span class='m'>0</span> and the second argument is <span class='m'>len(wordList) - 1</span>. The second argument is an expression that is first evaluated. <span class='m'>len(wordList)</span> will return the integer size of the list passed to <span class='m'>getRandomWord()</span>, and then we subtract one.</p>
<p>The reason we need the <span class='m'>- 1</span> is because the indexes for lists start at 0, not 1. If we have a list of three items, the index of the first item is 0, the index of the second item is 1, the index of the third item is 2. The length of this list is <span class='m'>3</span>, but the index 3 is after the last index. This is why we subtract 1 from the length.</p>
<p>For example, if we passed ['apple', 'orange', grape'] as an argument to <span class='m nw'>getRandomWord()</span>, then <span class='m'>len(wordList)</span> would return the integer <span class='m'>3</span> and the expression <span class='m'>3 - 1</span> would evaluate to the integer <span class='m'>2</span>.</p>
<p>That means that <span class='m'>wordIndex</span> would contain the return value of <span class='m'>randint(0, 2)</span>, which means <span class='m'>wordIndex</span> would equal <span class='m'>0</span>, <span class='m'>1</span>, or <span class='m'>2</span>. On line 64, we would return the element in <span class='m'>wordList</span> at the integer index stored in <span class='m'>wordIndex</span>.</p>
<p>Let's pretend we did send <span class='m'>['apple', 'orange', grape']</span> as the argument to <span class='m'>getRandomWord()</span> and that <span class='m'>randint(0, 2)</span> returned the integer <span class='m'>2</span>. That would mean that line 64 would become <span class='m'>return wordList[2]</span>, which would evaluate to <span class='m'>return 'grape'</span>. This is how the <span class='m'>getRandomWord()</span> returns a random string in the <span class='m'>wordList</span> list. The following code entered into the interactive shell demonstrates this:</p>
<div class='sourceblurb'>
>>> wordIndex = 2<br />
>>> print(wordIndex)<br />
2<br />
>>> print(['apple', 'orange', 'grape'][wordIndex])<br />
grape<br />
>>><br />
</div>
<p>And remember, we can pass any list of strings we want to the <span class='m'>getRandomWord()</span> function, which is what makes it so useful for our Hangman game.</p>
<h3 id="DisplayingtheBoardtothePlayer">Displaying the Board to the Player</h3>
<p>Next we need to create another function which will print the hangman board on the screen, along with how many letters the player has correctly (and incorrectly) guessed.</p>
<div class='sourcecode'><ol start='66'>
<li>def displayBoard(HANGMANPICS, missedLetters, correctLetters, secretWord):</li>
<li> print(HANGMANPICS[len(missedLetters)])</li>
<li> print()</li>
</ol></div>
<p>This code defines a new function named <span class='m'>displayBoard()</span>. This function has four parameters. This function will implement the code for the "Show the board and blanks to the player" box in our flow chart. Here is what each parameter means:</p>
<ul>
<li><span class='m'>HANGMANPICS</span> - This is a list of multi-line strings that will display the board as ASCII art. We will always pass the global <span class='m'>HANGMANPICS</span> variable as the argument for this parameter.</li>
<li><span class='m'>missedLetters</span> - This is a string made up of the letters the player has guessed that are not in the secret word.</li>
<li><span class='m'>correctLetters</span> - This is a string made up of the letters the player has guessed that are in the secret word.</li>
<li><span class='m'>secretWord</span> - This string is the secret word that the player is trying to guess..</li>
</ul>
<p>The first <span class='m'>print()</span> function call will display the board. <span class='m'>HANGMANPICS</span> will be a list of strings for each possible board. <span class='m'>HANGMANPICS[0]</span> shows an empty gallows, <span class='m'>HANGMANPICS[1]</span> shows the head (this happens when the player misses one letter), <span class='m'>HANGMANPICS[2]</span> shows a head and body (this happens when the player misses two letters), and so on until <span class='m'>HANGMANPICS[6]</span> when the full hangman is shown and the player loses.</p>
<p>The number of letters in <span class='m'>missedLetters</span> will tell us how many incorrect guesses the player has made. We can call <span class='m'>len(missedLetters)</span> to find out this number. This number can also be used as the index to the <span class='m'>HANGMANPICS</span> list, which will allow us to print the correct board for the number of incorrect guesses. So, if <span class='m'>missedLetters</span> is <span class='m'>'aetr'</span> then <span class='m'>len('aetr')</span> will return <span class='m'>4</span> and we will display the string <span class='m'>HANGMANPICS[4]</span>. This is what <span class='m'>HANGMANPICS[len(missedLetters)]</span> evaluates to. This line shows the correct hangman board to the player.</p>
<div class='sourcecode'><ol start='70'>
<li> print('Missed letters:', end=' ')</li>
<li> for letter in missedLetters:</li>
<li> print(letter, end=' ')</li>
<li> print()</li>
</ol></div>
<p>Line 71 is a new type of loop, called a <span class='m'>for</span> loop. A <span class='m'>for</span> loop is kind of like a <span class='m'>while</span> loop. Line 72 is the entire body of the <span class='m'>for</span> loop. The <span class='m'>range()</span> function is often used with <span class='m'>for</span> loops. I will explain both in the next two sections.</p>
<p>Remember that the keyword argument <span class='m'>end=' '</span> uses only one = sign (like <span class='m'>=</span>), not two (like <span class='m'>==</span>).</p>
<h2 id="TherangeFunction">The <span class='m'>range()</span> and <span class='m'>list()</span> Functions</h2>
<p>The <span class='m'>range()</span> function is easy to understand. You can call it with either one or two integer arguments. When called with one argument, <span class='m'>range()</span> will return a range object of integers from 0 up to (but not including) the argument. This range object can be converted to the more familiar list data type with the <span class='m'>list()</span> function. Try typing <span class='m'>list(range(10))</span> into the shell:</p>
<div class='sourceblurb'>
>>> list(range(10))<br />
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]<br />
>>><br />
</div>
<p>The <span class='m'>list()</span> function is very similar to the <span class='m'>str()</span> or <span class='m'>int()</span> functions. It just converts the object it is passed into a list. It's very easy to generate huge lists with the <span class='m'>range()</span> function. Try typing in <span class='m'>list(range(10000))</span> into the shell:</p>
<div class='sourceblurb'>
>>> list(range(10000))<br />
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,...<br />
...The text here has been skipped for brevity...<br />
...9989, 9990, 9991, 9992, 9993, 9994, 9995, 9996, 9997, 9998, 9999]<br />
>>><br />
</div>
<p>The list is so huge, that it won't even all fit onto the screen. But we can save the list into the variable just like any other list by entering this:</p>
<div class='sourceblurb'>
>>> spam = list(range(10000))<br />
>>><br />
</div>
<p>If you pass two arguments to <span class='m'>range()</span>, the list of integers it returns is from the first argument up to (but not including) the second argument. Try typing <span class='m'>list(range(10, 20))</span> into the shell:</p>
<div class='sourceblurb'>
>>> list(range(10, 20))<br />
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]<br />
>>><br />
</div>
<p>The <span class='m'>range()</span> is a very useful function, because we often use it in <span class='m'>for</span> loops (which are much like the <span class='m'>while</span> loops we have already seen).</p>
<h2 id="forLoops"><span class='m'>for</span> Loops</h2>
<p>The <span class='m'>for</span> loop is very good at looping over a list of values. This is different from the <span class='m'>while</span> loop, which loops as long as a certain condition is true. A <span class='m'>for</span> statement begins with the <span class='m'>for</span> keyword, followed by a variable name, followed by the <span class='m'>in</span> keyword, followed by a sequence (such as a list or string) or a range object (returned by the <span class='m nw'>range()</span> function), and then a colon. Each time the program execution goes through the loop (that is, on each <span class='term'>iteration</span> through the loop) the variable in the <span class='m'>for</span> statement takes on the value of the next item in the list.</p>
<p>For example, you just learned that the <span class='m'>range()</span> function will return a list of integers. We will use this list as the <span class='m'>for</span> statement's list. In the shell, type <span class='m'>for i in <span class='nw'>range(10):</span></span> and press Enter. Nothing will happen, but the shell will indent the cursor and change the prompt from <span class='m'>>>></span> to <span class='m'>...</span> because it is waiting for you to type in the for-block. Type <span class='m'>print(i)</span> and press Enter. Then, to tell the interactive shell you are done typing in the for-block, press Enter again to enter a blank line. The shell will then execute your <span class='m'>for</span> statement and block:</p>
<div class='sourceblurb'>
>>> for i in range(10):<br />
... print(i)<br />
...<br />
0<br />
1<br />
2<br />
3<br />
4<br />
5<br />
6<br />
7<br />
8<br />
9<br />
>>><br />
</div>
<p>Notice that with <span class='m'>for</span> loops, you do not need to convert the range object returned by the <span class='m'>range()</span> function into a list with <span class='m'>list()</span>. <span class='m'>for</span> loops do this for us automatically.</p>
<p>The <span class='m'>for</span> loop executes the code inside the for-block once for each item in the list. Each time it executes the code in the for-block, the variable <span class='m'>i</span> is assigned the next value of the next item in the list. If we used the <span class='m'>for</span> statement with the list <span class='m'>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]</span> instead of <span class='m'>range(10)</span>, it would have been the same:</p>
<div class='sourceblurb'>
>>> for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:<br />
... print(i)<br />
...<br />
0<br />
1<br />
2<br />
3<br />
4<br />
5<br />
6<br />
7<br />
8<br />
9<br />
>>><br />
</div>
<p>The <span class='m'>for</span> statement automatically converts the range object returned by <span class='m'>range()</span> into a list, so there is no need to put something like list(range(10)) in the <span class='m'>for</span> statemet, just use <span class='m'>range(10)</span>.</p>
<p>Try typing this into the shell: <span class='m'>for thing in ['cats', 'pasta', 'programming', 'spam']:</span> and press Enter, then type <span class='m'>print('I really like ' + thing)</span> and press Enter, and then press Enter again to tell the shell to end the for-block. The output should look like this:</p>
<div class='sourceblurb'>
>>> for thing in ['cats', 'pasta', 'programming', 'spam']:<br />
... print('I really like ' + thing)<br />
...<br />
I really like cats<br />
I really like pasta<br />
I really like programming<br />
I really like spam<br />
>><br />
</div>
<p>And remember, because strings are also a sequence data type just like lists, you can use them in <span class='m'>for</span> statements as well. This example uses a single character from the string on each iteration:</p>
<div class='sourceblurb'>
>>> for i in 'Hello world!':<br />
... print(i)<br />
...<br />
H<br />
e<br />
l<br />
l<br />
o<br />
<br />
w<br />
o<br />
r<br />
l<br />
d<br />
!<br />
>>><br />
</div>
<h3 id="AwhileLoopEquivalentofaforLoop">A <span class='m'>while</span> Loop Equivalent of a <span class='m'>for</span> Loop</h3>
<p>The <span class='m'>for</span> loop is very similar to the <span class='m'>while</span> loop, but when you only need to iterate over items in a list, using a <span class='m'>for</span> loop is much less code to type. You can make a <span class='m'>while</span> loop that acts the same way as a <span class='m'>for</span> loop by adding extra code:</p>
<div class='sourceblurb'>
>>> sequence = ['cats', 'pasta', 'programming', 'spam']<br />
>>> index = 0<br />
>>> while (index < len(sequence)):<br />
... thing = sequence[index]<br />
... print('I really like ' + thing)<br />
... index = index + 1<br />
...<br />
I really like cats<br />
I really like pasta<br />
I really like programming<br />
I really like spam<br />
>>><br />
</div>
<p>But using the <span class='m'>for</span> statement automatically does all this extra code for us and makes programming easier since we have less to type. Our Hangman game will use <span class='m'>for</span> loops so you can see how useful they are in real games.</p>
<p>One more thing about <span class='m'>for</span> loops, is that the <span class='m'>for</span> statement has the <span class='m'>in</span> keyword in it. But when you use the <span class='m'>in</span> keyword in a <span class='m'>for</span> statement, Python does not treat it like the <span class='m'>in</span> operator you would use in something like <span class='m'>42 in [0, 42, 67]</span>. The <span class='m'>in</span> keyword in <span class='m'>for</span> statements is just used to separate the variable and the list it gets its values from.</p>
<p>The rest of the <span class='m'>displayBoard()</span> function displays the missed letters and creates the string of the secret word with all the unguessed letters as blanks.</p>
<div class='sourcecode'><ol start='72'>
print('Missed letters:', end=' ')<br />
for letter in missedLetters:<br />
print(letter, end=' ')<br />
print()<br />
</ol></div>
<p>This <span class='m'>for</span> loop on line 71 will display all the missed guesses that the player has made. When you play Hangman on paper, you usually write down these letters off to the side so you know not to guess them again. On each iteration of the loop the value of <span class='m'>letter</span> will be each letter in <span class='m'>missedLetters</span> in turn. Remember that the <span class='m'>end=' '</span> will replace the newline character that is printed after the string with a single space character.</p>
<p>If <span class='m'>missedLetters</span> was <span class='m'>'ajtw'</span> then this <span class='m'>for</span> loop would display <span class='m'>a j t w</span>.</p>
<h2 id="SlicesandSlicing">Slices and Slicing</h2>
<p>If we want to get a shorter copy of some of the items in a list, we can use list slicing. <span class='term'>Slicing</span> creates a duplicate list out of some or all of the items in another list. In code, we can create a slice of a list by specifying two indexes (the beginning and end) and a colon. For example, type the following into the interactive shell:</p>
<div class='sourceblurb'>
>>> spam = ['apples', 'oranges', 'pears', 'bananas']<br />
>>> eggs = spam[1:3]<br />
>>> eggs<br />
['oranges', 'pears']<br />
</div>
<p>The expression <span class='m'>spam[0:2]</span> evaluates to a list that contains all the items from index <span class='m'>0</span> up to (but not including) index <span class='m'>2</span> in <span class='m'>spam</span>. We store this smaller list in the variable <span class='m'>eggs</span>.</p>
<p>If you leave out the first index, Python will automatically think you want to specify index <span class='m'>0</span> for the first index:</p>
<div class='sourceblurb'>
>>> spam = ['apples', 'oranges', 'pears', 'bananas']<br />
>>> spam[:3]<br />
['apples', 'oranges', 'pears']<br />
</div>
<p>If you leave out the second index, Python will automatically think you want to specify the rest of the list:</p>
<div class='sourceblurb'>
>>> spam = ['apples', 'oranges', 'pears', 'bananas']<br />
>>> spam[1:]<br />
['oranges', 'pears', 'bananas']<br />
</div>
<p>Slicing is a simple way to get a subset of the items in a list. You can also use slices with strings in the same way you use them with lists. Each character in the string is like an item in the list. Try typing the following into the shell:</p>
<div class='sourceblurb'>
>>> myName = 'Zophie the Fat Cat'<br />
>>> myName[4:12]<br />
'ie the F'<br />
>>> myName[:10]<br />
'Zophie the'<br />
>>> myName[7:]<br />
'the Fat Cat'<br />
>>>
</div>
<p>Slices are used in the next part of the code we look at.</p>
<h3 id="DisplayingtheSecretWordwithBlanks">Displaying the Secret Word with Blanks</h3>
<p>So by this point we have shown the player the hangman board and the missed letters. Now we want to print the secret word, except we want blank lines for the letters. We can use the _ character (called the underscore character) for this. But we should print the letters in the secret word that the player has guessed, and use _ characters for the letters the player has not guessed yet. We can first create a string with nothing but one underscore for each letter in the secret word. Then we can replace the blanks for each letter in <span class='m'>correctLetters</span>. So if the secret word was <span class='m'>'otter'</span> then the blanked out string would be <span class='m'>'_____'</span> (five _ characters). If <span class='m'>correctLetters</span> was the string <span class='m'>'rt'</span> then we would want to change the blanked string to <span class='m'>'_tt_r'</span>. Here is the code that does that:</p>
<div class='sourcecode'><ol start='75'>
<li> blanks = '_' * len(secretWord)</li>
<li></li>
<li> for i in range(len(secretWord)): # replace blanks with correctly guessed letters</li>
<li> if secretWord[i] in correctLetters:</li>
<li> blanks = blanks[:i] + secretWord[i] + blanks[i+1:]</li>
<li></li>
<li> for letter in blanks: # show the secret word with spaces in between each letter</li>
</ol></div>
<p>Line 75 creates the <span class='m'>blanks</span> variable full of _ underscores using string replication. Remember that the <span class='m'>*</span> operator can also be used on a string and an integer, so the expression <span class='m'>'hello' * 3</span> evaluates to <span class='m'>'hellohellohello'</span>. This will make sure that <span class='m'>blanks</span> has the same number of underscores as <span class='m'>secretWord</span> has letters.</p>
<p>Then we use a <span class='m'>for</span> loop to go through each letter in <span class='m'>secretWord</span> and replace the underscore with the actual letter if it exists in <span class='m'>correctLetters</span>. Line 79 may look confusing. It seems that we are using the square brackets with the <span class='m'>blanks</span> and <span class='m'>secretWord</span> variables. But wait a second, <span class='m'>blanks</span> and <span class='m'>secretWord</span> are strings, not lists. And the <span class='m'>len()</span> function also only takes lists as parameters, not strings. But in Python, many of the things you can do to lists you can also do to strings such as replication, indexing, and slicing.</p>
<h3 id="ReplacingtheUnderscoreswithCorrectlyGuessedLetters">Replacing the Underscores with Correctly Guessed Letters</h3>
<div class='sourcecode'><ol start='77'>
<li> for i in range(len(secretWord)): # replace blanks with correctly guessed letters</li>
<li> if secretWord[i] in correctLetters:</li>
<li> blanks = blanks[:i] + secretWord[i] + blanks[i+1:]</li>
</ol></div>
<p>Let's pretend the value of <span class='m'>secretWord</span> is <span class='m'>'otter'</span> and the value in <span class='m'>correctLetters</span> is <span class='m'>'tr'</span>. Then <span class='m'>len(secretWord)</span> will return <span class='m'>5</span>. Then <span class='m'>range(len(secretWord))</span> becomes <span class='m'>range(5)</span>, which in turn returns the list <span class='m'>[0, 1, 2, 3, 4]</span>.</p>
<p>Because the value of <span class='m'>i</span> will take on each value in <span class='m'>[0, 1, 2, 3, 4]</span>, then the <span class='m'>for</span> loop code is equivalent to this:</p>
<div class='sourceblurb'>
if secretWord[0] in correctLetters:<br />
blanks = blanks[:0] + secretWord[0] + blanks[1:]<br />
if secretWord[1] in correctLetters:<br />
blanks = blanks[:1] + secretWord[1] + blanks[2:]<br />
if secretWord[2] in correctLetters:<br />
blanks = blanks[:2] + secretWord[2] + blanks[3:]<br />
if secretWord[3] in correctLetters:<br />
blanks = blanks[:3] + secretWord[3] + blanks[4:]<br />
if secretWord[4] in correctLetters:<br />
blanks = blanks[:4] + secretWord[4] + blanks[5:]<br />
</div>
<p>(By the way, writing out the code like this is called <span class='term'>loop unrolling</span>.)</p>
<p>If you are confused as to what the value of something like <span class='m'>secretWord[0]</span> or <span class='m'>blanks[3:]</span> is, then look at this picture. It shows the value of the <span class='m'>secretWord</span> and <span class='m'>blanks</span> variables, and the index for each letter in the string.</p>
<p class='centeredImageP'><img src='images/9-2.png' alt='' class='centeredImage' /><br />
Figure 9-2: The indexes of the <span class='m'>blanks</span> and <span class='m'>secretWord</span> strings.</p>
<p>If we replace the list slices and the list indexes with the values that they represent, the unrolled loop code would be the same as this:</p>
<div class='sourceblurb'>
if 'o' in 'tr': # False, blanks == '_____'<br />
blanks = '' + 'o' + '____' # This line is skipped.<br />
if 't' in 'tr': # True, blanks == '_____'<br />
blanks = '_' + 't' + '___' # This line is executed.<br />
if 't' in 'tr': # True, blanks == '_t___'<br />
blanks = '_t' + 't' + '__' # This line is executed.<br />
if 'e' in 'tr': # False, blanks == '_tt__'<br />
blanks = '_tt' + 'e' + '_' # This line is skipped.<br />
if 'r' in 'tr': # True, blanks == '_tt__'<br />
blanks = '_tt_' + 'r' + '' # This line is executed.<br />
# blanks now has the value '_tt_r'<br />
</div>
<p>The above three code examples all do the <i>same thing</i> (at least, they do when <span class='m'>secretWord</span> is <span class='m'>'otter'</span> and <span class='m'>correctLetters</span> is <span class='m'>'tr'</span>. The first box is the actual code we have in our game. The second box shows code that does the same thing except without a <span class='m'>for</span> loop. The third box is the same as the second box, except we have evaluated many of the expressions in the second box.</p>
<p>The next few lines of code display the new value of <span class='m'>blanks</span> with spaces in between each letter.</p>
<div class='sourcecode'><ol start='81'>
<li> for letter in blanks: # show the secret word with spaces in between each letter</li>
<li> print(letter, end=' ')</li>
<li> print()</li>
</ol></div>
<p>This <span class='m'>for</span> loop will print out each character in the string <span class='m'>blanks</span>. Remember that by now, <span class='m'>blanks</span> may have some of its underscores replaced with the letters in <span class='m'>secretWord</span>. The <span class='m'>end</span> keyword argument in line 82's <span class='m'>print()</span> call makes the <span class='m nw'>print()</span> function put a space character at the end of the string instead of a newline character. This is the end of the <span class='m'>displayBoard()</span> function.</p>
<h3 id="GetthePlayersGuess">Get the Player's Guess</h3>
<p>The <span class='m'>getGuess()</span> function we create next will be called whenever we want to let the player type in a letter to guess. The function returns the letter the player guessed as a string. Further, <span class='m'>getGuess()</span> will make sure that the player types a valid letter before returning from the function.</p>
<div class='sourcecode'><ol start='85'>
<li>def getGuess(alreadyGuessed):</li>
<li> # Returns the letter the player entered. This function makes sure the player entered a single letter, and not something else.</li>
</ol></div>
<p>The <span class='m'>getGuess()</span> function has a string parameter called <span class='m'>alreadyGuessed</span> which should be passed a string that contains the letters the player has already guessed, and will ask the player to guess a single letter. This single letter will be the return value for this function.</p>
<div class='sourcecode'><ol start='87'>
<li> while True:</li>
<li> print('Guess a letter.')</li>
<li> guess = input()</li>
<li> guess = guess.lower()</li>
</ol></div>
<p>We will use a <span class='m'>while</span> loop because we want to keep asking the player for a letter until they enter text that is a single letter they have not guessed previously. Notice that the condition for the <span class='m'>while</span> loop is simply the Boolean value <span class='m'>True</span>. That means the only way execution will ever leave this loop is by executing a <span class='m'>break</span> statement (which leaves the loop) or a <span class='m'>return</span> statement (which leaves the entire function). Such a loop is called an <span class='term'>infinite loop</span>, because it will loop forever (unless it reaches a <span class='m'>break</span> statement).</p>
<p>The code inside the loop asks the player to enter a letter, which is stored in the variable <span class='m'>guess</span>. If the player entered a capitalized letter, it will be converted to lowercase on line 90.</p>
<h2 id="elifElseIfStatements"><span class='m'>elif</span> ("Else If") Statements</h2>
<p>Take a look at the following code:</p>
<div class='sourceblurb'>
if catName == 'Fuzzball':<br />
print('Your cat is fuzzy.')<br />
else:<br />
print('Your cat is not very fuzzy at all.')<br />
</div>
<p>We've seen code like this before and it's rather simple. If the <span class='m'>catName</span> variable is equal to the string <span class='m'>'Fuzzball'</span>, then the <span class='m'>if</span> statement's condition is <span class='m'>True</span> and we tell the user that her cat is fuzzy. If <span class='m'>catName</span> is anything else, then we tell the user her cat is not fuzzy.</p>
<p>But what if we wanted something else besides "fuzzy" and "not fuzzy"? We could put another <span class='m'>if</span> and <span class='m'>else</span> statement inside the first <span class='m'>else</span> block like this:</p>
<div class='sourceblurb'>
if catName == 'Fuzzball':<br />
print('Your cat is fuzzy.')<br />
else:<br />
if catName == 'Spots'<br />
print('Your cat is spotted.')<br />
else:<br />
print('Your cat is neither fuzzy nor spotted.')<br />
<br />
</div>
<p>But if we wanted more things, then the code starts to have a lot of indentation:</p>
<div class='sourceblurb'>
if catName == 'Fuzzball':<br />
print('Your cat is fuzzy.')<br />
else:<br />