CH8Solutions PDF
CH8Solutions PDF
Solutions
Multiple Choice True/False
Solutions Solutions
1. b 1. T
2. c 2. T
3. c 3. F
4. c 4. T
5. b 5. F
6. a 6. F
7. e 7. T
8. d 8. F
9. e 9. T
10. a 10. F
A valid Java Identifier is a Java Letter followed by zero or more Java Identifier
Substrings.
A Java Identifier Substring consists of zero or more valid Java Letters or zero or
more Java Digits.
A Java Letter is any of the 26 English alphabetic characters in both uppercase and
lowercase, the $ and the _ (underscore) characters, as well as alphabetic
characters from other languages.
A Java Digit includes the digits 0 through 9.
8.2. Write a recursive definition of xy (x raised to the power y), where x and y are integers and y > 0.
If y = 0, then xy = 1.
otherwise x = x * x(y-1).
y
8.3. Write a recursive definition of i * j (integer multiplication), where i > 0. Define the multiplication process in
terms of integer addition. For example, 4 * 7 is equal to 7 added to itself 4 times.
If i = 1, then i * j = j
otherwise i * j = j + (i-1) * j
8.4. Write a recursive definition of the Fibonacci numbers. The Fibonacci numbers are a sequence of integers, each
of which is the sum of the previous two numbers. The first two numbers in the sequence are 0 and 1. Explain
why you would not normally use recursion to solve this problem.
Fib(0) = 0
Fib(1) = 1
You would not normally use recursion to solve this problem since a Fibonacci
number less than Fib(j-1) would be calculated at least twice in order to calculate
Fib(j). The recalculation of each such number would lead to the further
recalculation of other Fibonacci numbers with the accompanying inefficiency.
8.5. Modify the method that calculates the sum of the integers between 1 and N shown in this chapter. Have the
new version match the following recursive definition: The sum of 1 to N is the sum of 1 to (N/2) plus the sum
of (N/2 + 1) to N. Trace your solution using an N of 7.
8.6. Write a recursive method that returns the value of N! (N factorial) using the definition given in this chapter.
Explain why you would not normally use recursion to solve this problem.
if (num == 1)
result = 1;
else
result = num * factorial (num - 1);
return result;
}
You would not normally use recursion to solve this problem because it can be done
more efficiently using iteration and because the recursive solution it no more
intuitive than the iterative solution.
8.7. Write a recursive method to reverse a string. Explain why you would not normally use recursion to solve this
problem.
return result;
}
}
8.8. Design or generate a new maze for the MazeSearch program in this chapter and rerun the program. Explain the
processing in terms of your new maze, giving examples of a path that was tried but failed, a path that was
never tried, and the ultimate solution.
A new maze could be generated with nested for loops which randomly place either a
1 or a 0 in each cell of a two-dimensional array. Since the likelihood of
8.9. Annotate the lines of output of the SolveTowers program in this chapter to show the recursive steps.
Note the symmetry about the line where a call is made with numDisks = 4.
8.10. Produce a chart showing the number of moves required to solve the Towers of Hanoi puzzle using the
following number of disks: 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, and 25.
Disks Moves
2: 3
3: 7
4: 15
5: 31
6: 63
7: 127
8: 255
9: 511
10: 1023
15: 32767
20: 1,048,575
25: 33,554,431
8.11. Describe a strategy for choosing a pivot value in quick sort so that the list will always be partitioned into two
equal halves. Does your strategy change the time efficiency of quick sort?
In order to partition the list into two equal halves, the pivot value would have
to be the median of the list. One way to find the median is the sort the list
using insertion sort and take the value in the middle of the list. This would
certainly affect the time efficiency!
8.12. How many line segments are used to construct a Koch snowflake of order N? Produce a chart showing the
number of line segments that make up a Koch snowflake for orders 1 through 9.
8.1 PalindromeTester
//********************************************************************
// PalindromeTester.java Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.1
//
// Modifies code from Chapter 3 to use recursion to identify a
// palindrome
//********************************************************************
import java.util.Scanner;
public class PalindromeTester {
private String testString;
//-----------------------------------------------------------------
// Converts a string to correct format; removes all characters
// except for number and digits
//-----------------------------------------------------------------
private String convertString(String str)
{
StringBuffer convertedString = new StringBuffer();
convertedString.append(c);
}
/*
String.substring(first, last) includes first char up to but not
including last char. Adding a dummy character on the end of the
string prevents an ArrayIndexOutOfBounds exception when the
isPalindrome()
methods uses String.substring() to access the entire string
*/
convertedString.append('*');
return convertedString.toString();
}
//-----------------------------------------------------------------
// Determines if the string is a palindrome.
//-----------------------------------------------------------------
public boolean isPalindrome()
{
return testPalindrome(0, testString.length()-1);
}
//-----------------------------------------------------------------
// Method determines if the string is a palindrome by
// recursively testing smaller substrings of the string.
//-----------------------------------------------------------------
private boolean testPalindrome(int subStringStart, int subStringEnd)
{
// base case
if (subStringEnd - subStringStart <= 1)
return true;
// compare the first and last characters
if (testString.charAt(subStringStart) != testString.charAt(subStringEnd-
1))
return false;
System.out.println();
System.out.print ("Test another palindrome (y/n)? ");
another = scan.nextLine();
}
}
8.2 DivisorCalc
//********************************************************************
// DivisorCalc.java Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.2
//
// Contains a static method to calculate the greatest common
// divisor of two positive integers.
//********************************************************************
8.3 Maze
//********************************************************************
// Maze.java Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.3
//
// Represents a maze of characters. The goal is to get from the
// top left corner to the bottom right, following a path of 1s.
// Prints the path of the final solution as it is discoverd.
//********************************************************************
//-----------------------------------------------------------------
// Attempts to recursively traverse the maze. Inserts special
// characters indicating locations that have been tried and that
// eventually become part of the solution.
//-----------------------------------------------------------------
private boolean traverse (int row, int column)
{
boolean done = false;
if (valid (row, column))
{
grid[row][column] = TRIED; // this cell has been tried
if (row == grid.length-1 && column == grid[0].length-1)
done = true; // the maze is solved
else
{
done = traverse (row+1, column); // down
if (!done)
done = traverse (row, column+1); // right
if (!done)
done = traverse (row-1, column); // up
if (!done)
done = traverse (row, column-1); // left
}
if (done) // this location is part of the final path
{
grid[row][column] = PATH;
System.out.println("[" + row + "], [" + column + "]");
}
}
return done;
}
//-----------------------------------------------------------------
// Determines if a specific location is valid.
//-----------------------------------------------------------------
private boolean valid (int row, int column)
{
boolean result = false;
return result;
}
//-----------------------------------------------------------------
// Returns the maze as a string.
//-----------------------------------------------------------------
public String toString ()
{
String result = "\n";
for (int row=0; row < maze.length; row++)
{
for (int column=0; column < maze[row].length; column++)
8.3 MazeSearch
//********************************************************************
// MazeSearch.java Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.3
//
// Demonstrates recursion.
//********************************************************************
public class MazeSearch
{
//-----------------------------------------------------------------
// Creates a new maze, prints its original form, attempts to
// solve it, and prints out its final form.
//-----------------------------------------------------------------
public static void main (String[] args)
{
Maze labyrinth = new Maze();
System.out.println (labyrinth);
System.out.println("\nTraversal path [row],[column]");
System.out.println (labyrinth);
}
}
8.4 Maze3D
//********************************************************************
// Maze3D.java Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.4
//
// Represents a 3D maze of characters. The goal is to get from the
// top left near corner to the bottom right far corner, following a path of 1s.
// Prints the path of the final solution as it is discoverd.
//********************************************************************
//-----------------------------------------------------------------
// Creates a working copy of the maze to compute the final solution.
// The original maze is not modified. Calls traverse to recursively
// traverse the maze.
//-----------------------------------------------------------------
public boolean traverseMaze (int row, int column, int page)
{
// make copy of maze
grid = new int[maze.length][maze[0].length][maze[0][0].length];
for (int i = 0; i < maze.length; i++)
for (int j = 0; j < maze[i].length; j++)
for (int k = 0; k < maze[i][j].length; k++)
grid[i][j][k] = maze[i][j][k];
return traverse(row, column, page);
}
//-----------------------------------------------------------------
// Attempts to recursively traverse the maze. Inserts special
// characters indicating locations that have been tried and that
// eventually become part of the solution.
//-----------------------------------------------------------------
private boolean traverse (int row, int column, int page)
{
boolean done = false;
8.4 Maze3Dsearch
//********************************************************************
// Maze3DSearch.java Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.4
//
// Creates a random 3D maze and attempts to solve it. Repeats until
// a maze is solved and prints out the traversal steps.
//********************************************************************
import java.util.Random;
//-----------------------------------------------------------------
// Generates a random 3D maze
//-----------------------------------------------------------------
public static int[][][] generateRandom3DMaze()
{
Random gen = new Random();
int[][][] maze = new int[MAX_SIZE][MAX_SIZE][MAX_SIZE];
8.5 MirroredPictures
//********************************************************************
// MirroredPictures.java Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.5
//
// Demonstrates the use of recursion.
//********************************************************************
import java.applet.Applet;
import java.awt.*;
public class MirroredPictures extends Applet
{
private final int APPLET_WIDTH = 320;
private final int APPLET_HEIGHT = 320;
private final int MIN = 20; // smallest picture size
private Image world, everest, goat;
//-----------------------------------------------------------------
// Loads the images.
//-----------------------------------------------------------------
public void init()
{
world = getImage (getDocumentBase(), "world.gif");
everest = getImage (getDocumentBase(), "everest.gif");
goat = getImage (getDocumentBase(), "goat.gif");
8.6 NonAttackingQueens
//********************************************************************
// NonAttackingQueens.java Author: Lewis/Loftus/Cocking
//
//-----------------------------------------------------------------
// Returns true if a queen queenNumber can be placed in column
//-----------------------------------------------------------------
boolean canPlace(int queenNumber, int column)
{
for (int row = 0; row < queenNumber; row++) // check all rows above
queenNumber row
{
if (queens[row] == column) // in the same column
return false;
if (Math.abs(queens[row] - column) == Math.abs(row - queenNumber))
// same diagonal
return false;
}
return true;
}
//-----------------------------------------------------------------
// Starting with the row represented by queenNumber, find all correct
// placements in the row and below the row.
//-----------------------------------------------------------------
public void solve(int queenNumber)
{
for (int column = 0; column < NUM_QUEENS; column++) // iterate through
all columns
{
if (canPlace(queenNumber, column)) // queen can be placed in current
column
{
queens[queenNumber] = column; // place queen in current column
//-----------------------------------------------------------------
// Prints a grid showing the postion of the queens on the chessboard.
// Queen = X
// Empty space = O
//-----------------------------------------------------------------
private void printSolution()
{
int column;
for (int row=0; row<NUM_QUEENS; row++)
{
for (column = 0; column<NUM_QUEENS; column++)
if (queens[row] == column)
System.out.print(" X");
else
System.out.print(" 0");
System.out.print("\n");
}
System.out.println("\n-----------------------");
}
8.7 BlurbGenerator
//********************************************************************
// BlurbGenerator.java Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.7
//
// Generates random Blurbs using recursion
//********************************************************************
import java.util.Scanner;
import java.util.Random;
public class BlurbGenerator {
Random chooser;
public BlurbGenerator()
{
chooser = new Random();
}
//-----------------------------------------------------------------
// Recursively generates a random Whoozit 'y' string.
// A Whoozit 'y' string is zero or more 'y's
//-----------------------------------------------------------------
private String getWhoozitYs()
{
StringBuffer y = new StringBuffer();
y.append("y");
return y.toString();
}
//-----------------------------------------------------------------
// Generates a random Whoozit.
2007 Pearson Education
S 196 Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions
//-----------------------------------------------------------------
// Generates a random Whatzit.
// A Whatzit is a 'q' followed by either a 'z' or a 'd', followed
// by a Whoozit.
//-----------------------------------------------------------------
private String getWhatzit()
{
StringBuffer whatzit = new StringBuffer();
whatzit.append("q");
boolean z = chooser.nextBoolean();
if (z)
whatzit.append("z");
else
whatzit.append("d");
whatzit.append(getWhoozit());
return whatzit.toString();
}
//-----------------------------------------------------------------
// Recursively generates a string of one or more Whatzits.
//-----------------------------------------------------------------
private String getMultipleWhatzits()
{
StringBuffer whatzits = new StringBuffer();
whatzits.append(getWhatzit());
boolean stop = chooser.nextBoolean();
if (!stop)
whatzits.append(getMultipleWhatzits());
else
return whatzits.toString();
return whatzits.toString();
}
//-----------------------------------------------------------------
// Generates a random Blurb.
// A Blurb is a Whoozit followed by one or more Whatzits
//-----------------------------------------------------------------
public String generateBlurb()
{
StringBuffer blurb = new StringBuffer();
blurb.append(getWhoozit());
blurb.append(getMultipleWhatzits());
return blurb.toString();
}
8.8 BlurbParser
//********************************************************************
// BlurbParser.java Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.8
//
// Parses a string using recursion and determines if
// the string is a valid Blurb,
//********************************************************************
import java.util.Scanner;
// Parses a Blurb.
// A Blurb is a Whoozit followed by one or more Whatzits
//-----------------------------------------------------------------
public boolean isABlurb(String aString)
{
return parseWhoozit(aString);
}
public static void main (String args[])
{
BlurbParser parser = new BlurbParser();
Scanner scan = new Scanner (System.in);
String another = "y";
while (another.equalsIgnoreCase("y"))
{
System.out.println("Enter a Blurb:");
String blurb = scan.nextLine();
if (parser.isABlurb(blurb))
System.out.println(blurb + " IS a valid Blurb");
else
System.out.println(blurb + " is NOT a valid Blurb");
System.out.println("Parse another Blurb (y/n/)?");
another = scan.nextLine();
}
}
8.9 PascalTriangle
//********************************************************************
// PascalTriangle.java Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.9
//
// Determines and prints the Nth line of Pascal's Triangle
//********************************************************************
import java.util.Scanner;
//-----------------------------------------------------------------
// Creates an new PascalTriangle
//-----------------------------------------------------------------
public PascalTriangle()
{
rowNumber = 1;
}
//-----------------------------------------------------------------
// Creates a new PascalTriangle with the row number n
//-----------------------------------------------------------------
public PascalTriangle(int n)
{
setRow(n);
}
//-----------------------------------------------------------------
// Sets the row of the triangle to n. If n is less than 1, sets
// row to 1
2007 Pearson Education
Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions S 199
//-----------------------------------------------------------------
public void setRow(int n)
{
if (n < 1)
rowNumber = 1;
else
rowNumber = n;
}
//-----------------------------------------------------------------
// Returns the row number setting
//-----------------------------------------------------------------
public int getRow()
{
return rowNumber;
}
//-----------------------------------------------------------------
// Recursively computes successive rows of Pascal's triangle
// until the Nth row (represented by the variable rowNumber) is
// reached.
//-----------------------------------------------------------------
private void expand(int[] row)
{
//base case
if (rowCount >= rowNumber)
return;
newRow = new int[row.length+1];
newRow[0] = 1;
newRow[row.length] = 1;
rowCount ++;
expand(newRow);
return;
}
//-----------------------------------------------------------------
// Computes and returns the Nth row (represented by
// the variable rowNumber) of Pascal's Triangle.
//-----------------------------------------------------------------
public int[] computeRow()
{
rowCount = 1;
newRow = new int[rowCount];
newRow[0] = 1;
expand(newRow);
return newRow;
}
8.10 RecursiveSorts
//********************************************************************
// RecursiveSorts.java Author: Lewis/Loftus/Cocking
//
// Implements a quick sort of doubles
//********************************************************************
public class RecursiveSorts
{
//-----------------------------------------------------------------
// Sorts the specified array of doubles using quick sort.
//-----------------------------------------------------------------
public static void quickSort (double[] numbers)
{
doQuickSort(numbers, 0, numbers.length - 1);
}
//-----------------------------------------------------------------
// Recursively sorts the portion of the given array beginning
// at start and ending at end.
//-----------------------------------------------------------------
private static void doQuickSort (double[] numbers, int start, int end)
{
if (start < end)
{
int middle = partition(numbers, start, end);
doQuickSort(numbers, start, middle);
doQuickSort(numbers, middle + 1, end);
}
}
//-----------------------------------------------------------------
// Partitions the array such that each value in [start, middle]
// is less than or equal to each value in [middle + 1, end].
// The index middle is determined in the procedure and returned.
//-----------------------------------------------------------------
private static int partition (double[] numbers, int start, int end)
{
double pivot = numbers[(start + end) / 2];
int i = start - 1;
int j = end + 1;
// As the loop progresses, the indices i and j move towards each other.
// Elements at i and j that are on the wrong side of the partition are
// exchanged. When i and j pass each other, the loop ends and j is
// returned as the index at which the elements are partitioned around.
while (true)
{
i = i + 1;
while (numbers[i] < pivot)
i = i + 1;
j = j - 1;
while (numbers[j] > pivot)
j = j - 1;
if (i < j)
2007 Pearson Education
Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions S 201
{
double tmp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = tmp;
}
else return j;
}
}
}
8.10 SortPrices
//********************************************************************
// SortPrices.java Author: Lewis/Loftus/Cocking
//
// Sorts an array of prices using quick sort
//********************************************************************
public class SortPrices
{
//-----------------------------------------------------------------
// Creates an array of prices, sorts them, then prints them.
//-----------------------------------------------------------------
public static void main (String[] args)
{
double[] prices = {1.99, 2.45, 23.35, 0.25, 119.99, 5.55, 19.85};
RecursiveSorts.quickSort (prices);
System.out.println();
}
}
8.11 Disk
//********************************************************************
// Disk.java Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.11
//
// Encapsulates a disk in the grapical Towers of Hanoi solution
//********************************************************************
import java.awt.Color;
import java.awt.Graphics;
class Disk
{
int diskSize;
static final int HEIGHT = 20;
static final int WIDTH_STEP = 20;
static final int ARC_WIDTH = 5;
static final int ARC_HEIGHT = 5;
static final Color[] DISK_COLORS = {
Color.black,
Color.red,
Color.blue,
Color.yellow,
Color.green,
Color.orange,
Color.magenta,
Color.gray,
Color.pink
};
//-----------------------------------------------------------------
// Creates a disk of specified size
//-----------------------------------------------------------------
Disk(int size)
{
diskSize = size;
}
//-----------------------------------------------------------------
// Returns the size of the disk
//-----------------------------------------------------------------
int getSize()
{
return diskSize;
}
//-----------------------------------------------------------------
// Returns the width of the disk to be drawn on the screen
//-----------------------------------------------------------------
int getScreenWidth()
{
return diskSize * WIDTH_STEP;
}
//-----------------------------------------------------------------
// Returns the color of the disk as indexed in DISK_COLORS
//-----------------------------------------------------------------
Color getDiskColor()
{
return DISK_COLORS[diskSize % DISK_COLORS.length];
}
//-----------------------------------------------------------------
// Draws the disk using graphics context g. Position x
// represents the x coordinate of the center of the tower,
// position y represents the top position of the disk on the tower
//-----------------------------------------------------------------
void draw(Graphics g, int x, int y)
{
int width = getScreenWidth();
int diskX = x - width / 2;
g.setColor(getDiskColor());
g.fillRoundRect(diskX, y, width, HEIGHT, ARC_WIDTH, ARC_HEIGHT);
g.setColor(Color.black);
g.drawRoundRect(diskX, y, width, HEIGHT, ARC_WIDTH, ARC_HEIGHT);
}
8.11 Tower
//********************************************************************
// Tower.java Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.11
//
// Encapsulates a tower in the grapical Towers of Hanoi solution
//********************************************************************
import java.util.Stack;
import java.awt.Color;
import java.awt.Graphics;
class Tower
2007 Pearson Education
Lewis/Loftus/Cocking, 2/e: Chapter 8 Solutions S 203
{
Stack disks;
int towerHeight;
static final int WIDTH = 10;
//-----------------------------------------------------------------
// Creates a new tower, height should be set to the max number of
// disks the tower will hold.
//-----------------------------------------------------------------
public Tower(int height)
{
disks = new Stack();
towerHeight = height;
}
//-----------------------------------------------------------------
// Adds disk to the top of the tower
//-----------------------------------------------------------------
void addDisk(Disk d)
{
disks.push(d);
}
//-----------------------------------------------------------------
// Removes the top disk from the tower
//-----------------------------------------------------------------
Disk removeDisk()
{
if (disks.empty())
return null;
else
return (Disk)disks.pop();
}
//-----------------------------------------------------------------
// Draws the tower using graphics context g. The coordinates (x,y)
// represent the bottom left corner of the tower
//-----------------------------------------------------------------
void draw(Graphics g, int x, int y)
{
// draw tower
int height = Disk.HEIGHT * towerHeight;
g.setColor(Color.black);
g.fillRect(x,y-height, WIDTH, height);
// draw disks
if (!disks.isEmpty())
{
// create a stack of disks in reverse order
Stack temp = new Stack();
while (!disks.empty())
temp.push(disks.pop());
location ++;
}
}
}
}
8.11 Move
//********************************************************************
// Move.java Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.11
//
// Encapsulates a disk move
//*********************************************************************
public class Move {
private int from;
private int to;
8.11 TowerFrame
//********************************************************************
// TowerFrame.java Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.11
//
// Main progrma to run the Graphical Towers of Hanoi
//********************************************************************
import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.event.*;
import java.awt.*;
import java.util.Hashtable;
public TowerFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
speed.setLabelTable(labelTable);
speed.setPaintLabels(true);
speed.addMouseListener(sliderHandler);
getContentPane().add(controls, BorderLayout.SOUTH);
// make disk selector
JSlider diskNum = new JSlider();
diskNum.setName("disks");
diskNum.setMinimum(TowerPanel.MIN_DISKS);
diskNum.setMaximum(TowerPanel.MAX_DISKS);
diskNum.setValue(TowerPanel.DEFAULT_NUM_DISKS);
diskNum.setBorder(new TitledBorder("Disks"));
diskNum.setMajorTickSpacing(1);
diskNum.setPaintLabels(true);
diskNum.setPaintTicks(true);
diskNum.setSnapToTicks(true);
diskNum.addMouseListener(sliderHandler);
getContentPane().add(diskNum, BorderLayout.NORTH);
pack();
}
//********************************************************************
// Represents the mouse listener class for the sliders.
//********************************************************************
class SliderListener extends MouseAdapter
{
public void mouseReleased(MouseEvent event)
{
JSlider source = (JSlider)event.getSource();
if (source.getName() == "speed")
towerViewer.setPauseTime(source.getValue());
else
if (source.getName() == "disks")
towerViewer.setNumDisks(source.getValue());
}
}
//********************************************************************
// Represents the button listener class for the buttons.
//********************************************************************
class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
JButton source = (JButton)e.getSource();
String name = source.getName();
if (name == "reset")
towerViewer.resetTowers();
else
if (name == "animate")
towerViewer.animate();
else
if (name == "user")
towerViewer.userSolve();
else
if (name == "pause")
towerViewer.stopTimer();
else
if (name == "resume")
towerViewer.resumeTimer();
}
}
8.11 TowerPanel
//********************************************************************
// TowerPanel.java Author: Lewis/Loftus/Cocking
//
// Solution to Programming Project 8.11
//
// Controls the graphical display of the Towers of Hanoi
//********************************************************************
import javax.swing.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
public class TowerPanel extends JPanel {
TowersOfHanoi towerEngine;
Tower[] towers;
int numDisks;
int pauseTime;
int firstTower;
// boolean solved;
boolean userSolve;
boolean firstTowerSelected;
ArrayList solution;
Timer animationTimer;
setBackground(Color.white);
addMouseListener(new TowerSelectListener());
2007 Pearson Education
S 208 Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions
}
//-----------------------------------------------------------------
// Overrides JPanels getPreferredSize().
//-----------------------------------------------------------------
public Dimension getPreferredSize()
{
// panel width is length of largest disk * num towers + 2 width step
between towers
int panelWidth = MAX_DISKS * Disk.WIDTH_STEP * NUM_TOWERS + 2 *
Disk.WIDTH_STEP + NUM_TOWERS;
// panel height 1.2 as tall as largest towers
int panelHeight = Disk.HEIGHT * MAX_DISKS;
panelHeight = Math.round(1.2f * (float)panelHeight);
return new Dimension(panelWidth, panelHeight);
}
//-----------------------------------------------------------------
// Draws the Towers of Hanoi.
//-----------------------------------------------------------------
public void paintComponent(Graphics g)
{
super.paintComponent(g);
int towerSpacing = getSize().width / NUM_TOWERS;
//-----------------------------------------------------------------
// Sets the amount of time in milliseconds to pause between each
// animation step. If in animation mode, resets the animation
// timer
//-----------------------------------------------------------------
public void setPauseTime(int time)
{
pauseTime = time;
if (animationTimer == null)
return;
if (userSolve) // no animation
return;
// update animation speed
if (!solution.isEmpty() && animationTimer.isRunning())
{
stopTimer();
animationTimer = new Timer(pauseTime, new UpdateAnimation());
animationTimer.start();
}
}
//-----------------------------------------------------------------
// Sets the number of disks and resets the puzzle.
//-----------------------------------------------------------------
public void setNumDisks(int num)
{
numDisks = num;
stopTimer(); // stop any animation
userSolve = false; // stop any user solution
resetTowers();
//-----------------------------------------------------------------
// Animates the current solution. Stops any user solution
// If the solution is empty, resets the towers.
//-----------------------------------------------------------------
public void animate()
{
userSolve = false; // stop user solution
stopTimer(); // temporarily stop timer
if (solution.isEmpty())
resetTowers();
// start new timer
animationTimer = new Timer(pauseTime, new UpdateAnimation());
animationTimer.start();
}
//-----------------------------------------------------------------
// Allows a user to step-by-step solve the puzzle.
// Stops any animation and starts user solution mode.
// If solution is empty, resets the towers.
//-----------------------------------------------------------------
public void userSolve()
{
stopTimer(); // stop animation
if (solution.isEmpty())
resetTowers(); // start over
userSolve = true; // check for mouse motion
}
//-----------------------------------------------------------------
// Resets the towers to current settings.
// Creates new towers, tower engine, solution, and
// redraws the screen.
//-----------------------------------------------------------------
public void resetTowers()
{
towers = new Tower[NUM_TOWERS];
for (int i=0; i<NUM_TOWERS; i++)
towers[i] = new Tower(numDisks);
//-----------------------------------------------------------------
// Resumes the animation timer, stops any user solutions
//-----------------------------------------------------------------
public void resumeTimer()
{
if (animationTimer == null)
return;
if (!animationTimer.isRunning()) // get new settings and restart
{
userSolve = false;
animationTimer = new Timer(pauseTime, new UpdateAnimation());
animationTimer.start();
}
}
//********************************************************************
// Represents the listener class for the animation timer.
//********************************************************************
class UpdateAnimation implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (!solution.isEmpty())
{
Move nextMove = (Move)solution.remove(0);
Disk d = towers[nextMove.getFrom()].removeDisk();
towers[nextMove.getTo()].addDisk(d);
repaint();
}
}
}
//********************************************************************
// Represents the mouse listener class for the panel. Used in
// the user solve mode.
//********************************************************************
class TowerSelectListener extends MouseAdapter
{
public void mousePressed(MouseEvent e)
{
if (!userSolve)
return;
if (solution.isEmpty())
return;
{
solution.remove(0);
Disk d = towers[currentMove.getFrom()].removeDisk();
towers[currentMove.getTo()].addDisk(d);
repaint();
}
else // incorrect move
{
int result =JOptionPane.showConfirmDialog(null,
TRY_AGAIN_MESSAGE,
"",
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE);
// show solution anyway?
if (result != JOptionPane.YES_OPTION)
{
solution.remove(0);
Disk d = towers[currentMove.getFrom()].removeDisk();
towers[currentMove.getTo()].addDisk(d);
repaint();
}
}
}
// display solved message
if (solution.isEmpty())
{
JOptionPane.showMessageDialog(null,
SOLVED_MESSAGE,
"",
JOptionPane.INFORMATION_MESSAGE);
}
}
}
}
8.11 TowersofHanoi
//********************************************************************
// TowersOfHanoi.java Author: Lewis/Loftus/Cocking
//
// Represents the classic Towers of Hanoi puzzle.
//********************************************************************
import java.util.ArrayList;
public class TowersOfHanoi
{
private int totalDisks;
ArrayList moves;
//-----------------------------------------------------------------
// Sets up the puzzle.
//-----------------------------------------------------------------
public TowersOfHanoi (int numDisks)
{
totalDisks = numDisks;
moves = new ArrayList();
}
//-----------------------------------------------------------------
// Performs the initial call to moveTower to solve the puzzle.
// Moves the disks from tower 1 to tower 3 using tower 2.
// Returns an ArrayList of the moves made.
//-----------------------------------------------------------------
2007 Pearson Education
S 212 Lewis/Loftus/Cocking: 2/e Chapter 8 Solutions
//-----------------------------------------------------------------
// Moves the specified number of disks from one tower to another
// by moving a subtower of n-1 disks out of the way, moving one
// disk, then moving the subtower back. Base case of 1 disk.
//-----------------------------------------------------------------
private void moveTower (int numDisks, int start, int end, int temp)
{
if (numDisks == 1)
moveOneDisk (start, end);
else
{
moveTower (numDisks-1, start, temp, end);
moveOneDisk (start, end);
moveTower (numDisks-1, temp, end, start);
}
}
//-----------------------------------------------------------------
// Stores instructions to move one disk from the specified start
// tower to the specified end tower.
//-----------------------------------------------------------------
private void moveOneDisk (int start, int end)
{
moves.add(new Move(start, end));
}
}
8.1
a.
// precondition: n > 0
public static int factorial (int n)
{
if (n == 1)
return 1;
else
return n * factorial(n-1);
}
b.
// precondition: exp >= 0
public static int power (int base, int exp)
{
if (exp == 0)
return 1;
else
return base * power(base, exp-1);
}
c.
// precondition: a has size at least 1
public static void triple (int[] a)
{
tripleHelp (a, 0);
}