Computer Science 132
Introduction To Computing II

Dickinson College
Fall Semester 2001
Grant Braught


import tio.*;

/**
 * TowersOfHanoi.java - 
 *   Recursive program that will solve a Towers
 *   of Hanoi puzzle.
 *
 * @author Grant William Braught
 * @author Dickinson College
 * @version 2/11/2000
 */
public class TowersOfHanoi {
    public static void main (String[] args) {
	
	char fromPeg, toPeg, auxPeg;
	int numDisks;

	// Display an introductory screen.
	printIntro();

	// Get from the user or determine all of the
	// information regarding the puzzle.
	fromPeg = getFromPeg();
	toPeg = getToPeg(fromPeg);
	auxPeg = findAuxPeg(fromPeg, toPeg);
	numDisks = getNumDisks();
	
	System.out.println();
	System.out.println("Move\tFrom\tTo");
	System.out.println("Disk\tPeg\tPeg");
	System.out.println("--------------------");

	// Solve the puzzle.
	towers(fromPeg,toPeg,auxPeg,numDisks);
    }

    /**
     * Recursively solve the towers of Hanoi puzzle by
     * moving numDisks disks from the fromPeg to the 
     * toPeg using the augPeg.
     *
     * @param fromPeg the peg from which the disks need
     *                to be moved.
     * @param toPeg the peg to which the disks are to be
     *              moved.
     * @param auxPeg the other peg.
     * @param numDisks the number of disks to be moved from
     *                 the from peg to the to peg.
     */
    static void towers(char fromPeg, char toPeg, char auxPeg,
		       int numDisks) {

	// Base Case:
	//   If there is only one disk just move it from
	//   the fromPeg to the toPeg and we're done!
	if (numDisks == 1) {
	    System.out.println(numDisks + "\t" +
			       fromPeg + "\t" + 
			       toPeg);	       
	}
	// Recursive Case:
	//   This takes three steps...
	//     1. Move the numDisks-1 disks to the auxPeg.
	//     2. Move the last disk from the fromPeg to the toPeg.
	//     3. Move the numDisk-1 disks from the auxPeg to the toPeg.
	else {
	    
	    // Step 1: Move numDisks-1 disks from the fromPeg
	    //         to the auxPeg using the toPeg.
	    towers(fromPeg, auxPeg, toPeg, numDisks-1);

	    // Step 2: Move 1 disk from the fromPeg to
	    //         the toPeg.
	    towers(fromPeg, toPeg, auxPeg, 1);

	    // Step 3: Move the numDisks-1 disks from the auxPeg
	    //         to the toPeg using the fromPeg.
	    towers(auxPeg, toPeg, fromPeg, numDisks-1);
	}
    }

    /**
     * Read the name of the peg that is to
     * contain the disks at the start of the 
     * game.  I.e this is the peg from which
     * the disks should be moved.
     * 
     * @return a character representing the
     *         peg containing the disks at the
     *         start of the game.
     */
    static char getFromPeg() {
	char thePeg = 'z';
	
	// Prompt the user for a peg until they enter a valid
	// peg.
	while (thePeg != 'a' && thePeg != 'A' &&
	       thePeg != 'b' && thePeg != 'B' &&
	       thePeg != 'c' && thePeg != 'C') {
	    System.out.print("Enter the peg that holds the disks " +
			       "[A, B, C]: ");
	    thePeg = Console.in.readChar();
	    
	    // The enter key counts as a character
	    // when using readChar.  So we'll read that
	    // here and just throw it away.  Otherwise
	    // it will be read by the next read operation.
	    Console.in.readChar();
	}

	return thePeg;
    }

    /**
     * Read the name of the peg that the disks
     * should end up on at the end of the game.
     * I.e. this is the peg to which the disks
     * should be moved.  This peg must be 
     * different than the toPeg.
     *
     * @param fromPeg the peg containing the disks
     *                at the start of the game.
     *
     * @return a character representing the peg that
     *         should hold the disks at the end of
     *         the game.
     */
    static char getToPeg(char fromPeg) {
	char thePeg = 'z';

	// Prompt the user for a peg until they enter a valid
	// peg.
	while (thePeg != 'a' && thePeg != 'A' &&
	       thePeg != 'b' && thePeg != 'B' &&
	       thePeg != 'c' && thePeg != 'C' ||
	       thePeg == fromPeg) {

	    // Probably a better way to do this would be to only
	    // offer the choice of the two pegs that are not the
	    // fromPeg!  I'll leave that as an exercise for you.
	    System.out.print("Enter the peg to move the disks to " +
			       "[A, B, C]: ");
	    thePeg = Console.in.readChar();

	    // The enter key counts as a character
	    // when using readChar.  So we'll read that
	    // here and just throw it away.  Otherwise
	    // it will be read by the next read operation.
	    Console.in.readChar();
	}

	return thePeg;
    }

    /**
     * Find and return the name of the aux. peg 
     * from the  names of the fromPeg and the toPeg.
     *
     * @param fromPeg the peg containing the disks
     *                at the start of the game.
     * @param toPeg the peg containing the disks
     *              at the end of the game.
     *
     * @return a character representing the the 
     *         aux. peg.
     */
    static char findAuxPeg(char fromPeg, char toPeg) {
	char auxPeg;
	
	// Is peg A being used?
	if (fromPeg == 'a' || fromPeg == 'A' ||
	    toPeg == 'a' || toPeg == 'A') {
	    
	    // Is peg B being used?
	    if (fromPeg == 'b' || fromPeg == 'B' ||
		toPeg == 'b' || toPeg == 'B') {

		// The pegs A and B are used so 
		// auxPeg must be C.
		auxPeg = 'C';
	    }
	    else {
		// The pegs A and C are used so
		// auxPeg must be B.
		auxPeg = 'B';
	    }
	}
	else {
	    // peg A is not used so the auxPeg
	    // must be A.
	    auxPeg = 'A';
	}

	return auxPeg;
    }

    /**
     * Ask the user for the number of disks in the game.
     * The number of disks must be greater than 0.
     *
     * @return the number of disks used in the game.
     */
    static int getNumDisks() {
	int numDisks = -1;

	while (numDisks <= 0) {
	    System.out.print("Enter the number of disks [ > 0]: ");
	    numDisks = Console.in.readInt();
	}

	return numDisks;
    }

    /**
     * Print an introductory screen to the 
     * towers of Hanoi solver.
     */
    static void printIntro() {
	System.out.println("Towers of Hanoi!\n\n");
	System.out.println("     |      |      |");
	System.out.println("1    +      |      |");
	System.out.println("2   -+-     |      |");
	System.out.println("3  --+--    |      |");
	System.out.println("4 ---+---   |      |");
	System.out.println("=======================");
	System.out.println("     A      B      C\n");
    }
}




TowersOfHanoi.java : javadoc documentation.