/** * Sorts an ArrayList of MazeCells based on the value of the Heuristic Function * * @param neighbors * @return */ private static ArrayList<MazeCell> sortNeighbors(ArrayList<MazeCell> neighbors) { for (MazeCell temp : neighbors) { if (temp.getHeuristicDistance() == Integer.MAX_VALUE) { neighbors.remove(temp); } } // Lowest index has highest path cost for (int i = 0; i < neighbors.size(); i++) { for (int j = 1; j < neighbors.size() - i; j++) { if (neighbors.get(j - 1).getHeuristicDistance() < neighbors.get(j).getHeuristicDistance()) { MazeCell temp = neighbors.get(j - 1); neighbors.set(j - 1, neighbors.get(j)); neighbors.set(j, temp); } } } return neighbors; }
/** * Implements a Greedy Best First Search on a Maze Object * * @param myMaze * @return */ public static char[] greedyBestFirstSearch(Maze myMaze) { // For Greedy Best First Search Stack<MazeCell> frontier = new Stack<MazeCell>(); // Add the Starting State frontier.add(myMaze.getCell(myMaze.getStartX(), myMaze.getStartY())); // Store the current Co-ordinates int currentX = 0, currentY = 0; while (!frontier.isEmpty()) { // Get the Top Node MazeCell currentNode = frontier.pop(); // Check if this node has been visited if (currentNode.getVisited() == true) { continue; } // Mark the current node as visited currentNode.setVisited(); // Obtain the current cordinates currentX = currentNode.getX(); currentY = currentNode.getY(); // Reached the Goal State if ((currentX == myMaze.getGoalX()) && (currentY == myMaze.getGoalY())) { return myMaze.getCell(myMaze.getGoalX(), myMaze.getGoalY()).getPath().toCharArray(); } // Increase the number of Expanded Nodes nodesExpanded += 1; // Check that you're not out of Bounds if (currentX <= 0 || currentY <= 0 || currentX >= myMaze.getHeight() - 1 || currentY >= myMaze.getWidth() - 1) { continue; } // Initial values of heuristics int heuristicRight = Integer.MAX_VALUE, heuristicLeft = Integer.MAX_VALUE, heuristicUp = Integer.MAX_VALUE, heuristicDown = Integer.MAX_VALUE; // Go Rightwards (0) if ((!myMaze.getCell(currentX, currentY + 1).isWall()) && (!myMaze.getCell(currentX, currentY + 1).getVisited())) { // Obtain the heuristic heuristicRight = manhattan(myMaze.getGoalX(), myMaze.getGoalY(), currentX, currentY + 1); // Adjust the Path myMaze .getCell(currentX, currentY + 1) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "0"); // Set the Heuristic myMaze.getCell(currentX, currentY + 1).setHeuristicDistance(heuristicRight); } // Go Downwards (1) if ((!myMaze.getCell(currentX + 1, currentY).isWall()) && (!myMaze.getCell(currentX + 1, currentY).getVisited())) { heuristicDown = manhattan(myMaze.getGoalX(), myMaze.getGoalY(), currentX + 1, currentY); myMaze .getCell(currentX + 1, currentY) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "1"); myMaze.getCell(currentX + 1, currentY).setHeuristicDistance(heuristicDown); } // Go Leftwards (2) if ((!myMaze.getCell(currentX, currentY - 1).isWall()) && (!myMaze.getCell(currentX, currentY - 1).getVisited())) { heuristicLeft = manhattan(myMaze.getGoalX(), myMaze.getGoalY(), currentX, currentY - 1); myMaze .getCell(currentX, currentY - 1) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "2"); myMaze.getCell(currentX, currentY - 1).setHeuristicDistance(heuristicLeft); } // Go Upwards (3) if ((!myMaze.getCell(currentX - 1, currentY).isWall()) && (!myMaze.getCell(currentX - 1, currentY).getVisited())) { heuristicUp = manhattan(myMaze.getGoalX(), myMaze.getGoalY(), currentX - 1, currentY); myMaze .getCell(currentX - 1, currentY) .appendPath(myMaze.getCell(currentX, currentY).getPath() + "3"); myMaze.getCell(currentX - 1, currentY).setHeuristicDistance(heuristicUp); } // Used to Sort the Values ArrayList<MazeCell> myNeighbors = new ArrayList<MazeCell>(); if (heuristicRight != Integer.MAX_VALUE) { myNeighbors.add(myMaze.getCell(currentX, currentY + 1)); } if (heuristicDown != Integer.MAX_VALUE) { myNeighbors.add(myMaze.getCell(currentX + 1, currentY)); } if (heuristicLeft != Integer.MAX_VALUE) { myNeighbors.add(myMaze.getCell(currentX, currentY - 1)); } if (heuristicUp != Integer.MAX_VALUE) { myNeighbors.add(myMaze.getCell(currentX - 1, currentY)); } // Sort the Cells based on Heuristic Values myNeighbors = sortNeighbors(myNeighbors); // Add the Cells to the Frontier in the Sorted Order for (MazeCell temp : myNeighbors) { if (temp.getHeuristicDistance() != Integer.MAX_VALUE) { frontier.add(temp); } } } return myMaze.getCell(myMaze.getGoalX(), myMaze.getGoalY()).getPath().toCharArray(); }