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(); } }