Extended Exercise: Hangman


rawhtml15 <#5765#>Figure: Three stages of the hangman picture<#5765#>
Hangman is a two-player, word-guessing game. One player thinks of a three-letter word and draws the noose of a gallows (see figure~#fighangman#5768>); the other player tries to guess the word, one letter at a time. For every wrong guess, the first player adds another part to the drawing (see figure~#fighangman#5769>): first the head, then the body, the arms, and the legs. If, however, a guess agrees with one or two letters in the chosen word, the first player reveals the position(s) where this letter occurs. The game is over when the second player guesses the complete word or when the first player has completed the stick figure. Let's design a program that plays the role of the first player. The program consists of two parts: one for drawing the figure, and another one for determining whether a guess occurs in the chosen word and where.
<#5772#>Exercise 6.7.1<#5772#> Develop the function <#61375#><#5774#>draw-next-part<#5774#><#61375#>, which draws the pieces of a hangman figure. The function consumes one of the following seven symbols: <#61376#><#5776#>'<#5776#><#5777#>right-leg<#5777#><#61376#> <#61377#><#5778#>'<#5778#><#5779#>left-leg<#5779#><#61377#> <#61378#><#5780#>'<#5780#><#5781#>left-arm<#5781#><#61378#> <#61379#><#5782#>'<#5782#><#5783#>right-arm<#5783#><#61379#> <#61380#><#5784#>'<#5784#><#5785#>body<#5785#><#61380#> <#61381#><#5786#>'<#5786#><#5787#>head<#5787#><#61381#> <#61382#><#5788#>'<#5788#><#5789#>noose<#5789#><#61382#> It always returns <#61383#><#5791#>true<#5791#><#61383#> and draws the matching part of the figure. See figure~#fighangman#5792> for three snapshots of intermediate stages. <#5794#>Hints:<#5794#> \ Add <#61385#><#5795#>(start<#5795#>\ <#5796#>200<#5796#>\ <#5797#>200)<#5797#><#61385#> to the top of the definition window; it creates a new canvas. Start with the noose and develop one component at a time. If a component of the stick figure requires more than one drawing operation, combine the operations with <#61386#><#5798#>and<#5798#><#61386#>, which evaluates both expressions and ensure that they evaluate to <#61387#><#5799#>true<#5799#><#61387#>.~ external Solution<#61388#><#61388#>
The second task of the first player is to determine whether a guess is among the letters of the chosen word and, if so, where it occurs. Our recipe requires that, before we design a function for this task, we need to analyze our data and provide data definitions. The key objects of the game are words and letters. A <#5807#>word<#5807#> consists of three letters. A <#5808#>letter<#5808#> is represented with the symbols <#61389#><#5809#>'<#5809#><#5810#>a<#5810#><#61389#> through <#61390#><#5811#>'<#5811#><#5812#>z<#5812#><#61390#>. Using just those letters, however, is not enough because the program also needs to maintain a word that records how much the second player has guessed. The solution is to add one extra ``letter'' to our alphabet that is distinct from the others; the hangman teachpack uses <#61391#><#5813#>'<#5813#><#5814#>_<#5814#><#61391#> for this purpose.
<#5817#>Exercise 6.7.2<#5817#> Provide a structure definition and a data definition for representing three-letter words. ~ external Solution<#61392#><#61392#> <#5824#>Exercise 6.7.3<#5824#> Develop the function <#61393#><#5826#>reveal<#5826#><#61393#>. It consumes three arguments:
  1. the <#5828#>chosen<#5828#> word, which is the word that we have to guess;
  2. the <#5829#>status<#5829#> word, which shows how much of the word bas been guessed so far; and
  3. a letter, which is our current <#5830#>guess<#5830#>.
The function produces a new status word, that is, a word that contains ordinary letters and <#61394#><#5832#>'<#5832#><#5833#>_<#5833#><#61394#>. The fields in the new status word are determined by comparing the guess with each pair of letters from the status word and the chosen word:
  1. If the guess is equal to the letter in the chosen word, the guess is the corresponding letter in the new status word.
  2. Otherwise, the new letter is the corresponding letter from the status word.
Test the function with the following examples:
  <#5840#>(reveal<#5840#> <#5841#>(make-word<#5841#> <#5842#>'<#5842#><#5843#>t<#5843#> <#5844#>'<#5844#><#5845#>e<#5845#> <#5846#>'<#5846#><#5847#>a)<#5847#> <#5848#>(make-word<#5848#> <#5849#>'<#5849#><#5850#>_<#5850#> <#5851#>'<#5851#><#5852#>e<#5852#> <#5853#>'<#5853#><#5854#>_<#5854#><#5855#>)<#5855#> <#5856#>'<#5856#><#5857#>u)<#5857#>
<#5858#>=<#5858#> <#5859#>(make-word<#5859#> <#5860#>'<#5860#><#5861#>_<#5861#> <#5862#>'<#5862#><#5863#>e<#5863#> <#5864#>'<#5864#><#5865#>_<#5865#><#5866#>)<#5866#> 
  <#5867#>(reveal<#5867#> <#5868#>(make-word<#5868#> <#5869#>'<#5869#><#5870#>a<#5870#> <#5871#>'<#5871#><#5872#>l<#5872#> <#5873#>'<#5873#><#5874#>e)<#5874#> <#5875#>(make-word<#5875#> <#5876#>'<#5876#><#5877#>a<#5877#> <#5878#>'<#5878#><#5879#>_<#5879#>  <#5880#>'<#5880#><#5881#>_<#5881#><#5882#>)<#5882#> <#5883#>'<#5883#><#5884#>e)<#5884#> 
<#5885#>=<#5885#> <#5886#>(make-word<#5886#> <#5887#>'<#5887#><#5888#>a<#5888#> <#5889#>'<#5889#><#5890#>_<#5890#> <#5891#>'<#5891#><#5892#>e)<#5892#> 
  <#5893#>(reveal<#5893#> <#5894#>(make-word<#5894#> <#5895#>'<#5895#><#5896#>a<#5896#> <#5897#>'<#5897#><#5898#>l<#5898#> <#5899#>'<#5899#><#5900#>l)<#5900#> <#5901#>(make-word<#5901#> <#5902#>'<#5902#><#5903#>_<#5903#> <#5904#>'<#5904#><#5905#>_<#5905#> <#5906#>'<#5906#><#5907#>_<#5907#><#5908#>)<#5908#> <#5909#>'<#5909#><#5910#>l)<#5910#> 
<#5911#>=<#5911#> <#5912#>(make-word<#5912#> <#5913#>'<#5913#><#5914#>_<#5914#> <#5915#>'<#5915#><#5916#>l<#5916#> <#5917#>'<#5917#><#5918#>l)<#5918#> 
The first one shows what happens when the <#61395#><#5922#>guess<#5922#><#61395#> does not occur in the word; the second one shows what happens when it does occur; and the last one shows what happens when it occurs twice. <#5923#>Hints:<#5923#> \ (1) Remember to develop auxiliary functions when a definition becomes too large or too complex to manage. (2) The function <#61396#><#5924#>reveal<#5924#><#61396#> consumes two structures and one atomic value (a letter). This suggests that we use the design recipe for compound data (figure~#figdesign3#5925>). For the template, it is best to write down the selector expressions in a two-column format, one column per word.~ external Solution<#61397#><#61397#>
When the functions <#61398#><#5933#>draw-next-part<#5933#><#61398#> and <#61399#><#5934#>reveal<#5934#><#61399#> are properly tested, set teachpack to <#5935#>hangman.ss<#5935#> and play the game by evaluating
<#5940#>(hangman<#5940#> <#5941#>make-word<#5941#> <#5942#>reveal<#5942#> <#5943#>draw-next-part)<#5943#>
The <#61400#><#5947#>hangman<#5947#><#61400#> function chooses a three-letter word randomly and displays a window with a pop-up menu for letters. Choose letters and, when ready, click the <#5948#>Check<#5948#> button to see whether the guess is correct. Comment out the test cases for exercise~#exdrawnext#5949> so that their drawing effects don't interfere with those of <#61401#><#5950#>hangman<#5950#><#61401#>.