/* Adapted from project 1 solution by Hannah Blau */ import java.util.Stack; public class Maze { private int width; private int height; private SCell [][] cells; public Maze(int w, int h) { height = h; width = w; cells = new SCell[width][height]; for (int i = 0; i < width; i++) for (int j = 0; j < height; j++) cells[i][j] = new SCell(i, j, true); } public Maze(int w, int h, String [] init) { this(w, h); initializeMaze(init); } private void initializeMaze(String[] init) { int rows = (height <= init.length ? height : init.length); for (int j = 0; j < rows; j++) { int cols = (width <= init[j].length() ? width : init[j].length()); for (int i = 0; i < cols; i++) { boolean isOpen = (init[j].charAt(i) == '1'); cells[i][j].setOpen(isOpen); } } } public int getCellStatus (int col, int row) { if (row >= height || col >= width || row < 0 || col < 0) return -1; else return (cells[col][row].getOpen() == true ? 1 : 0); } public SCell[] moves (int col, int row) throws ArrayIndexOutOfBoundsException { int [ ] neighborStatus = new int[4]; if (row >= height || col >= width || row < 0 || col < 0) throw new ArrayIndexOutOfBoundsException(); // not really needed neighborStatus[0] = getCellStatus(col, row+1); neighborStatus[1] = getCellStatus(col, row-1); neighborStatus[2] = getCellStatus(col+1, row); neighborStatus[3] = getCellStatus(col-1, row); int count = 0; for (int i = 0; i < 4; i++) if (neighborStatus[i] == 1) count++; int index = 0; SCell [] outCells = new SCell[count]; if (neighborStatus[0] == 1) outCells[index++] = cells[col][row+1]; if (neighborStatus[1] == 1) outCells[index++] = cells[col][row-1]; if (neighborStatus[2] == 1) outCells[index++] = cells[col+1][row]; if (neighborStatus[3] == 1) outCells[index++] = cells[col-1][row]; return outCells; } /* If path of open cells exists between starting point and ending * point, returns an array containing the SCells on the path. * If no path exists, returns an array of length 0. * @param sourceX: x-coordinate (column) of starting cell in path * @param sourceY: y-coordinate (row) of starting cell in path * @param destX: x-coordinate (column) of ending cell in path * @param destY: y-coordinate (row) of ending cell in path */ public SCell[] path ( int sourceX, int sourceY, int destX, int destY ){ // can only have a path if both source and destination cells are open if ( !(cells[sourceX][sourceY].getOpen() && cells[destX][destY].getOpen()) ) return new SCell[0]; // if source and destination are the same, then the path consists of that one cell if ( sourceX == destX && sourceY == destY ) { SCell[] goodPath = { cells[sourceX][sourceY] }; return goodPath; } // have to search for a path return pathSearch(sourceX, sourceY, destX, destY); } /* If path of open cells exists between starting point and ending * point, returns an array containing the SCells on the path. * If no path exists, returns an array of length 0. * @param sourceX: x-coordinate (column) of starting cell in path * @param sourceY: y-coordinate (row) of starting cell in path * @param destX: x-coordinate (column) of ending cell in path * @param destY: y-coordinate (row) of ending cell in path */ private SCell[] pathSearch ( int sourceX, int sourceY, int destX, int destY ) { SCell current; // cell currently at the top of the stack // assume there is no path from source to dest until we find one SCell[] path = new SCell[0]; Stack stack = new Stack(); SCell[] neighbors; // open, unseen cells that are within one move of current cell SCell neighbor; boolean stillLooking; // becomes false when we find an open, unseen neighbor of current cell int i; SCell start = cells[sourceX][sourceY]; start.setSeen(true); stack.push(start); while ( !stack.isEmpty() ) { current = stack.peek(); // have we reached the destination? if ( current.getXCoord() == destX && current.getYCoord() == destY ) { path = createPathArray(stack); break; } // can we find a neighbor of the current cell that is open and unseen? stillLooking = true; neighbors = moves(current.getXCoord(), current.getYCoord()); i = 0; while ( i < neighbors.length && stillLooking ) { neighbor = neighbors[i++]; if ( neighbor.getOpen() && !neighbor.getSeen() ) { stillLooking = false; neighbor.setSeen(true); stack.push(neighbor); } } if ( stillLooking ) { // current cell has no open, unseen neighbors; it is not on path to destination stack.pop(); } } resetUnseen(); return path; } /* Returns an array of SCells that represents the contents of the stack, a path from the source * on the bottom of the stack to the destination on the top of the stack. createPathArray reverses * the order of the SCells on the stack so the array reads from source to destination. * @param stk: stack of SCells containing the path. */ private SCell[] createPathArray(Stack stk) { int pathLength = stk.size(); SCell[] path = new SCell[pathLength]; for ( int i = pathLength - 1; i >= 0; i-- ) { path[i] = stk.pop(); } return path; } /* Resets all cells to unseen. */ private void resetUnseen() { for ( int col = 0; col < width; col++ ) { for ( int row = 0; row < height; row++ ) { cells[col][row].setSeen(false); } } } /* Returns true if a path exists from source to destination, false otherwise. */ public boolean isPath ( int sourceX, int sourceY, int destX, int destY ) { return path(sourceX, sourceY, destX, destY).length > 0; } public String toString () { String ret = ""; for (int j = 0; j < height; j++) { for (int i = 0 ; i < width; i++) ret += (cells[i][j].getOpen() == true ? "1" : "0"); if (j < height - 1) ret += "\n"; } return ret; } /* Displays a path on standard output. * @param path: array of SCells containing a path from source to destination. */ private void displayPath(SCell[] path) { if ( path.length == 0 ) { System.out.println("No path exists."); } else { for ( SCell c : path ) { System.out.print("(" + c.getXCoord() + ", " + c.getYCoord() + ") "); } System.out.println(); } } public static void main(String[] args) { String [] init = {"11011", "10001", "11011", "11000"}; int h = 4; int w = 5; Maze m = new Maze (w, h, init); System.out.println(m); for (int row=0; row < h; row++) for (int col=0; col < w; col++) { SCell [] result = m.moves(col, row); int numMoves = result.length; System.out.println ("Number of moves from col "+ col + " and row "+ row +" is: " + numMoves); for (int i = 0; i < numMoves; i++) System.out.println(result[i].toString()); } System.out.println("Path from (3,0) to (3,0)? "); m.displayPath(m.path(3, 0, 3, 0)); System.out.println("Path from (3,0) to (4,3)? "); m.displayPath(m.path(3, 0, 4, 3)); System.out.println("Path from (0,0) to (3,2)? "); m.displayPath(m.path(0, 0, 3, 2)); System.out.println("Path from (1,0) to (1,2)? "); m.displayPath(m.path(1, 0, 1, 2)); System.out.println("Path from (4,0) to (3,2)? "); m.displayPath(m.path(4, 0, 3, 2)); } }