Stanford CS106A Hangman Solution

Ok, so I put up the different parts of the Hangman Game Assignment Solution in the previous posts, so I thought I’d put them all together here. You can also see the solutions on github. If you’re interested in part-by-part solution, check out these posts:

The main Hangman Program is as follows:

```/*
* File: Hangman.java
* ------------------
* This program will eventually play the Hangman game from
* Assignment #4.
*/

import acm.graphics.*;
import acm.program.*;
import acm.util.*;

import java.awt.*;

public class Hangman extends ConsoleProgram {

private HangmanLexicon hangmanWords;

private HangmanCanvas canvas;

private RandomGenerator rgen = RandomGenerator.getInstance();

/** Tracks the number of guesses the player has */
private int guessCounter = 8;

public void run() {
setUpGame();
playGame();
}

//This is the word being guessed
private String hiddenWord;

//This is the secret word
private String word = pickWord();

//This is the latest character entered by the user
private char ch;

//This string keeps track of all the incorrect guessed letters
private String incorrectLetters = &quot;&quot;;

/*Set up the game by displaying the welcome message,
*how many letters there are in the word,
*and how many guesses the user has
*/
private void setUpGame() {
canvas.reset();
hiddenWord = showNumberOfLetters();
canvas.displayWord(hiddenWord);
println(&quot;Welcome to Hangman!&quot;);
println(&quot;The word now looks like this: &quot; + hiddenWord);
println(&quot;You have &quot; + guessCounter + &quot; guesses left.&quot;);
}

//Generates a random word selected from the HangmanLexicon
private String pickWord() {
hangmanWords = new HangmanLexicon();
int randomWord = rgen.nextInt(0, (hangmanWords.getWordCount() - 1));
String pickedWord = hangmanWords.getWord(randomWord);
return pickedWord;
}

//Shows how many letters there are in the word as part of game setup
private String showNumberOfLetters() {
String result = &quot;&quot;;
for(int i = 0; i&lt; word.length(); i++) {
result = result + &quot;-&quot;;
}
return result;
}

private void playGame() {
while(guessCounter &gt; 0) {
while (true) {
if(getChar.length() &gt; 1) {
getChar = readLine(&quot;You can only guess one letter at a time. Try again: &quot;);
}
if(getChar.length() == 1) break;
}
ch = getChar.charAt(0);
if(Character.isLowerCase(ch)) {
ch = Character.toUpperCase(ch);
}
letterCheck();
if (hiddenWord.equals(word)) {
println(&quot;You guessed the word: &quot; + word);
println(&quot;You win&quot;);
break;
}
println(&quot;The word now looks like this: &quot; + hiddenWord);
println(&quot;You have &quot; + guessCounter + &quot; guesses left.&quot;);

}
if (guessCounter == 0) {
println(&quot;You're completely hung.&quot;);
println(&quot;The word was:&quot; + word);
println(&quot;You lose.&quot;);
}
}

//updates the hiddenWord if the character entered is correct
private void letterCheck() {
//checks to see if the guessed letter is in the word
if(word.indexOf(ch) == -1) {
println(&quot;There are no &quot; + ch + &quot;'s in the word&quot;);
guessCounter--;
incorrectLetters = incorrectLetters + ch;
canvas.noteIncorrectGuess(incorrectLetters);
}
if(word.indexOf(ch) != -1) {
println(&quot;The guess is correct.&quot;);
}
//goes through each of the letters in the word and checks if it matches the guessed letter,
//if it's a match, updates the hidden word to reveal the position of the guessed letter
for(int i = 0; i &lt; word.length(); i++) {
if (ch == word.charAt(i)) {
if (i &gt; 0) {
hiddenWord = hiddenWord.substring(0, i) + ch + hiddenWord.substring(i + 1);
}
if(i == 0) {
hiddenWord = ch + hiddenWord.substring(1);
}
canvas.displayWord(hiddenWord);
}
}
}

public void init() {
canvas = new HangmanCanvas();
}
}
```

The solution to the Hangman Canvas part of the problem is as follows:

