
simple.server.extension.d20.MazeGenerator Maven / Gradle / Ivy
The newest version!
package simple.server.extension.d20;
import java.util.Random;
/**
* ***********************************************************************
* Compilation: javac MazeGenerator.java Execution: java MazeGenerator.java N
* Dependecies: StdDraw.java
*
* Generates a perfect N-by-N maze using depth-first search with a stack.
*
* % java MazeGenerator 62
*
* Note: this program generalizes nicely to finding a random tree in a graph.
*
************************************************************************
*/
public class MazeGenerator {
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;
private boolean done = false;
public MazeGenerator(int N) {
this.N = N;
StdDraw.setXscale(0, N + 2);
StdDraw.setYscale(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.25 && r < 0.50 && !visited[x + 1][y]) {
east[x][y] = west[x + 1][y] = false;
generate(x + 1, y);
break;
} else if (r >= 0.5 && r < 0.75 && !visited[x][y - 1]) {
south[x][y] = north[x][y - 1] = false;
generate(x, y - 1);
break;
} else if (r >= 0.75 && 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.setPenColor(StdDraw.BLUE);
StdDraw.filledCircle(x + 0.5, y + 0.5, 0.25);
StdDraw.show(30);
// reached middle
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.setPenColor(StdDraw.GRAY);
StdDraw.filledCircle(x + 0.5, y + 0.5, 0.25);
StdDraw.show(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.setPenColor(StdDraw.RED);
StdDraw.filledCircle(0.5 * N + 0.5, 0.5 * N + 0.5, 0.375);
StdDraw.filledCircle(1.5, 1.5, 0.375);
StdDraw.setPenColor(StdDraw.BLACK);
for (int x = 1; x <= N; x++) {
for (int y = 1; y <= N; y++) {
if (south[x][y]) {
StdDraw.line(x, y, x + 1, y);
}
if (north[x][y]) {
StdDraw.line(x, y + 1, x + 1, y + 1);
}
if (west[x][y]) {
StdDraw.line(x, y, x, y + 1);
}
if (east[x][y]) {
StdDraw.line(x + 1, y, x + 1, y + 1);
}
}
}
StdDraw.show(1000);
}
// a test client
public static void main(String[] args) {
int N = args.length==1?Integer.parseInt(args[0]):new Random().nextInt(100);
MazeGenerator maze = new MazeGenerator(N);
StdDraw.show(0);
maze.draw();
maze.solve();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy