Maze.java
Below is the syntax highlighted version of Maze.java
from §2.7 Recursion.
/*************************************************************************
* Compilation: javac Maze.java
* Execution: java Maze.java N
* Dependecies: StdDraw.java
*
* Generates a perfect N-by-N maze using depth-first search with a stack.
*
* % java Maze 62
*
* Note: this program generalizes nicely to finding a random tree
* in a graph.
*
*************************************************************************/
import java.awt.Color;
public class Maze {
private int N; // dimension of maze
private boolean[][] north; // is there a wall to north of cell i, j
private boolean[][] east;
private boolean[][] south;
private boolean[][] west;
private boolean[][] visited;
private double size;
boolean done = false;
public Maze(int N) {
this.N = N;
StdDraw.create(512, 512);
size = 512.0 / (N + 2);
init();
generate();
}
private void init() {
// initialize border cells as already visited
visited = new boolean[N+2][N+2];
for (int x = 0; x < N+2; x++) visited[x][0] = visited[x][N+1] = true;
for (int y = 0; y < N+2; y++) visited[0][y] = visited[N+1][y] = true;
// initialze all wells as present
north = new boolean[N+2][N+2];
east = new boolean[N+2][N+2];
south = new boolean[N+2][N+2];
west = new boolean[N+2][N+2];
for (int x = 0; x < N+2; x++)
for (int y = 0; y < N+2; y++)
north[x][y] = east[x][y] = south[x][y] = west[x][y] = true;
}
// generate the maze
private void generate(int x, int y) {
visited[x][y] = true;
// while there is an univisited neighbor
while (!visited[x][y+1] || !visited[x+1][y] || !visited[x][y-1] || !visited[x-1][y]) {
// pick random neighbor (could use Knuth's trick instead)
while (true) {
double r = Math.random();
if (r < 0.25 && !visited[x][y+1]) {
north[x][y] = south[x][y+1] = false;
generate(x, y + 1);
break;
}
else if (r < 0.50 && !visited[x+1][y]) {
east[x][y] = west[x+1][y] = false;
generate(x+1, y);
break;
}
else if (r < 0.75 && !visited[x][y-1]) {
south[x][y] = north[x][y-1] = false;
generate(x, y-1);
break;
}
else if (r < 1.00 && !visited[x-1][y]) {
west[x][y] = east[x-1][y] = false;
generate(x-1, y);
break;
}
}
}
}
// generate the maze starting from lower left
private void generate() {
generate(1, 1);
// delete some random walls
for (int i = 0; i < N; i++) {
int x = (int) (1 + Math.random() * (N-1));
int y = (int) (1 + Math.random() * (N-1));
north[x][y] = south[x][y+1] = false;
}
// add some random walls
for (int i = 0; i < 10; i++) {
int x = (int) (N / 2 + Math.random() * (N / 2));
int y = (int) (N / 2 + Math.random() * (N / 2));
east[x][y] = west[x+1][y] = true;
}
}
// solve the maze using depth first search
private void solve(int x, int y) {
if (x == 0 || y == 0 || x == N+1 || y == N+1) return;
if (done || visited[x][y]) return;
visited[x][y] = true;
StdDraw.setColor(Color.blue);
StdDraw.go(size * (x + 0.5), size * (y + 0.5));
StdDraw.spot(size / 2);
StdDraw.pause(30);
// reached upper right
if (x == N/2 && y == N/2) done = true;
if (!north[x][y]) solve(x, y + 1);
if (!east[x][y]) solve(x + 1, y);
if (!south[x][y]) solve(x, y - 1);
if (!west[x][y]) solve(x - 1, y);
if (done) return;
StdDraw.setColor(Color.gray);
StdDraw.go(size * (x + 0.5), size * (y + 0.5));
StdDraw.spot(size / 2);
StdDraw.pause(30);
}
// solve the maze starting from the start state
public void solve() {
for (int x = 1; x <= N; x++)
for (int y = 1; y <= N; y++)
visited[x][y] = false;
done = false;
solve(1, 1);
}
// display the maze in turtle graphics
public void draw() {
StdDraw.setColor(Color.red);
StdDraw.go(size * (N/2 + 0.5), size * (N/2 + 0.5));
StdDraw.spot(3 * size / 4);
StdDraw.go(size * (1 + 0.5), size * (1 + 0.5));
StdDraw.spot(3 * size / 4);
StdDraw.setColor(Color.black);
for (int x = 1; x <= N; x++) {
for (int y = 1; y <= N; y++) {
if (south[x][y]) {
StdDraw.go(x*size, y*size);
StdDraw.penDown();
StdDraw.go(x*size + size, y*size);
StdDraw.penUp();
}
if (north[x][y]) {
StdDraw.go(x*size, y*size + size);
StdDraw.penDown();
StdDraw.go(x*size + size, y*size + size);
StdDraw.penUp();
}
if (west[x][y]) {
StdDraw.go(x*size, y*size);
StdDraw.penDown();
StdDraw.go(x*size, y*size + size);
StdDraw.penUp();
}
if (east[x][y]) {
StdDraw.go(x*size + size, y*size);
StdDraw.penDown();
StdDraw.go(x*size + size, y*size + size);
StdDraw.penUp();
}
}
}
StdDraw.pause(1000);
StdDraw.show();
}
// a test client
public static void main(String[] args) {
int N = Integer.parseInt(args[0]);
Maze maze = new Maze(N);
maze.draw();
maze.solve();
}
}
Last updated: Sun Sep 26 12:36:31 EDT 2004
.
Copyright © 2004, Robert Sedgewick and Kevin Wayne.