Computer Science 105 Lab 7: Array Search, Sort, and the Game of HangPhrase
Due: November 6, 2001

Objectives and Overview: This lab provides an opportunity to develop all the methods of a complete class, and then use that class in the development of an interactive game of "hangPhrase," a gentle blend of the familiar games Hangman and Wheel of Fortune.

Part 1 is a review of arrays and sorting, as discussed in class and covered in Chapter 6 of your text.  There, you will complete the definition of the search, sort and other methods of the wordArray class.  Part 2 is an introduction to recursion, which is an important and distinctive problem solving technique.  Part 3 asks you to use your completed wordArray class and write a program that interacts with the user to play the game of hangPhrase.  

You are encouraged to work in teams of 2 or 3, in which case only one set of deliverables for Parts 1, 2, and 3 should be turned in.

Part 1 - Completing the wordArray Class: Searching and Sorting

This part of the project is a continuation of our discussions of arrays, searching, and sorting.  Completing the methods search, sort, and a few others that appear in the file wordArray.java will complete this part of the project.

Part 2 - Recursion

Recursive methods are introduced in Chapter 11 of your text.  A recursive method can be used in place of any method that contains a loop, and there are a few of them inside the wordArray class.  Read over the first three sections of Chapter 11 before continuing this section.

Consider the problem of finding the index of the minimum element in a subarray A[i]... A[nwords-1] of a wordArray A, which can be written in the following iterative Java method:

// loop-based definition of findMinimum
  int findMinimum (wordArray A, int i) {
    int j, min = i;
    for (j=i+1; j<nwords; j++)
      // A[min] <= all elements in A[i]...A[j-1]
      if (A[j].compareTo(A[min]) < 0)
         min = j;

    return min;
  }

The basic idea of recursion is to define the solution to a problem in terms of a "base case" and a "recursive case".   The base case identifies a situation in which the solution can be immediately computed.  The recursive case identifies a situation in which the solution can be expressed in terms of the solution to a slightly simpler problem.  The recursive version of findMinimum looks like this.

// recursive definition of findMinimum
  int findMinimum (wordArray A, int i) {
    if (i==nwords-1)
       return i;
    else {
       int j=findMinimum(A, i+1);
       if (A[i].compareTo(A[j]) < 0)
          return i;
       else
          return j;
    }
  }

Here, the base case is the one in which i=n (in Java vernacular, remembering that array indexes begin at 0, this translates to i==nStudents-1 ), so that the smallest element must be the ith, since that's the only one in a subarray of length 1.  The recursive case requires the method to call itself, using a slightly smaller subarray (beginning at position i+1), and storing that result in the index j.  If the ith element precedes the jth element -- which is expressed  as A[i].compareTo(A[j]) < 0 -- then i is the answer; otherwise j is the answer.

The key to recursive programming is identifying the base case and the recursive case.  This can be tricky for some kinds of problems.  However, for other kinds of problems it turns out to be more natural than writing a loop.

Questions:
1.  Convert as many of the methods in the wordArray class as you can to an equivalent method using recursion.
2.  What determines whether or not a method can be rewritten using recursion?  
3.  Suppose you have a recursive method.  Can it be converted to a method that has no recursion?  Explain.

Part 3 - The Game of HangPhrase

In this game, the program selects a secret phrase and then monitors the progress of a player in guessing the phrase.  A separate graphics window displays a traditional "gallows," in addition to a visual display of the secret word (with guessed letters displayed) and a list of the letters already guessed.  Below is the visual display generated by the Gallows class (Gallows.java).  

One wrong guess will place the person's head on the gallows.  Six (6) wrong guesses (one for the head, one for the torso, one for each arm, and one for each leg) will complete the game.  Letters in the secret phrase that remain to be guessed should be indicated by dashes (- ) in this window.  Letters that have already been guessed should be reported back to the player in this window.

A skeleton version of the program and the Gallows class are given in the files hangPhrase.java and Gallows.java, which may be copied into your myProject folder on the desktop from the CS105 (Tucker) server.  Copy the wordArray.java file into the myProject folder and run the program to obtain the display above.  Try it!

The program does not do anything yet because several key methods are incomplete -- that is, they have skeleton definitions but no code!  There's a lot of commentary inside the main program that indicates what methods and code need to be completed in order for this game to work correctly.  Please read these comments for guidance.

Note in this program that the principal variables are three wordArrays (lettersUsed , secretPhrase, and partialPhrase ), an integer (wrongGuesses ), and a String (nextLetter ).  Their roles in the game are described and illustrated below:
wordArray lettersUsed,   // the letters already guessed,  e.g. "lex"
       secretPhrase,  // the secret phrase,            e.g, "hello there"
       partialPhrase; // the partially-guessed phrase, e.g. "-ell- --e-e"
int    wrongGuesses;  // the number of wrong guesses,  e.g. 1
String nextLetter;      // next letter guessed,          e.g. "h"
These variables are initialized by the first few statements inside the inner loop of the main program.  The inner loop which follows these statements controls an interaction with the player who is guessing the secret phrase.

Each repetition of the inner loop should process a single letter guessed by the player.  That is, it should update the state of the game (the variables above and the graphics window) accordingly.  This loop needs to be completed.  Whoever will be doing this part of the project should begin by reading the detailed comments inside this loop in the main method of the hangPhrase0.java program listing.

This loop is assisted by calling several methods of the wordArray class, along with three major methods inside the hangPhrase class itself.  One of these, getSecretPhrase, is already complete, while the other two are not -- take a look at the hangPhrase.java listing.  Here are these skeletons, along with the commentary that describes the purposes of the other two methods.
        // Prompt the user to enter the next letter, checking that it
        // hasn't already been guessed; that is, it is not among the letters
        // already used.
        static String getNextGuess (wordArray lettersUsed) {
          String ng = " ";


          return ng;
        }

        static wordArray updatePhrase(wordArray pp, wordArray sp, String nl) {
        // Return the wprdArray that results from replacing each character pp[i]
        // by nl for which nl == sp[i], for 0 <= i < sp.length().  That is,
        // all occurrences of "-" in pp that correspond to occurrences of nl
        // in sp are replaced by nl.
          wordArray newpp = new wordArray();


          return newpp;
        }
The completion of these methods can be done independently of the other tasks in this project, and independently of each other.  So each one should be completed by a different team member.

Deliverables:

Each team should submit a hard copy of its completed wordArray class, its answers to Part 2, and its completed hangPhrase program.  Copies of your wordArray<yourname>.java and hangPhrase<yourname>.java programs should also be dragged to the CS105 (Tucker) -> Drop Box by 11:30am on the due date.