```/*
* File: HangmanCanvas.java
* ------------------------
* This file keeps track of the Hangman display.
*/

import acm.graphics.*;

public class HangmanCanvas extends GCanvas {

/** Resets the display so that only the scaffold appears */
public void reset() {
drawScaffold();
}

private void drawScaffold() {
double scaffoldTopX = getWidth()/2 - UPPER_ARM_LENGTH;
double scaffoldBottomY = scaffoldTopY + SCAFFOLD_HEIGHT;
GLine scaffold= new GLine (scaffoldTopX, scaffoldTopY, scaffoldTopX, scaffoldBottomY);
double beamRightX = scaffoldTopX + BEAM_LENGTH;
GLine beam = new GLine(scaffoldTopX, scaffoldTopY, beamRightX, scaffoldTopY);
double ropeBottomY = scaffoldTopY + ROPE_LENGTH;
GLine rope = new GLine (beamRightX, scaffoldTopY, beamRightX, ropeBottomY);
}

/**
* Updates the word on the screen to correspond to the current
* state of the game.  The argument string shows what letters have
* been guessed so far; unguessed letters are indicated by hyphens.
*/
public void displayWord(String word) {
//adds the label with the correctly guessed letters
double x = getWidth()/4;
GLabel unGuessedWord = new GLabel(word, x, y);
unGuessedWord.setFont(&quot;Halvetica-24&quot;);
//removes the latest hidden word and replaces it
//with the newest one with the new updated guessed letter
if (getElementAt(x,y) != null){
remove(getElementAt(x,y));
}

}

/**
* Updates the display to correspond to an incorrect guess by the
* user.  Calling this method causes the next body part to appear
* on the scaffold and adds the letter to the list of incorrect
* guesses that appears at the bottom of the window.
*/
public void noteIncorrectGuess(String incorrectGuesses) {
//adds the label with the incorrect letters
double x = getWidth()/4;
GLabel incorrectLetters = new GLabel(incorrectGuesses, x, y);
//checks to see if there is already a list of incorrect letters in place,
//and removes them before adding the new string, with the latest letter
if(getElementAt(x,y) != null) {
remove(getElementAt(x,y));
}
//checks how many incorrect guessed letters there are
//and draws the next appropriate body part of the hangman
if(incorrectGuesses.length() == 1) {
}
if(incorrectGuesses.length() == 2) {
drawBody();
}
if(incorrectGuesses.length() == 3) {
drawLeftArm();
}
if(incorrectGuesses.length() == 4) {
drawRightArm();
}
if(incorrectGuesses.length() == 5) {
drawLeftLeg();
}
if(incorrectGuesses.length() == 6) {
drawRightLeg();
}
if(incorrectGuesses.length() == 7) {
drawLeftFoot();
}
if(incorrectGuesses.length() == 8) {
drawRightFoot();
}
}

}

private void drawBody() {
double topY = getHeight()/2 - BODY_LENGTH;
double bottomY = topY + BODY_LENGTH;
GLine body = new GLine (x, topY, x, bottomY);
}

private void drawLeftArm() {
double upperArmHeightY = getHeight()/2 - BODY_LENGTH + ARM_OFFSET_FROM_HEAD;
GLine upperLeftArm = new GLine (armStartX, upperArmHeightY, armEndX, upperArmHeightY);
double lowerArmEndY = upperArmHeightY + LOWER_ARM_LENGTH;
GLine lowerLeftArm = new GLine (armEndX, upperArmHeightY, armEndX, lowerArmEndY);
}

private void drawRightArm() {
double upperArmHeightY = getHeight()/2 - BODY_LENGTH + ARM_OFFSET_FROM_HEAD;
GLine upperRightArm = new GLine (armStartX, upperArmHeightY, armEndX, upperArmHeightY);
double lowerArmEndY = upperArmHeightY + LOWER_ARM_LENGTH;
GLine lowerRightArm = new GLine (armEndX, upperArmHeightY, armEndX, lowerArmEndY);
}

private void drawLeftLeg() {
double hipEndX = hipStartX - HIP_WIDTH;
double hipHeightY = getHeight()/2;
GLine leftHip = new GLine(hipStartX, hipHeightY, hipEndX, hipHeightY);
double leftLegY = hipHeightY + LEG_LENGTH;
GLine leftLeg = new GLine(hipEndX, hipHeightY, hipEndX, leftLegY);

}

private void drawRightLeg() {
double hipEndX = hipStartX + HIP_WIDTH;
double hipHeightY = getHeight()/2;
GLine leftHip = new GLine(hipStartX, hipHeightY, hipEndX, hipHeightY);
double leftLegEndY = hipHeightY + LEG_LENGTH;
GLine leftLeg = new GLine(hipEndX, hipHeightY, hipEndX, leftLegEndY);
}

private void drawLeftFoot() {
double footEndX = footStartX - FOOT_LENGTH;
double footHeightY = getHeight()/2 + LEG_LENGTH;
GLine leftFoot = new GLine(footStartX, footHeightY, footEndX, footHeightY);
}

private void drawRightFoot() {
double footEndX = footStartX + FOOT_LENGTH;
double footHeightY = getHeight()/2 + LEG_LENGTH;
GLine rightFoot = new GLine(footStartX, footHeightY, footEndX, footHeightY);
}

/* Constants for the simple version of the picture (in pixels) */
private static final int SCAFFOLD_HEIGHT = 360;
private static final int BEAM_LENGTH = 144;
private static final int ROPE_LENGTH = 18;
private static final int BODY_LENGTH = 144;
private static final int ARM_OFFSET_FROM_HEAD = 28;
private static final int UPPER_ARM_LENGTH = 72;
private static final int LOWER_ARM_LENGTH = 44;
private static final int HIP_WIDTH = 36;
private static final int LEG_LENGTH = 108;
private static final int FOOT_LENGTH = 28;

}
```

Finally, the Hangman Lexicon solution is as follows:

```/*
* File: HangmanLexicon.java
* -------------------------
* This file contains a stub implementation of the HangmanLexicon
* class that you will reimplement for Part III of the assignment.
*/

import acm.util.*;
import java.io.*;
import java.util.*;

public class HangmanLexicon {

private ArrayList  wordList = new ArrayList  ();

public HangmanLexicon() {
//adds the individual words in the file to the array list
try {
while(true) {
if(line == null) break;
}
hangmanWords.close();
} catch (IOException ex) {
throw new ErrorException(ex);
}
}

/** Returns the word at the specified index. */
public String getWord(int index) {
return wordList.get(index);
}

/** Returns the number of words in the lexicon. */
public int getWordCount() {
return wordList.size();
}
}
```

Enjoy the article? Join over 20,000+ Swift developers and enthusiasts who get my weekly updates.

• aryan

&gt

• aryan

&lt