Read [Gray], Chapters 3 through 7. Consider the "Checkpoint" questions as part of your reading assignment: answer them but don't turn in your answers.You are encouraged to do all of these because many of the quiz and final exam questions will be based on these.
Use your CVS repository (or an SVN repository if you prefer) while working on this assignment.
The real-life programming projects are back! Please provide professionally crafted solutions to the following:
/**
* Moves a rat from (x1,y1) to (x2,y2), filling in the cells
* as it goes, and notifying a listener at each step.
*/
public boolean solve(Maze maze, int x1, int y1, int x2, int y2,
MazeListener listener) {
. . .
}
You are required to "solve" the maze using a stack-based
backtracking algorithm; you must
use the SimpleStack class in the online course notes. You are not
required to turn in a unit test, but you should write one anyway. I've
already written the Maze class and a silly graphics program
that will use your solver:
package edu.lmu.cs.maze;
/**
* A maze simple rectangular maze.
*/
public class Maze {
// A maze is a rectangular array of cells, whose width and height
// are stored separately for convenience. The class is set up
// so that mazes can't get whacked out of a rectangular shape.
private Cell[][] cells;
private int width;
private int height;
// Hide the constructor, since we'll only allow construction
// via the factory method that constructs the maze from a string.
private Maze() {
}
/**
* An (x,y) position, with methods returning whether
* or not the position is within the maze, whether or
* not the position is open, and its neighbors.
*/
public class Location {
private int x;
private int y;
Location(int x, int y) {this.x = x; this.y = y;}
boolean isLegal() {return x >= 0 && x < width && y >= 0 && y < height;}
boolean isOpen() {return isLegal() && cells[y][x] == Cell.OPEN;}
Location above() {return new Location(x, y - 1);}
Location below() {return new Location(x, y + 1);}
Location left() {return new Location(x - 1, y);}
Location right() {return new Location(x + 1, y);}
void set(Cell cell) {cells[y][x] = cell;}
Cell get() {return cells[y][x];}
public boolean isAt(int x, int y) {return this.x == x && this.y == y;}
}
/**
* A simple cell value. A cell can be open (meaning a rat has
* never visited it), a wall, part of the rat's current path,
* or "tried" (meaning the rat found it to be part of a dead end.
*/
public static enum Cell {
OPEN('.'), WALL('#'), TRIED('x'), PATH('o'), RAT('r');
private char display;
private Cell(char display) {this.display = display;}
public String toString() {return Character.toString(display);}
}
/**
* A listener interface for responding to maze changes.
*/
public interface MazeListener {
void mazeChanged(Maze maze);
}
/**
* Build and return a new maze given a description in the
* form of a string of 0's and 1's -- 0's for open spaces and
* 1's for walls. Each row is separated by whitespace.
* For example "1100 0100 1001" represents a 3-row, 4-column
* maze that looks like this:
* <pre>
* ##..
* .#..
* #..#
* </pre>
*/
public static Maze fromText(String description) {
Maze maze = new Maze();
String[] rows = description.trim().split("\\s+");
maze.height = rows.length;
maze.width = rows[0].length();
maze.cells = new Cell[maze.height][maze.width];
for (int y = 0; y < maze.height; y++) {
String row = rows[y];
if (!row.matches("[01]+")) {
throw new IllegalArgumentException("Illegal characters in maze");
}
if (row.length() != maze.width) {
throw new IllegalArgumentException("Non-rectangular maze");
}
for (int x = 0; x < maze.width; x++) {
maze.cells[y][x] = row.charAt(x) == '0' ? Cell.OPEN : Cell.WALL;
}
}
return maze;
}
/**
* Replaces all non-walls with open marks. Used to clean up
* a maze after a rat ran through it.
*/
public void clear() {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (cells[y][x] != Cell.WALL) cells[y][x] = Cell.OPEN;
}
}
}
/**
* Returns a textual description of the maze, separating each
* row with a newline.
*/
public String toString() {
StringBuilder builder = new StringBuilder(height * width);
for (Cell[] row: cells) {
for (Cell cell: row) {
builder.append(cell);
}
builder.append("\n");
}
return builder.toString();
}
}
package edu.lmu.cs.maze;
import java.awt.BorderLayout;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
/**
* Really cheap application that "animates" a rat moving through
* a maze. It simply keeps refreshing a monospaced font rendering
* of the maze's toString() output.
*/
public class SwingMazeDemo {
public static class MazePanel extends JPanel implements Maze.MazeListener {
private JTextArea display = new JTextArea(40, 40);
public MazePanel() {
setLayout(new BorderLayout());
display.setFont(new Font("Monospaced", Font.PLAIN, 32));
add(new JScrollPane(display), BorderLayout.CENTER);
}
/**
* Waits a second then refreshes the maze in the textarea.
*/
public void mazeChanged(Maze maze) {
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
}
display.setText(maze.toString());
}
}
public static void main(String[] args) throws Exception {
JFrame frame = new JFrame("Maze");
MazePanel panel = new MazePanel();
frame.setSize(800, 600);
frame.getContentPane().add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Maze maze = Maze.fromText("000110000 110100010 010000010 000100000");
boolean success = new MazeSolver().solve(maze, 6, 0, 1, 3, panel);
frame.setTitle(success ? "Made it! " : "Stuck");
}
}
With this assignment, version control is now a requirement. Organize your work in your CVS (or SVN) repository with the following structure:
homework
cmsi281
src
main
docs
hw4.tex
<diagram source files>, if any
<images>, if any
java
edu
lmu
cs
collections
Sequence.java
maze
MazeSolver.java
math
Polynomial.java (you should already have this from HW 2)
LinkedPolynomial.java (implements Polynomial)
collections
ListUtils.java
Stack.java
SimpleStack.java
maze
Maze.java
SwingMazeApplication.java
test
java
edu
lmu
cs
collections
ListUtilsTest.java
SequenceTest.java
math
LinkedPolynomialTest.java
Your LaTeX file will contain solutions to each problem, numbered, and in order. You may embed source code in the document, or give the answer as "See <filename>" and submit the sources for these answers at the end of the document. Generate a pdf from the LaTeX file and hand in a printed copy. Only turn in printed copies of your own files; do not waste trees by printing the sources for the code I gave you.
Notes