Make Maze
<< DuckyLove | FinalProjectsTrailIndex | Perspective Floor >>
Various interactive mazes could be made. This one just constructs a maze using the Recursive backtracker algorithm described here
For a visual demonstration of the algorithm, Click here
This will make a new maze on a mouse click. To see it in action, click here
Cell.java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.ArrayList;
/**
* @author Chris Thiel, OFMCap
* @version 16 May 2012
*/
public class Cell
{
public static final int GAP=10, SIZE=40, LEFT=40, TOP=60;
public static final int NORTH=0, SOUTH=1, EAST=2, WEST=3;
private int visits, row, col;
private boolean[] wall;
private Rectangle box;
public Cell(int r, int c)
{
visits=-1;
row=r;
col=c;
wall=new boolean[4];
box = new Rectangle (LEFT+col*(SIZE+GAP), TOP+row*(SIZE+GAP), SIZE, SIZE);
for (int i=0;i<4;i++)
wall[i]=true;
}
/**
*
* @return a random neighboring Cell, or null if all neighbors have been visited
*/
public Cell randomNeighbor(Cell[][] m){
ArrayList<Cell> n = new ArrayList<Cell>();
//NORTH
if (row>0 && m[row-1][col].getVisits()<0)
n.add(m[row-1][col]);
//SOUTH
if (row<m.length-1 && m[row+1][col].getVisits()<0)
n.add(m[row+1][col]);
//WEST
if (col>0 && m[row][col-1].getVisits()<0)
n.add(m[row][col-1]);
//EAST
if (col<m[0].length-1 && m[row][col+1].getVisits()<0)
n.add(m[row][col+1]);
if (n.size()<1)
return null;
return n.get((int)(n.size()*Math.random()));
}
public void draw(Graphics g, Color c)
{
Color oldColor=g.getColor();
g.setColor(c);
if (visits==1)
g.setColor(Color.GREEN);
if (visits>1)
g.setColor(Color.RED);
g.fillRect(box.x, box.y, box.width, box.height);
if (!wall[SOUTH])
g.fillRect(box.x, box.y+SIZE, box.width, GAP);
if (!wall[EAST])
g.fillRect(box.x+SIZE, box.y, GAP, box.width);
g.setColor(oldColor);
}
public Rectangle getBox(){return box;}
public int getRow(){return row;}
public int getCol(){return col;}
public int getVisits(){return visits;}
public void setVisits(int i){visits=i;}
public void incVisits(){visits++;}
public void setWall(int direction, boolean value){
wall[direction]=value;
}
/**
* removes the walls between this cell and the other cell
* @param other
*/
public void removeWall(Cell other) {
if (other.getRow()>row){//other cell is below this one
this.setWall(SOUTH, false);
other.setWall(NORTH, false);
}
if (other.getRow()<row){//other cell is above this one
this.setWall(NORTH, false);
other.setWall(SOUTH, false);
}
if (other.getCol()>col){//other cell is east of this one
this.setWall(EAST, false);
other.setWall(WEST, false);
}
if (other.getCol()<col){//other cell is west this one
this.setWall(WEST, false);
other.setWall(EAST, false);
}
}
}
MazeMaker.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
/**
* @author Chris Thiel, OFMCap
* @version 16 May 2012 (Applet)
* @version 5 Sept 2021 (Application)
*/
public class MakeMaze extends JPanel implements MouseListener
{
public static final int ROWS=10, COLS=10;
public static final int WIDTH=575, HEIGHT=620;
private Cell[][] m;
String message="Making Maze";
public static void main(String[] args) {
MakeMaze app= new MakeMaze();
JFrame window = new JFrame("Make Maze");
window.setSize(WIDTH, HEIGHT);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(app);
window.setVisible(true);
}
public MakeMaze()
{
message="Making First Maze";
makeMaze();
message="First Maze done.";
this.addMouseListener(this);
}
public void makeMaze()
{
m = new Cell[ROWS][COLS];
for (int r=0;r<ROWS;r++)
for(int c=0;c<COLS;c++)
m[r][c]=new Cell(r,c);
Cell currentCell=m[ROWS-1][0];
currentCell.incVisits();
ArrayList<Cell> stack=new ArrayList<Cell>();
while (unvisitedCells()){
Cell choice=currentCell.randomNeighbor(m);
if (choice!=null){
stack.add(0, currentCell);
currentCell.removeWall(choice);
currentCell=choice;
currentCell.incVisits();
}else{
stack.remove(0);
currentCell=stack.get(0);
}
repaint();
}
}
private boolean unvisitedCells(){
int r=0;
while(r<ROWS){
int c=0;
while(c<COLS)
if(m[r][c].getVisits()<0){
return true;
}else{
c++;
}
r++;
}
return false;
}
public void paintComponent(Graphics g)
{
g.setColor(Color.WHITE);
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.BLACK);
g.drawString(message, 20, 20);
int left = Cell.LEFT-Cell.GAP;
int top = Cell.TOP-Cell.GAP;
int width = COLS*(Cell.SIZE+Cell.GAP)+Cell.GAP;
int height = ROWS*(Cell.SIZE+Cell.GAP)+Cell.GAP;
g.fillRect(left, top, width,height );
for (int r = 0; r < ROWS; r++)
for(int c=0;c<COLS;c++)
m[r][c].draw(g, Color.YELLOW);
int bottom = height;
int delta = Cell.SIZE+ 1*Cell.GAP;
for(int r = 1; r <= ROWS; r++)
g.drawString(""+r, 5, bottom - (r-1)*delta);
for(int c = 1; c <= COLS; c++)
g.drawString(""+c, c*delta + 30, height+delta + 15 );
}
public void update(Graphics g)
{
paint(g);
}
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
@Override
public void mousePressed(MouseEvent e) {}
@Override
public void mouseReleased(MouseEvent e) {
message="Making new Maze";
makeMaze();
message="Maze Done";
repaint();
}
}
