Computer Science 120
Introduction to Programming

Spring 2012, Siena College

Hangman Demo

A working demo of Hangman will appear below. Click inside the applet to interact with it.



Hangman BlueJ Project

Click here to download a BlueJ project for Hangman.


Hangman Source Code

The Java source code for Hangman is below. Click on a file name to download it.


Hangman.java

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

/* $Id: Hangman.java 1608 2011-04-23 01:17:26Z terescoj $ */

/**
 * Example Hangman: play a text-based hangman
 *
 * @author Jim Teresco, Siena College, CSIS 120, Spring 2011
 *
 */

public class Hangman {

    // See: http://jbauman.com/aboutgsl.html
    private static final String DICTIONARY_FILE = "gsl.txt";
    // for a ridiculously large dictionary use "dictionary.txt"
    
    // minimum length of a word to consider
    private static final int MIN_WORD_LENGTH = 3;
    
    // largest number of misses allowed to be set
    private static final int MAX_MISSES = 26;
    
    public static void main(String[] args) {
        
        System.out.println("Welcome to Hangman!");
        
        // check for debug mode
        boolean debug = args.length > 1 && args[0].equals("debug");
        
        // read in the data from the dictionary to an ArrayList
        ArrayList<String> words = new ArrayList<String>();
        
        // first, open the file and create a Scanner to read it in
        Scanner wordScan = null;
        try {
            wordScan = new Scanner(new File(DICTIONARY_FILE));
        }
        catch (FileNotFoundException e) {
            System.err.println(e);
            System.exit(1);
        }
        
        // read the contents of the file one word at a time, skipping
        // over words that are too short for use by hangman.
        while (wordScan.hasNext()) {
            String nextWord = wordScan.next();
            if (nextWord.length() >= MIN_WORD_LENGTH) {
                words.add(nextWord);
            }
        }
        
        if (debug) {
            System.out.println("Dictionary contains " + words.size() + " words");
        }
        
        // create a random number generator to pick a word
        // this is how you can get a Random generator without
        // objectdraw's RandomIntGenerator
        Random r = new Random();

        // create a Scanner to read keyboard input
        Scanner keyboard = new Scanner(System.in);
        
        // find out the number of guesses allowed before a hangman
        int missesAllowed = 0;
        while ((missesAllowed < 1) || missesAllowed > MAX_MISSES) {
            System.out.print("How many guesses before a hangman? ");
            missesAllowed = keyboard.nextInt();
        }
        
        boolean gameOver = false;
        while (!gameOver) {
            
            // pick the next word
            // note: r.nextInt(n) returns an int between 0 and n-1
            String theWord = words.get(r.nextInt(words.size()));
            
            if (debug) {
                System.out.println("The word is... " + theWord);
            }
            boolean wordOver = false;
            int missesLeft = missesAllowed;
            ArrayList<Character> guessed = new ArrayList<Character>();
            
            // keep looping until the word has been guessed or too
            // many incorrect guesses have been made
            while (!wordOver) {
                
                showGuessed(theWord, guessed);
                System.out.println("\nYou have " + missesLeft + " incorrect guesses remaining");
                System.out.println(maskWord(theWord, guessed));
                boolean guessOK = false;
                String guess = null;
                while (!guessOK) {
                    System.out.print("Your guess? ");
                    guess = keyboard.next().toLowerCase();
                    // add this guess to our list of guessed letters
                
                    if (guessed.contains(guess.charAt(0))) {
                        System.out.println("You already guessed that!");
                    }
                    else {
                        // insert the guess into the list of guessed
                        // letters in alphabetical order
                        int pos = 0;
                        while (pos < guessed.size() &&
                               guessed.get(pos) < guess.charAt(0)) {
                                   pos++;
                                }
                        guessed.add(pos, guess.charAt(0));
                        guessOK = true;
                    }
                }
                // is the first letter of the response in the word?
                if (theWord.indexOf(guess.substring(0,1)) == -1) {
                    // not in the word
                    System.out.println("The letter " + guess.charAt(0) + " is not in the word.");
                    missesLeft--;
                    if (missesLeft == 0) {
                        System.out.println("Too bad!  HANGMAN!  The word was: " + theWord);
                        wordOver = true;
                    }
                }
                else {
                    // it is in the word
                    System.out.println("Good - you have a match.");
                    if (theWord.equals(maskWord(theWord, guessed))) {
                        System.out.println("You got it!  The word was: " + theWord);
                        wordOver = true;
                    }
                }
            }
            
            System.out.print("Play again? ");
            String response = keyboard.next();
            gameOver = response.equalsIgnoreCase("no");
            
        }
        
        System.out.println("Thanks for playing.");
    }
    
    /**
     * return a String with the characters not in the list of characters
     * replaced with _ characters.
     * 
     * @param word the word to be masked
     * @param letters the ArrayList of characters to be revealed
     * @return the word with all characters not in letters replaced by _'s
     */
    private static String maskWord(String word, ArrayList<Character> letters) {
        
        String answer = "";
        for (int i = 0; i<word.length(); i++) {
            if (letters.contains(word.charAt(i))) {
                answer = answer + word.charAt(i);
            }
            else {
                answer = answer + "_";
            }
        }
        return answer;
    }
    
    /**
     * Show the list of guessed letters that were not found in the word.
     * 
     * @param theWord the word being guessed
     * @param letters the ArrayList of characters guessed so far
     */
    private static void showGuessed(String theWord, ArrayList<Character> letters) {
        
        System.out.print("Guessed: ");
        for (int i = 0; i<letters.size(); i++) {
            if (theWord.indexOf(letters.get(i)) == -1) {
                System.out.print(letters.get(i) + " ");
            }
        }
        System.out.println();
    }
 }