/** * Creates a new Maze object. Sets up the maze to be generated and generates a maze starting at * (1, 1) of the maze. * * @param res The resolution that the maze will be including walls. The maze is a square. * @param inW The character that will represent walls in the final maze. * @param inH The character that will represent halls in the final maze. */ @SuppressWarnings("Convert2Diamond") public Maze(int res, char inW, char inH) { // initialize the array lists to track past positions to aid with the recursion process pastX = new ArrayList<Integer>(); pastY = new ArrayList<Integer>(); wall = inW; // sets the wall symbol to the one indicated in the parameters hall = inH; // sets the hall symbol to the one indicated in the parameters setup(res); // setsup the maze for the generation generate(1, 1); // generates the maze using recursive backtracking }
/** * Generates the maze part of the maze using recursive backtracking to break down walls until a * perfect maze has been created. * * @param xPos The x coordinate to break a wall from * @param yPos The y coordinate to break a wall from */ private void generate(int xPos, int yPos) { /* RULES: 1. set current spot to visited and opened 2. select a random direction to try to move in 3. for the selected direction: go there if it: is not visited, is a wall, it is not touching any other opened spaces on the 3 other sides 4. if it is not a valid spot, pick another direction 5. if there is no valid direction, go back to the previous section and try again */ // Part 1 visited[xPos][yPos] = true; // Sets the current position to visited maze[xPos][yPos] = hall; // Sets the current position to a hall // End Part 1 // These booleans will be used so that the program knows when it needs to backtrack boolean cannotGoN = false; boolean cannotGoS = false; boolean cannotGoE = false; boolean cannotGoW = false; boolean canGoSomewhere = true; // this will be false once the program knows that it can not move in any direction and // will triger the recursion // Part 4 while (canGoSomewhere) { // this loop runs until it is known that the computer cannot validly // break a wall // Part 2 // generates a random direction to try to break a wall and move in Random rand = new Random(); int goThisWay = rand.nextInt(4); // Part 3 // It now attempts to go in the direction mentioned in the comment after each of the first if // statements. // I am not going to comment all four directions. Each is similar. // the nested if statements could be formatted as one using the && oporater but it is easier // to read and comment with three seperate ones if (goThisWay == 0) { // attempt to go north if (maze[xPos][yPos - 1] == wall && !visited[xPos][ yPos - 1]) { // checks to see if the spot that they are trying to break is a wall and // not already visited if (maze[xPos][yPos - 2] == wall && maze[xPos - 1][yPos - 1] == wall && maze[xPos + 1][yPos - 1] == wall) { // checks to see if the spots around the spot it is trying to move into // are walls (not including the current spot) pastX.add( xPos); // puts the current x coordinate into the past x coordinates to prepare to // break the wall pastY.add( yPos); // puts the current y coordinate into the past x coordinates to prepare to // break the wall generate( xPos, yPos - 1); // goes to the next spot where it will break the wall and try to move // again canGoSomewhere = false; } else { // if the spot was not able to be turned into a hall because a spot next to it // was a hall then it cannot move in this direction cannotGoN = true; // makes sure the program does not try again so that it can eventually recurse } } else { // if the spot was not able to be turned into a hall because it was an already // visited wall cannotGoN = true; // makes sure the program does not try again so that it can eventually recurse } } else if (goThisWay == 1) { // east if (maze[xPos + 1][yPos] == wall && !visited[xPos + 1][yPos]) { if (maze[xPos + 2][yPos] == wall && maze[xPos + 1][yPos + 1] == wall && maze[xPos + 1][yPos - 1] == wall) { pastX.add(xPos); pastY.add(yPos); generate(xPos + 1, yPos); canGoSomewhere = false; } else { cannotGoE = true; } } else { cannotGoE = true; } } else if (goThisWay == 2) { // south if (maze[xPos][yPos + 1] == wall && !visited[xPos][yPos + 1]) { if (maze[xPos][yPos + 2] == wall && maze[xPos - 1][yPos + 1] == wall && maze[xPos + 1][yPos + 1] == wall) { pastX.add(xPos); pastY.add(yPos); generate(xPos, yPos + 1); canGoSomewhere = false; } else { cannotGoS = true; } } else { cannotGoS = true; } } else if (goThisWay == 3) { // west if (maze[xPos - 1][yPos] == wall && !visited[xPos - 1][yPos]) { if (maze[xPos - 2][yPos] == wall && maze[xPos - 1][yPos + 1] == wall && maze[xPos - 1][yPos - 1] == wall) { pastX.add(xPos); pastY.add(yPos); generate(xPos - 1, yPos); canGoSomewhere = false; } else { cannotGoW = true; } } else { cannotGoW = true; } } // End Part 3 // Part 5 if (cannotGoN && cannotGoS && cannotGoE && cannotGoW) { // if the program cannot break a wall in any direction canGoSomewhere = false; // this tells the program that it cannot recurse (the while loop will now stop // repeating) } // End Part 5 } // the recursion process if (pastX.size() > 0 && pastY.size() > 0) { // if the program is not done creating the maze because it is not yet back at (1, // 1) int tempX = pastX.get(pastX.size() - 1); // store the x coordinate of the spot to recur to int tempY = pastY.get(pastY.size() - 1); // store the y coordinate of the spot to recur to pastX.remove( pastX.size() - 1); // remove the x coordinate of the spot to recur to from the list of past // positions pastY.remove( pastY.size() - 1); // remove the y coordinate of the spot to recur to from the list of past // positions generate(tempX, tempY); // recurse to the previous position } }