Solutions
Multiple Choice
Solutions
1. b
2. c
3. c
4. c
5. b
6. a
7. e
8. d
9. e
10. a
True/False
Solutions
1. T
2. T
3. F
4. T
5. F
6. F
7. T
8. F
9. T
10. F
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).
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
where * refers to recursive multiplication as defined here and would be provided
by a method such as recursiveMult (i,j). To avoid confusing * with
conventional multiplication, the definition could be rewritten as
If i = 1, then recursiveMult (i,j) = j
otherwise, recursiveMult (i,j) = j + recursiveMult (i, j-1)
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
S 183
S 184
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.
public int sum (int num)
{
int result;
if (num == 1)
result = num;
else
{
int half = num/2;
int span = num - half; // span is used to "shift" upper range
result = sum(half) + sum(span) + (half * span);
}
return result;
}
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.
public int factorial (int num)
{
int result;
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.
public String reverse (String text)
{
if (text.length() == 1)
return text;
else
{
String result;
result = text.charAt(text.length() - 1)
+ reverse (text.substring(0, text.length()-1));
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
S 185
{1,0,1,0,1,1,1,1,1},
{1,0,1,0,1,0,1,0,1},
{1,0,1,0,1,0,1,0,1},
{1,0,1,0,1,0,1,0,1},
{1,0,1,0,1,0,1,0,1},
{1,1,1,0,1,0,1,0,1},
{0,0,1,0,1,0,1,0,1},
{1,0,1,0,1,0,1,0,1},
{1,0,1,0,1,0,1,0,1},
{1,0,1,0,1,0,1,0,1},
{1,0,1,1,1,1,1,0,1} };
8.9.
0
0
0
0
0
7
0
0
0
0
0
1
1
1
1
1
7
7
7
7
7
7
0
0
0
0
0
0
0
0
0
0
7
1
1
1
1
1
1
1
1
1
1
7
1
0
0
0
0
0
0
0
0
0
7
7
7
7
7
7
7
7
7
7
7
7
7
0
0
0
0
0
0
0
0
0
0
7
7
7
7
7
7
7
7
7
7
7
Annotate the lines of output of the SolveTowers program in this chapter to show the recursive steps.
Move
Move
Move
Move
Move
Move
Move
Move
Move
Move
Move
Move
Move
Move
Move
one
one
one
one
one
one
one
one
one
one
one
one
one
one
one
disk
disk
disk
disk
disk
disk
disk
disk
disk
disk
disk
disk
disk
disk
disk
from
from
from
from
from
from
from
from
from
from
from
from
from
from
from
1
1
2
1
3
3
1
1
2
2
3
2
1
1
2
to
to
to
to
to
to
to
to
to
to
to
to
to
to
to
2
3
3
2
1
2
2
3
3
1
1
3
2
3
3
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
called
called
called
called
called
called
called
called
called
called
called
called
called
called
called
with
with
with
with
with
with
with
with
with
with
with
with
with
with
with
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
numDisks
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
1
2
1
3
1
2
1
4
1
2
1
3
1
2
1
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:
4:
5:
6:
7:
8:
9:
10:
3
7
15
31
63
127
255
511
1023
S 186
15:
20:
25:
8.11.
32767
1,048,575
33,554,431
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.
A Koch snowflake of order N has 3(4N-1) line segments.
Order
Line Segments
1: 3
2: 12
3: 48
4: 192
5: 768
6: 3072
7: 12,288
8: 49,152
9: 196,608
S 187
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(subStringEnd1))
return false;
// first and last equal, try smaller substring
testPalindrome(subStringStart+1, subStringEnd-1);
return true;
}
//----------------------------------------------------------------// Tests strings to see if they are palindromes.
//----------------------------------------------------------------public static void main (String args[])
{
String str, another = "y";
Scanner scan = new Scanner (System.in);
while (another.equalsIgnoreCase("y"))
{
System.out.println ("Enter a potential palindrome:");
str = scan.nextLine();
PalindromeTester p = new PalindromeTester(str);
if (p.isPalindrome())
System.out.println ("That string IS a palindrome.");
else
System.out.println ("That string is NOT a palindrome.");
System.out.println();
System.out.print ("Test another palindrome (y/n)? ");
another = scan.nextLine();
}
}
2007 Pearson Education
S 188
}
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.
//********************************************************************
public class DivisorCalc {
public static int gcd(int num1, int num2)
{
if (num2 % num1 == 0)
return num1;
else
return gcd(num2, num1 % num2);
}
}
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.
//********************************************************************
public class Maze
{
private final int TRIED = 3;
private final int PATH = 7;
private int[][] maze = { {1,1,1,0,1,1,0,0,0,1,1,1,1},
{1,0,1,1,1,0,1,1,1,1,0,0,1},
{0,0,0,0,1,0,1,0,1,0,1,0,0},
{1,1,1,0,1,1,1,0,1,0,1,1,1},
{1,0,1,0,0,0,0,1,1,1,0,0,1},
{1,0,1,1,1,1,1,1,0,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,1,1,1,1,1,1} };
private int[][] grid;
//----------------------------------------------------------------// 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)
{
// make copy
grid = new int[maze.length][maze[0].length];
for (int i = 0; i < maze.length; i++)
for (int j = 0; j < maze[i].length; j++)
grid[i][j] = maze[i][j];
return traverse(row, column);
2007 Pearson Education
S 189
}
//----------------------------------------------------------------// 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;
S 190
S 191
//----------------------------------------------------------------// 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;
if (valid (row, column, page))
{
grid[row][column][page] = TRIED;
S 192
S 193
S 194
//
//
//
//
//----------------------------------------------------------------// 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-----------------------");
}
public static void main (String args[]) {
new NonAttackingQueens().showSolutions();
}
}
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();
boolean stop = chooser.nextBoolean();
if (!stop)
y.append(getWhoozitYs());
else
return y.toString();
y.append("y");
return y.toString();
}
//----------------------------------------------------------------// Generates a random Whoozit.
2007 Pearson Education
S 195
S 196
S 197
S 198
// 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;
public class PascalTriangle {
private int rowNumber;
private int rowCount;
private int[] newRow;
//----------------------------------------------------------------// 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
S 199
S 200
{
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);
for (int index = 0; index < prices.length; index++)
System.out.print (prices[index] + "
");
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
static
static
static
final
final
final
final
int
int
int
int
HEIGHT = 20;
WIDTH_STEP = 20;
ARC_WIDTH = 5;
ARC_HEIGHT = 5;
S 201
S 202
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
{
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());
// draw the disks
int location = 1;
int diskX = x + WIDTH / 2;
while (!temp.isEmpty())
{
Disk d = (Disk)temp.pop();
int diskY = y - Disk.HEIGHT * location;
d.draw(g, diskX, diskY);
// put disk back on stack
disks.push(d);
2007 Pearson Education
S 203
S 204
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;
public Move(int fromTower, int toTower)
{
from = fromTower;
to = toTower;
}
public String toString()
{
return "Move from tower " + from + " to tower " + to;
}
public int getFrom()
{
return from;
}
public int getTo()
{
return 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
import
import
import
import
javax.swing.*;
javax.swing.border.TitledBorder;
java.awt.event.*;
java.awt.*;
java.util.Hashtable;
public TowerFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
towerViewer = new TowerPanel(TowerPanel.DEFAULT_NUM_DISKS);
getContentPane().add(towerViewer, BorderLayout.CENTER);
// create listeners
SliderListener sliderHandler = new SliderListener();
ButtonListener buttonHandler = new ButtonListener();
//create animation button panel
JPanel animationButtonPanel = new JPanel();
animationButtonPanel.setLayout(new GridLayout(1,2));
JButton pause = new JButton("Pause Animation");
pause.setName("pause");
pause.addActionListener(buttonHandler);
animationButtonPanel.add(pause);
JButton start = new JButton("Resume Animation");
start.setName("resume");
start.addActionListener(buttonHandler);
animationButtonPanel.add(start);
//create animation speed slider
JSlider speed = new JSlider();
speed.setName("speed");
speed.setMinimum(TowerPanel.MIN_PAUSE_TIME);
speed.setMaximum(TowerPanel.MAX_PAUSE_TIME);
speed.setValue(TowerPanel.DEFAULT_PAUSE_TIME);
speed.setBorder(new TitledBorder("Animation Speed"));
// make label table
Hashtable labelTable = new Hashtable();
labelTable.put(new Integer(TowerPanel.MIN_PAUSE_TIME), new
JLabel("Faster"));
labelTable.put(new Integer(TowerPanel.MAX_PAUSE_TIME), new
JLabel("Slower"));
speed.setLabelTable(labelTable);
speed.setPaintLabels(true);
speed.addMouseListener(sliderHandler);
// create options button panel
JPanel buttonPanel = new JPanel();
JButton animate = new JButton("Animate");
animate.setName("animate");
animate.addActionListener(buttonHandler);
buttonPanel.add(animate);
JButton user = new JButton("Let Me Try");
user.setName("user");
user.addActionListener(buttonHandler);
buttonPanel.add(user);
JButton reset = new JButton("Reset");
reset.setName("reset");
reset.addActionListener(buttonHandler);
buttonPanel.add(reset);
JPanel controls = new JPanel();
controls.setLayout(new BoxLayout(controls, BoxLayout.Y_AXIS));
controls.add(buttonPanel);
controls.add(speed);
controls.add(animationButtonPanel);
2007 Pearson Education
S 205
S 206
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();
}
public static void main (String args[]) {
new TowerFrame().show();
}
//********************************************************************
// 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();
}
}
2007 Pearson Education
S 207
}
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
import
import
import
import
javax.swing.*;
javax.swing.Timer;
java.awt.*;
java.awt.event.*;
java.util.ArrayList;
final
final
final
final
final
final
final
int
int
int
int
int
int
int
MIN_PAUSE_TIME = 50;
MAX_PAUSE_TIME = 1500;
DEFAULT_PAUSE_TIME = 900;
MIN_DISKS = 1;
MAX_DISKS = 8;
DEFAULT_NUM_DISKS = 4;
NUM_TOWERS = 3;
S 208
}
//----------------------------------------------------------------// 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;
int towerX = towerSpacing/2 - Tower.WIDTH/2;
int towerY = getSize().height;
for (int i=0; i<NUM_TOWERS; i++)
{
towers[i].draw(g, towerX, towerY);
towerX += towerSpacing;
}
}
//----------------------------------------------------------------// 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();
2007 Pearson Education
}
//----------------------------------------------------------------// 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);
for (int i=numDisks; i>0; i--)
towers[0].addDisk(new Disk(i));
towerEngine = new TowersOfHanoi(numDisks);
solution = towerEngine.getSolution();
repaint();
}
//----------------------------------------------------------------// Stops the animation timer.
//----------------------------------------------------------------public void stopTimer()
{
if (animationTimer == null)
return;
if (animationTimer.isRunning())
animationTimer.stop();
}
//----------------------------------------------------------------// Resumes the animation timer, stops any user solutions
//----------------------------------------------------------------public void resumeTimer()
{
2007 Pearson Education
S 209
S 210
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;
int towerSpacing = getSize().width /
NUM_TOWERS;
S 211
{
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
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);
}
// triples the elements from k to a.length-1
private static void tripleHelp (int[] a, int k)
{
a[k] = a[k] * 3;
if (k < a.length-1)
tripleHelp(a, k+1);
}
S 213