On this page:
1 Introduction(s)
2 Purpose
3 Hangman
3.1 Letter functions
3.2 Word functions
3.3 Hangman functions
4 A Trip to the Gallows
6.12

Lab 7: Rite of Words and Life

1 Introduction(s)

You’ll work in labs in pairs. Find someone to work with for this first lab and introduce yourself.

Make sure at least one of you have a laptop to work on for this lab.

The two of you will work as a team to solve problems. At any time, one of you will be the Head and the other will be the Hands. The Head does the thinking and the Hands does the typing. Hands type only what the Head tells them to, but you’re free to discuss any issues that pop up. We’ll have you switch off during the lab to make sure each of you get practice problem solving, dealing with syntax, and getting finger exercises on the keyboard.

2 Purpose

In this lab, you’ll practice
  • refining programs designed by others and

  • using lists to represent arbitrarily large collections of data.

3 Hangman

In this lab, you will be finishing a program designed to implement (a simplified version of) Hangman.

In this simplified version of the game, you are presented with a number of boxes, indicating that your job is to guess a word with that many letters in it. Pressing any alphabetic key will register a guess of that letter. If the letter is present in the word you’re trying to guess, the appropriate boxes will reveal that letter. If it is not present, you’ve registered a wrong guess and are one step closer to losing (although there will be no visual indication of this other than no letters appear). Make more than 6 wrong guesses and you’ve lost and the game will end.

An almost complete design of the program is available here: hangman.rkt.

Here are the critical data definitions for the program:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Data definitions
 
;; A Hangman is a (make-hangman Word Lo1String)
(define-struct hangman (word misses))
;; Interpretation: word is the (partially) guessed word
;; misses is a list of incorrect guesses
 
;; A Word is one of:
;; - '()
;; - (cons Letter Word)
;; Interpretation: a word where some letters maybe hidden
 
;; A Letter is one of:
;; - (make-hidden 1String)
;; - 1String
;; Interpretation: (make-hidden s) means s has not been revealed,
;; a string s means s has been revealed
(define-struct hidden (sec))
 
;; A Lo1String is one of:
;; - '()
;; - (cons 1String Lo1String)
 
;; A 1String is a String of length 1
3.1 Letter functions

Let’s start by looking at the Letter data definition. A letter can be in one of two states: either it is hidden (and not shown to the player) or it has been guessed and revealed. There are two functions for operating on letters, letter-draw and letter-reveal. Here are some examples to illustrate their use.

Examples:
> (letter-draw (make-hidden "a"))

image

> (letter-draw "a")

image

> (letter-draw (letter-reveal (make-hidden "a") "a"))

image

> (letter-draw (letter-reveal (make-hidden "a") "b"))

image

> (letter-draw (letter-reveal "a" "b"))

image

3.2 Word functions

Words are simply lists of letters.

Your first job is to design the functions word-draw and word-reveal, which are like the functions for letters, but work at the level of words. (Stubs are included in the code provided.)

There’s a convenience function provided which takes a string an makes a Word that hides the complete string. Here’s how word-draw and word-reveal should work.

Examples:
> (word-draw (string-hide "abc"))

image

> (word-draw (word-reveal (string-hide "abc") "a"))

image

> (word-draw (word-reveal (string-hide "abc") "b"))

image

> (word-draw (word-reveal (word-reveal (string-hide "abc") "a") "b"))

image

Lab problem 1: Word functions

Finish the design of word-reveal and word-draw.

3.3 Hangman functions

Of the functions that operate on Hangman values, the critical one is hangman-guess, which consumes the representation of a hangman game state and updates it according to a guess.

Three possible scenarios can occur:

Here’s a design for the hangman-guess function (tests are in the code provided):

;; Hangman 1String -> Hangman
;; Guess s in given game
(define (hangman-guess hm s)
  (cond [(hangman-hiding? hm s)
         (make-hangman (word-reveal (hangman-word hm) s)
                       (hangman-misses hm))]
        [(hangman-already-missed? hm s) hm]
        [else
         (make-hangman (hangman-word hm)
                       (cons s (hangman-misses hm)))]))

It relies upon two helper functions: hangman-already-missed?, which determines if the given guess was previously guessed (and wrong), and hangman-hiding? which determines if a given guess is hidden in the current game.

Here are some examples. We’re using the explode function as a convenience for turning a string into a list of its 1String parts.

Examples:
> (hangman-already-missed? (make-hangman (string-hide "Hello") '()) "b")

#f

> (hangman-already-missed? (make-hangman (string-hide "Hello") (explode "abc")) "b")

#t

> (hangman-already-missed? (make-hangman (string-hide "Hello") (explode "abc")) "d")

#f

> (hangman-hiding? (make-hangman (string-hide "Hello") '()) "e")

#t

> (hangman-hiding? (make-hangman (string-hide "Hello") '()) "z")

#f

> (hangman-hiding? (make-hangman (word-reveal (string-hide "Hello") "e") '()) "e")

#f

The hangman-already-missed? function needs to check for a given guess in the list of bad guesses in the given hangman. This task calls for another helper function which consumes a list of string and a string and determines if the string is in the list. With such a function, hangman-already-missed? becomes easy:

;; Hangman 1String -> Boolean
;; Was s already guessed in given game?
(define (hangman-already-missed? hm s)
  (los-contains? (hangman-misses hm) s))

Lab problem 2: List of strings function

Design the los-contains? function.

The hangman-hiding? function needs to check the word to see if contains a hidden letter corresponding to the guess. This task also suggest the need for a helper function that makes the design of hangman-hiding? trivial:

;; Hangman -> Boolean
;; Is s a hidden letter in the given game?
(define (hangman-hiding? hm s)
  (word-hiding? (hangman-word hm) s))

Lab problem 3: Word hiding function

Design the word-hiding? function.

4 A Trip to the Gallows

Putting the pieces together is pretty easy. Here’s the main function:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Main
 
;; String -> Hangman
;; Play a game of hangman trying to guess s
(define (main s)
  (big-bang (make-hangman (string-hide s) '())
    [on-key hangman-key]
    [to-draw hangman-draw]
    [stop-when hangman-done? hangman-draw-done]))

Note the use of a stop-when clause. This new big-bang clause is used to specify a predicate to determine if the game is over. Whenever it returns true of the current game state, the program stops, and the final state is rendered using the given drawing function.

If you’re curious about hangman-key, hangman-done?, or hangman-draw-done, take a look at the provided code.

Once you’ve completed the above problems, give it a try with (main "tangerine") or whichever word you’d like to use.