i know after debugging that sons list is changed
i don't know why it is changed
and this modification causes me problems in my algorithm
public class IDS extends Algo {
public State found = null;
public IDS(char[][] input, int size) {
super(input, size);
}
public String solve() {
State root = new State(0, 0, 0, 0, "", 0, 0);
for (int i = 0; i < size * size; i++) {
found = DLS(root, i);
if (found != null) {
return found.path + " " + found.dist;
}
}
return "no path";
}
private State DLS(State node, int depth) {
if (depth == 0 && super.inp[node.row][node.col] == 'G') {
return node;
}
if (depth > 0) {
// List<State> sons = super.find_neighbors(node.row, node.col, node.prod_time);
// for (int j = 0; j < sons.size(); j++) {
//State cur = sons.get(j);
for(State cur : super.find_neighbors(node.row, node.col, node.prod_time)){
cur.addCost(node.dist);
cur.path = cur.addpath(node.path);
found = DLS(cur, depth - 1);
if (found != null) {
return found;
}
}
}
return null;
}
}
here is the abstract class:
abstract class Algo {
public static Map<Integer,String> ways = new TreeMap<>();
protected char[][]inp;
protected int size;
private Map<Character,Integer>costs = new HashMap<>();
public List<State>sons = new ArrayList<>();
public Algo(){}
public Algo(char[][] input,int size){
inp = input;
this.size = size;
ways.put(1,"R");
ways.put(2,"RD");
ways.put(3,"D");
ways.put(4,"LD");
ways.put(5,"L");
ways.put(6,"LU");
ways.put(7,"U");
ways.put(8,"RU");
costs.put('R',1);
costs.put('D',3);
costs.put('H',10);
costs.put('G',0);
costs.put('S',0);
}
private void addDirection(int row,int col,int prod, int loc){
int cos = costs.get(inp[row][col]);
State s = new State(row,col,0,prod,"",loc,cos);
sons.add(s);
}
public abstract String solve();
//gets the parent i,j and the prod_t of the sons
public List<State> find_neighbors(int i, int j,int prod_t){
List<String>openD = new ArrayList<>();
sons.clear();
if(j+1 < size) {//right
if (inp[i][j + 1] != 'W') {
addDirection(i, j + 1, prod_t, 1);
openD.add("R");
}
}
if(i-1 >= 0) {
if (inp[i - 1][j] != 'W') {//up
addDirection(i - 1, j, prod_t, 7);
openD.add("U");
}
}
if(i+1 < size) {
if (inp[i + 1][j] != 'W') {//down
addDirection(i + 1, j, prod_t, 3);
openD.add("D");
}
}
if(j-1 >= 0){
if(inp[i][j-1]!='W'){//left
addDirection(i,j-1,prod_t,5);
openD.add("L");
}
}
if(openD.contains("L")){
if(openD.contains("U")){
if(inp[i-1][j-1]!='W'){
addDirection(i-1,j-1,prod_t,6);
}
}
if(openD.contains("D")){
if(inp[i+1][j-1]!='W'){
addDirection(i+1,j-1,prod_t,4);
}
}
}
if(openD.contains("R")){
if(openD.contains("U")) {
if (inp[i - 1][j + 1] != 'W') {
addDirection(i - 1, j + 1, prod_t, 8);
}
}
if(openD.contains("D")){
if(inp[i+1][j+1]!='W'){
addDirection(i+1,j+1,prod_t,2);
}
}
}
return sons;
}
}
the exception just helped me know the list has modified however still don't know why :
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at IDS.DLS(IDS.java:33)
at IDS.solve(IDS.java:17)
at ex1.main(ex1.java:34)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
super.find_neighbors modifies and returns the sons list. Inside your loop the method DLS is recursively called which calls super.find_neighbors again (modifying the same list that is currently iterated one recursion above). Because the list is changed during you iterate over it the exception is thrown.
You are doings a sons.clear() inside Algo.find_neighbours() That will cause the ConcurrentModification in the loop. Moreover, since find_neighbours() always return an empty List, what's the poingt in trying to iterate over it?
Related
For example I have 2d matrix like this:
.X..X..
2...2..
..X.1..
2.....X
Starting at (0,0),I can move down 1 cell or right 1 cell at a time, cell 'X' is an obstacle. Find the path with maximum sum. The answer for the above input is: DRRRRRD (D for down, R for right)
I could find the sum using dfs and a DP array but I don't know how can I trace the optimal path with this approach.
public static int dfs(char[][] matrix, int i, int j, int[][] cache) {
if (cache[i][j] != 0) {
return cache[i][j];
}
if (matrix[i][j] != 'X' && matrix[i][j] != 'x' && matrix[i][j] != '.') {
cache[i][j] += Character.getNumericValue(matrix[i][j]);
}
int iDown = i + 1;
int jRight = j + 1;
int dirDown = cache[i][j];
int dirRight = cache[i][j];
if (iDown < matrix.length && matrix[iDown][j] != 'X' && matrix[iDown][j] != 'x') {
dirDown += dfs(matrix, iDown, j, cache);
}
if (jRight < matrix[0].length && matrix[i][jRight] != 'X' && matrix[i][jRight] != 'x') {
dirRight += dfs(matrix, i, jRight, cache);
}
cache[i][j] = Math.max(dirDown, dirRight);
return cache[i][j];
}
You can modify dfs to keep track of the path and have it return a pair of Integer (the sum) and a String representing the path:
import java.util.Map;
import java.util.Map.Entry;
class Main {
public static void main(String[] args) {
char[][] matrix = {
{'.','X','.','.','X','.','.'},
{'2','.','.','.','2','.','.'},
{'.','.','X','.','1','.','.'},
{'2','.','.','.','.','.','X'}
};
Entry<Integer, String> result = dfs(matrix,0,0,new int[matrix.length][matrix[0].length],"");
System.out.println(result.getKey() +" "+ result.getValue());
}
//Entry is used as a container for an int-string pair
public static Entry<Integer, String> dfs(char[][] matrix, int i, int j, int[][] cache, String path) {
cache[i][j]=0;//clear previous sum
if (matrix[i][j] != 'X' && matrix[i][j] != 'x' && matrix[i][j] != '.') {
cache[i][j] += Character.getNumericValue(matrix[i][j]);
}
int iDown = i + 1;
int jRight = j + 1;
Entry<Integer,String> resultDown = null;
Entry<Integer,String> resultRight = null;
if (iDown < matrix.length && matrix[iDown][j] != 'X' && matrix[iDown][j] != 'x') {
resultDown = dfs(matrix, iDown, j, cache, path+"D");
if(resultDown.getKey() <= 0) { //no values found
resultDown = null;
}
}
if (jRight < matrix[0].length && matrix[i][jRight] != 'X' && matrix[i][jRight] != 'x') {
resultRight = dfs(matrix, i, jRight, cache, path+"R");
if(resultRight.getKey() <= 0) { //no values found
resultRight = null;
}
}
//no values found moving right or down
if(resultDown == null && resultRight == null) return Map.entry(cache[i][j], path);
String newPath = path;
if(resultDown != null && resultRight != null){ //values found in both directions
if(resultDown.getKey() > resultRight.getKey()) {
cache[i][j]+= resultDown.getKey();
newPath = resultDown.getValue();
}else {
cache[i][j] += resultRight.getKey();
newPath = resultRight.getValue();
}
}else /*values found only in one direction*/if(resultDown != null ) {
cache[i][j] += resultDown.getKey();
newPath = resultDown.getValue();
}else{
cache[i][j] += resultRight.getKey();
newPath = resultRight.getValue();
}
return Map.entry(cache[i][j] , newPath);
}
}
A better and more Object Oriented approach is to define a Node object, for example:
class Node {
private final char value;
private String direction;
private Node child = null;
private int sum = 0;
public Node(char value) {
this.value = value;
}
public String getDirection() {
return direction;
}
public void setDirection(String direction) {
this.direction = direction;
}
public Node getChild() {
return child;
}
public void setChild(Node parent) {
child = parent;
}
public char getValue() {
return value;
}
public int getSum() {
return sum;
}
public void addToSum(int add) {
sum += add;
}
}
and run dfs on a graph of Nodes (for example Node[][]).
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
The goal is to draw a maze after resolving it (using BFS) with the shortest path from start to exit.
OUTPUT must be like this
***************************************************
[20,19]
***************************************************
#####################
..#...........#.....#
#.#.#########.#.###.#
#...#.........#.#...#
###############.#.###
#.....#.......#.#...#
#.#######.###.#.#.#.#
#...#...#...#...#.#.#
###.###.###.###.#.#.#
#.#.#.#...#.#...#.#.#
#.#.#.#.#1#.#.###.#.#
#...#.#.#1#.#...#.#.#
#####.###1#.#####.###
#.#1111111#.#...#...#
#.#1#######.#.#.###.#
#.#1#...#...#.#.#...#
#.#1###.#.#####.#####
#.#11111111111111111#
#.##.####.#########1#
#..................11
#####################
There are many path to go to the exit [20,19] , but we must draw with the shortest path.
My code is below but it doesn't print the shortest path.
CODE
class Maze {
public static void main(String args[]) {
int W = 21;
int H = 21;
int X = 9;
int Y = 10;
String[] mazeString = {
"##########.##########",
"..#...........#.....#",
"#.#.#########.#.###.#",
"#...#.........#.#...#",
"###############.#.###",
"#.....#.......#.#...#",
"#.#######.###.#.#.#.#",
"#...#...#...#...#.#..",
"###.###.###.###.#.#.#",
"#.#.#.#...#.#...#.#.#",
"#.#.#.#.#.#.#.###.#.#",
"#...#.#.#.#.#...#.#.#",
"#####.###.#.#####.###",
"#.#.......#.#...#...#",
"#.#.#######.#.#.###.#",
"#.#.#...#...#.#.#...#",
"#.#.###.#.#####.#####",
"#.#.................#",
"#.##.####.#########.#",
"#.........#..........",
"####.######.#########"
};
Node[][] nodes = new Node[W][H];
Node start = null;
List<Node> result = new ArrayList<>();
Boolean[][] visited = new Boolean[W][H];
Boolean[][] blocked = new Boolean[W][H];
Boolean[][] exits = new Boolean[W][H];
for (int i = 0; i < H; i++) {
String R = mazeString[i];
for (int j = 0; j < W; j++) {
Node node = new Node(j, i);
blocked[j][i] = R.charAt(j) == '#';
node.blocked = R.charAt(j) == '#';
exits[j][i] = (!node.blocked) && (i == (H - 1) || j == (W - 1) || i == 0 || j == 0);
visited[j][i] = false;
node.exit = (!node.blocked) && (i == (H - 1) || j == (W - 1) || i == 0 || j == 0);
nodes[j][i] = node;
if (X == j && Y == i) {
start = nodes[j][i];
}
}
}
List<List<Node>> paths = new ArrayList<>();
findExits(start, nodes, visited, W, H, result, paths);
if (!result.isEmpty()) {
Collections.sort(result, new Comparator<Node>() {
#Override
public int compare(Node o1, Node o2) {
if (Integer.compare(o1.x, o2.x) == 0) {
return Integer.compare(o1.y, o2.y);
} else {
return Integer.compare(o1.x, o2.x);
}
}
});
}
for (List<Node> path : paths) {
System.out.println("***************************************************");
System.out.println("[" + path.get(0).x + "," + path.get(0).y + "]");
System.out.println("***************************************************");
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
String s = blocked[j][i] ? "#" : path.contains(new Node(j, i)) ? "1" : ".";
System.out.print(s);
}
System.out.println("");
}
}
}
public static void findExits(Node start, Node[][] nodes, Boolean[][] visited, int W, int H, List<Node> result, List<List<Node>> paths) {
int x = start.x;
int y = start.y;
visited[x][y] = true;
if (start.exit) {
result.add(start);
visited[x][y] = false;
List<Node> path = new ArrayList<Node>();
while (start.parent != null) {
path.add(start);
start = start.parent;
}
path.add(start);
paths.add(path);
}
//TOP
if ((y - 1) >= 0) {
if (!visited[x][y - 1] && (!nodes[x][y - 1].blocked)) {
nodes[x][y - 1].parent = start;
findExits(nodes[x][y - 1], nodes, visited, W, H, result, paths);
}
}
//BOT
if ((y + 1) < H) {
if (!visited[x][y + 1] && (!nodes[x][y + 1].blocked)) {
nodes[x][y + 1].parent = start;
findExits(nodes[x][y + 1], nodes, visited, W, H, result, paths);
}
}
//LEFT
if ((x - 1) >= 0) {
if (!visited[x - 1][y] && (!nodes[x - 1][y].blocked)) {
nodes[x - 1][y].parent = start;
findExits(nodes[x - 1][y], nodes, visited, W, H, result, paths);
}
}
//RIGHT
if ((x + 1) < W) {
if (!visited[x + 1][y] && (!nodes[x + 1][y].blocked)) {
nodes[x + 1][y].parent = start;
findExits(nodes[x + 1][y], nodes, visited, W, H, result, paths);
}
}
}
public static class Node {
public int x, y;
boolean blocked = false;
boolean exit = false;
Node parent = null;
public Node(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Node other = (Node) obj;
if (this.x != other.x) {
return false;
}
if (this.y != other.y) {
return false;
}
return true;
}
}
}
I want to solve a maze and print the shortest path from start to exit usign BFS. I already solve the maze but my code doesnt print the shortest path, this is my problem.
NB (Additional informations, not questions) :
the maze can have many exit
W (width), H (height), [X,Y] (start point)
'#' (blocked cell), '.' (free cell)
the path from start and exit is represented by '11111...' on the output
Please review the following code. It lets you printout all paths found, as well as the shortest one found.
I did not change nor checked the search algorithm. I think it needs more work because I think it does not find the shortest path possible to each exit. I will look into it later.
I did not figure out yet what is the use of List<Node> result. Also I did not see you implement backtracking.
class Maze {
private static char NUMBER_SIGN = '#', DOT = '.', START = 'S';
private static char EXIT = 'E', PATH = '1';
private static Node[][] nodes;
private static Node start;
private static boolean[][] visited; //no need to use Boolean
//exit holds the same information as Node.blocked. No need to duplicate
//private static boolean[][] blocked;
//exit holds the same information as Node.exit. No need to duplicate
//private static boolean[][] exits;
private static int mazeWidth, mazeHeight, startH, startW; //use meaningful names
private static List<List<Node>> paths;
public static void main(String args[]) {
mazeWidth = 21;//use meaningful names
mazeHeight = 21;
startH = 9; startW = 10;
String[] mazeData = getMazeData() ;
makeMaze(mazeData);
drawMaze(); //draw maze as built from input data
List<Node> result = new ArrayList<>();
paths = new ArrayList<>();
findExits(start, nodes, visited, mazeWidth, mazeHeight, result, paths);
if (!result.isEmpty()) {
Collections.sort(result, new Comparator<Node>() {
#Override
public int compare(Node o1, Node o2) {
if (Integer.compare(o1.x, o2.x) == 0) {
return Integer.compare(o1.y, o2.y);
} else {
return Integer.compare(o1.x, o2.x);
}
}
});
}
drawAllPaths(); // see all paths found
List<Node> shortestPath = getShortestPath();
drawShortestPath(shortestPath);
}
private static void drawMaze() {
System.out.println("***************************************************");
System.out.println("Maze as defined by input");
System.out.println("***************************************************");
drawMaze(null);
}
private static void drawAllPaths() {
for (List<Node> path : paths) {
System.out.println("***************************************************");
System.out.println("Path to exit ["
+ path.get(0).x + "," + path.get(0).y + "] length:"+ path.size());
System.out.println("***************************************************");
drawMaze(path);
}
}
private static void drawShortestPath(List<Node> path) {
System.out.println("***************************************************");
System.out.println("Shortest path is to exit ["
+ path.get(0).x + "," + path.get(0).y + "] length:"+ path.size());
System.out.println("***************************************************");
drawMaze(path);
}
private static void drawMaze(List<Node> path) {
for(Node[] row : nodes ) {
for(Node node : row) {
char c = node.getGraphics();
if ((path != null) && path.contains(node)) {c = PATH;}
System.out.print(c);
}
System.out.println("");
}
}
private static void makeMaze(String[] mazeData) {
nodes = new Node[mazeHeight][mazeWidth];
visited = new boolean[mazeHeight][mazeWidth];
for (int height = 0; height < mazeHeight; height++) {
String row = mazeData[height];
for (int width = 0; width < mazeWidth; width++) {
Node node = new Node(height, width);
node.blocked = row.charAt(width) == NUMBER_SIGN;
visited[width][height] = false;
node.exit = (!node.blocked) && ((height == (mazeHeight - 1)) ||
(width == (mazeWidth - 1)) || (height == 0) || (width == 0));
nodes[height][width] = node;
}
}
start = nodes[startH][startW];//no need to set it in the loop
}
//use boolean instead of Boolean
private static void findExits(Node start, Node[][] nodes,
boolean[][] visited, int W, int H, List<Node> result, List<List<Node>> paths) {
int x = start.x;
int y = start.y;
visited[x][y] = true;
if (start.exit) {
result.add(start);
visited[x][y] = false;
List<Node> path = new ArrayList<>();
while (start.parent != null) {
path.add(start);
start = start.parent;
}
path.add(start);
paths.add(path);
}
//TOP
if ((y - 1) >= 0) {
if (!visited[x][y - 1] && (!nodes[x][y - 1].blocked)) {
nodes[x][y - 1].parent = start;
findExits(nodes[x][y - 1], nodes, visited, W, H, result, paths);
}
}
//BOT
if ((y + 1) < H) {
if (!visited[x][y + 1] && (!nodes[x][y + 1].blocked)) {
nodes[x][y + 1].parent = start;
findExits(nodes[x][y + 1], nodes, visited, W, H, result, paths);
}
}
//LEFT
if ((x - 1) >= 0) {
if (!visited[x - 1][y] && (!nodes[x - 1][y].blocked)) {
nodes[x - 1][y].parent = start;
findExits(nodes[x - 1][y], nodes, visited, W, H, result, paths);
}
}
//RIGHT
if ((x + 1) < W) {
if (!visited[x + 1][y] && (!nodes[x + 1][y].blocked)) {
nodes[x + 1][y].parent = start;
findExits(nodes[x + 1][y], nodes, visited, W, H, result, paths);
}
}
}
public static class Node {
public int x, y;
boolean blocked = false;
boolean exit = false;
Node parent = null;
public Node(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Node other = (Node) obj;
if (x != other.x) {
return false;
}
if (y != other.y) {
return false;
}
return true;
}
//it is simpler to have Node return its graphic representation
char getGraphics() {
char c = blocked ? NUMBER_SIGN : DOT;
if(equals(start)) { c=START;}
else if (exit) { c=EXIT;}
return c;
}
}
private static List<Node> getShortestPath() {
//initialize with an arbitrary path
List<Node> shortest = paths.get(0);
for (List<Node> path : paths) {
if(path.size() < shortest.size()) {
shortest = path;
}
}
return shortest;
}
private static String[] getMazeData() {
return new String[] {
"##########.##########",
"..#...........#.....#",
"#.#.#########.#.###.#",
"#...#.........#.#...#",
"###############.#.###",
"#.....#.......#.#...#",
"#.#######.###.#.#.#.#",
"#...#...#...#...#.#..",
"###.###.###.###.#.#.#",
"#.#.#.#...#.#...#.#.#",
"#.#.#.#.#.#.#.###.#.#",
"#...#.#.#.#.#...#.#.#",
"#####.###.#.#####.###",
"#.#.......#.#...#...#",
"#.#.#######.#.#.###.#",
"#.#.#...#...#.#.#...#",
"#.#.###.#.#####.#####",
"#.#.................#",
"#.##.####.#########.#",
"#.........#..........",
"####.######.#########"
};
}
}
EDIT
An improved version. Please test carefully.
class Maze {
private static char NUMBER_SIGN = '#', DOT = '.', START = 'S';
private static char EXIT = 'E', PATH = '1';
private static Node[][] nodes;
private static Node startNode;
private static boolean[][] visited; //no need to use Boolean
//exit holds the same information as Node.blocked. No need to duplicate
//private static boolean[][] blocked;
//exit holds the same information as Node.exit. No need to duplicate
//private static boolean[][] exits;
private static int mazeRows, mazeCols, startRow, startCol; //use meaningful names
private static List<List<Node>> paths;
public static void main(String args[]) {
mazeCols = 21; mazeRows = 21;//use meaningful and consistent names
startRow = 9; startCol = 10; //better keep h,w or height,width all over
String[] mazeData = getMazeData() ;
makeMaze(mazeData);
drawMaze(); //draw maze as built from input data
paths = new ArrayList<>();
findExits(startNode);
drawAllPaths(); // print all paths found
List<Node> shortestPath = getShortestPath();
drawShortestPath(shortestPath);
}
private static void drawMaze() {
System.out.println("*****************************************");
System.out.println("Maze as defined by input");
System.out.println("*****************************************");
drawMaze(null);
}
private static void drawAllPaths() {
for (List<Node> path : paths) {
System.out.println("*****************************************");
System.out.println("Path to exit ["
+ path.get(0).row + "," + path.get(0).col + "] length:"+ path.size());
System.out.println("*****************************************");
drawMaze(path);
}
}
private static void drawShortestPath(List<Node> path) {
System.out.println("*****************************************");
System.out.println("Shortest path is to exit ["
+ path.get(0).row + "," + path.get(0).col + "] length:"+ path.size());
System.out.println("*****************************************");
drawMaze(path);
}
private static void drawMaze(List<Node> path) {
for(Node[] row : nodes ) {
for(Node node : row) {
char c = node.getGraphics();
//overwrite c if node is in path
if ( (c != EXIT) && ( c != START ) &&
(path != null) && path.contains(node)) {c = PATH;}
System.out.print(c);
}
System.out.println("");
}
}
private static void makeMaze(String[] mazeData) {
nodes = new Node[mazeRows][mazeCols];
visited = new boolean[mazeRows][mazeCols];
for (int rowIndex = 0; rowIndex < mazeRows; rowIndex++) {
String row = mazeData[rowIndex];
for (int colIndex = 0; colIndex < mazeCols; colIndex++) {
Node node = new Node(rowIndex, colIndex);
node.blocked = row.charAt(colIndex) == NUMBER_SIGN;
visited[rowIndex][colIndex] = false;
node.exit = (!node.blocked) && ((rowIndex == (mazeRows - 1)) ||
(colIndex == (mazeCols - 1)) || (rowIndex == 0) || (colIndex == 0));
nodes[rowIndex][colIndex] = node;
}
}
startNode = nodes[startRow][startCol];//no need to set it in the loop
}
//use boolean instead of Boolean
private static void findExits(Node node) {
int row = node.row;
int col = node.col;
if(visited[row][col]) { return; }
if (node.exit) {
List<Node> path = new ArrayList<>();
while (node.parent != null) {
path.add(node);
node = node.parent;
}
path.add(node);
paths.add(path);
return; //do not continue to check exit neighbors
}
//LEFT
if ((col - 1) >= 0) {
Node testNode = nodes[row][col - 1];
//the following if statement repeats for all directions
//better put in a method
if ((testNode.parent == null) && ! testNode.blocked) {
testNode.parent = node; //parent ! null indicates that cell is tested
findExits(testNode);
testNode.parent = null; //set back to null: test finished
}
}
//RIGHT
if ((col + 1) < mazeCols) {
Node testNode = nodes[row][col + 1];
if ((testNode.parent == null) && ! testNode.blocked) {
testNode.parent = node;
findExits(testNode);
testNode.parent = null;
}
}
//TOP
if ((row - 1) >= 0) {
Node testNode = nodes[row-1][col];
if ((testNode.parent == null) && ! testNode.blocked) {
testNode.parent = node;
findExits(testNode);
testNode.parent = null;
}
}
//BOTTOM
if ((row + 1) < mazeRows) {
Node testNode = nodes[row+1][col];
if ((testNode.parent == null) && ! testNode.blocked) {
testNode.parent = node;
findExits(testNode);
testNode.parent = null;
}
}
visited[row][col] = true; //mark as visited after all directions explored
node.parent = null;
}
public static class Node {
public int row, col;
boolean blocked = false;
boolean exit = false;
Node parent = null;
public Node(int row, int col) {
this.row = row;
this.col = col;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Node other = (Node) obj;
if (row != other.row) {
return false;
}
if (col != other.col) {
return false;
}
return true;
}
//it is simpler to have Node return its graphic representation
char getGraphics() {
char c = blocked ? NUMBER_SIGN : DOT;
if(equals(startNode)) { c=START;}
else if (exit) { c=EXIT;}
return c;
}
#Override
public String toString() {
return "Node " + row +"-"+ col +" ("+ getGraphics() + ")";
}
}
private static List<Node> getShortestPath() {
//initialize with an arbitrary path
List<Node> shortest = paths.get(0);
for (List<Node> path : paths) {
if(path.size() < shortest.size()) {
shortest = path;
}
}
return shortest;
}
private static String[] getMazeData() {
return new String[] {
"##########.##########",
"..#...........#.....#",
"#.#.#########.#.###.#",
"#...#.........#.#...#",
"###############.#.###",
"#.....#.......#.#...#",
"#.#######.###.#.#.#.#",
"#...#...#...#...#.#..",
"###.###.###.###.#.#.#",
"#.#.#.#...#.#...#.#.#",
"#.#.#.#.#.#.#.###.#.#",
"#...#.#.#.#.#...#.#.#",
"#####.###.#.#####.###",
"#.#.......#.#...#...#",
"#.#.#######.#.#.###.#",
"#.#.#...#...#.#.#...#",
"#.#.###.#.#####.#####",
"#.#.................#",
"#.##.####.#########.#",
"#.........#..........",
"####.######.#########"
};
}
}
Feedback would be appreciated.
You're on the right track where you're building a list of paths.
Try this:
create an empty list of paths
start at the starting point, create one path with one cell
look in the four directions and for each cell that is not blocked and not already included in any of the previous paths clone your current path, add that new cell to the end and add it to the list of paths
now loop through all your paths and repeat this progress, checking the four directions from the cell at the tip
stop building a path when it hits the exit or has no more legitimate moves to make, i.e. dead end
use the path with the shortest length
I'm looking to generate a specific output with my fibonacci recursive method. I already have the recursive code. However the output should display the fibonacci number(one per line) and also the ratio of the current and previous fibonacci numbers on each line.
(if user enters 5)
Fib#1=0
Fib#2=1
Fib#3=1; 1/1=1
Fib#4=2; 2/1=2
Fib#5=3; 3/2=1
this is the code i have so far:
if(n == 0)
return "0";
else if(n == 1)
return "1";
else
return FibonacciCalc(n - 1) + FibonacciCalc(n - 2);
How do i make that output? Should i return a String or make a different print method? Thanks
The problem with this recursive function is that it would be very inefficient as it has the calculate the whole range every time. Better to do this in a loop.
int beforeLastNumber = 1;
int lastNumber = 1;
System.out.println("0");
System.out.println("1");
for(int number=2; number<max; number++) {
int nextNumber = beforeLastNumber + lastNumber;
beforeLastNumber = lastNumber;
lastNumber = nextNumber;
System.out.println(nextNumber);
}
The above keeps a running total of where we're at, which avoid recalculating a sum of lots of numbers to get the higher ones.
Try this:
public class fib {
public static int FibonnaciCalc(int n) {
if (n == 0)
return 0;
else if (n == 1)
return 1;
else
return FibonnaciCalc(n - 1) + FibonnaciCalc(n - 2);
}
public static void main(String[] args) {
final List<Integer> fibList = new ArrayList<Integer>();
int limit = 5;
for (int i = 0; i < limit; i++)
fibList.add(FibonnaciCalc(i));
int tmp = 0;
for (int i=0;i<fibList.size();i++) {
tmp=i+1;
if (i <2)
System.out.println("Fib#" + tmp + "=" + fibList.get(i));
else
System.out.println("Fib#" + tmp + "=" + fibList.get(i)+"; "+fibList.get(i) +"/"+fibList.get(i-1)+"="+fibList.get(i)/fibList.get(i-1));
}
}
}
Recursive fibonacci output
class FibonacciContext {
int beforePrevious;
int previous;
public FibonacciContext(int beforePrevious, int previous) {
this.beforePrevious = beforePrevious;
this.previous = previous;
}
public int getBeforePrevious() {
return beforePrevious();
}
public int getPrevious() {
return previous;
}
public int getNext() {
return beforePrevious + previous;
}
public FibonnaciContext getNextContext() {
return new FibonnaciContext(previous, getNext());
}
}
public FibonacciContext outputFibonacciNumbers(int maxIndex) {
// 0 and 1 are 0 and 1 - non recursive termination
if (maxIndex<2) {
System.out.println(maxIndex);
return new FibonnaciContext(0, maxIndex);
}
// output all previous numbers before this one
FibonnaciContext context = outputFibonacciNumbers(maxIndex-1);
// print out this one
System.out.println(context.getNext());
// context passed back to the recursive call
return context.getNextContext();
}
Try this one:
public static void main(String[] args) {
new Main().f(5);
}
private void f(final int i) {
if (i > 2) {
f(i - 1);
System.out.println(String.format("Fib#%1$d=%2$d; %2$d/%3$d=%4$d", i, fib(i-1), fib(i-2), fib(i-1)/fib(i-2)));
} else if (i > 0) {
f(i - 1);
System.out.println(String.format("Fib#%1$d=%2$d", i, fib(i-1)));
}
}
private int fib(final int i) {
if (i == 0) {
return 0;
} else if (i == 1) {
return 1;
} else {
return fib(i - 2) + fib(i - 1);
}
}
For an assignment, we were instructed to create a priority queue implemented via a binary heap, without using any built-in classes, and I have done so successfully by using an array to store the queued objects. However, I'm interested in learning how to implement another queue by using an actual tree structure, but in doing so I've run across a bit of a problem.
How would I keep track of the nodes on which I would perform insertion and deletion? I have tried using a linked list, which appends each node as it is inserted - new children are added starting from the first list node, and deleted from the opposite end. However, this falls apart when elements are rearranged in the tree, as children are added at the wrong position.
Edit: Perhaps I should clarify - I'm not sure how I would be able to find the last occupied and first unoccupied leaves. For example, I would always be able to tell the last inserted leaf, but if I were to delete it, how would I know which leaf to delete when I next remove the item? The same goes for inserting - how would I know which leaf to jump to next after the current leaf has both children accounted for?
A tree implementation of a binary heap uses a complete tree [or almost full tree: every level is full, except the deepest one].
You always 'know' which is the last occupied leaf - where you delete from [and modifying it is O(logn) after it changed so it is not a problem], and you always 'know' which is the first non-occupied leaf, in which you add elements to [and again, modifying it is also O(logn) after it changed].
The algorithm idea is simple:
insert: insert element to the first non-occupied leaf, and use heapify [sift up] to get this element to its correct place in the heap.
delete_min: replace the first element with the last occupied leaf, and remove the last occupied leaf. then, heapify [sift down] the heap.
EDIT: note that delete() can be done to any element, and not only the head, however - finding the element you want to replace with the last leaf will be O(n), which will make this op expensive. for this reason, the delete() method [besides the head], is usually not a part of the heap data structure.
I really wanted to do this for almost a decade.Finally sat down today and wrote it.Anyone who wants it can use it.I got inspired by Quora founder to relearn Heap.Apparently he was asked how would you find K near points in a set of n points in his Google phone screen.Apparently his answer was to use a Max Heap and to store K values and remove the maximum element after the size of the heap exceeds K.The approach is pretty simple and the worst case is nlog K which is better than n^2 in most sorting cases.Here is the code.
import java.util.ArrayList;
import java.util.List;
/**
* #author Harish R
*/
public class HeapPractise<T extends Comparable<T>> {
private List<T> heapList;
public List<T> getHeapList() {
return heapList;
}
public void setHeapList(List<T> heapList) {
this.heapList = heapList;
}
private int heapSize;
public HeapPractise() {
this.heapList = new ArrayList<>();
this.heapSize = heapList.size();
}
public void insert(T item) {
if (heapList.size() == 0) {
heapList.add(item);
} else {
siftUp(item);
}
}
public void siftUp(T item) {
heapList.add(item);
heapSize = heapList.size();
int currentIndex = heapSize - 1;
while (currentIndex > 0) {
int parentIndex = (int) Math.floor((currentIndex - 1) / 2);
T parentItem = heapList.get(parentIndex);
if (parentItem != null) {
if (item.compareTo(parentItem) > 0) {
heapList.set(parentIndex, item);
heapList.set(currentIndex, parentItem);
currentIndex = parentIndex;
continue;
}
}
break;
}
}
public T delete() {
if (heapList.size() == 0) {
return null;
}
if (heapList.size() == 1) {
T item = heapList.get(0);
heapList.remove(0);
return item;
}
return siftDown();
}
public T siftDown() {
T item = heapList.get(0);
T lastItem = heapList.get(heapList.size() - 1);
heapList.remove(heapList.size() - 1);
heapList.set(0, lastItem);
heapSize = heapList.size();
int currentIndex = 0;
while (currentIndex < heapSize) {
int leftIndex = (2 * currentIndex) + 1;
int rightIndex = (2 * currentIndex) + 2;
T leftItem = null;
T rightItem = null;
int currentLargestItemIndex = -1;
if (leftIndex <= heapSize - 1) {
leftItem = heapList.get(leftIndex);
}
if (rightIndex <= heapSize - 1) {
rightItem = heapList.get(rightIndex);
}
T currentLargestItem = null;
if (leftItem != null && rightItem != null) {
if (leftItem.compareTo(rightItem) >= 0) {
currentLargestItem = leftItem;
currentLargestItemIndex = leftIndex;
} else {
currentLargestItem = rightItem;
currentLargestItemIndex = rightIndex;
}
} else if (leftItem != null && rightItem == null) {
currentLargestItem = leftItem;
currentLargestItemIndex = leftIndex;
}
if (currentLargestItem != null) {
if (lastItem.compareTo(currentLargestItem) >= 0) {
break;
} else {
heapList.set(currentLargestItemIndex, lastItem);
heapList.set(currentIndex, currentLargestItem);
currentIndex = currentLargestItemIndex;
continue;
}
}
}
return item;
}
public static void main(String[] args) {
HeapPractise<Integer> heap = new HeapPractise<>();
for (int i = 0; i < 32; i++) {
heap.insert(i);
}
System.out.println(heap.getHeapList());
List<Node<Integer>> nodeArray = new ArrayList<>(heap.getHeapList()
.size());
for (int i = 0; i < heap.getHeapList().size(); i++) {
Integer heapElement = heap.getHeapList().get(i);
Node<Integer> node = new Node<Integer>(heapElement);
nodeArray.add(node);
}
for (int i = 0; i < nodeArray.size(); i++) {
int leftNodeIndex = (2 * i) + 1;
int rightNodeIndex = (2 * i) + 2;
Node<Integer> node = nodeArray.get(i);
if (leftNodeIndex <= heap.getHeapList().size() - 1) {
Node<Integer> leftNode = nodeArray.get(leftNodeIndex);
node.left = leftNode;
}
if (rightNodeIndex <= heap.getHeapList().size() - 1) {
Node<Integer> rightNode = nodeArray.get(rightNodeIndex);
node.right = rightNode;
}
}
BTreePrinter.printNode(nodeArray.get(0));
}
}
public class Node<T extends Comparable<?>> {
Node<T> left, right;
T data;
public Node(T data) {
this.data = data;
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class BTreePrinter {
public static <T extends Comparable<?>> void printNode(Node<T> root) {
int maxLevel = BTreePrinter.maxLevel(root);
printNodeInternal(Collections.singletonList(root), 1, maxLevel);
}
private static <T extends Comparable<?>> void printNodeInternal(
List<Node<T>> nodes, int level, int maxLevel) {
if (nodes.isEmpty() || BTreePrinter.isAllElementsNull(nodes))
return;
int floor = maxLevel - level;
int endgeLines = (int) Math.pow(2, (Math.max(floor - 1, 0)));
int firstSpaces = (int) Math.pow(2, (floor)) - 1;
int betweenSpaces = (int) Math.pow(2, (floor + 1)) - 1;
BTreePrinter.printWhitespaces(firstSpaces);
List<Node<T>> newNodes = new ArrayList<Node<T>>();
for (Node<T> node : nodes) {
if (node != null) {
String nodeData = String.valueOf(node.data);
if (nodeData != null) {
if (nodeData.length() == 1) {
nodeData = "0" + nodeData;
}
}
System.out.print(nodeData);
newNodes.add(node.left);
newNodes.add(node.right);
} else {
newNodes.add(null);
newNodes.add(null);
System.out.print(" ");
}
BTreePrinter.printWhitespaces(betweenSpaces);
}
System.out.println("");
for (int i = 1; i <= endgeLines; i++) {
for (int j = 0; j < nodes.size(); j++) {
BTreePrinter.printWhitespaces(firstSpaces - i);
if (nodes.get(j) == null) {
BTreePrinter.printWhitespaces(endgeLines + endgeLines + i
+ 1);
continue;
}
if (nodes.get(j).left != null)
System.out.print("//");
else
BTreePrinter.printWhitespaces(1);
BTreePrinter.printWhitespaces(i + i - 1);
if (nodes.get(j).right != null)
System.out.print("\\\\");
else
BTreePrinter.printWhitespaces(1);
BTreePrinter.printWhitespaces(endgeLines + endgeLines - i);
}
System.out.println("");
}
printNodeInternal(newNodes, level + 1, maxLevel);
}
private static void printWhitespaces(int count) {
for (int i = 0; i < 2 * count; i++)
System.out.print(" ");
}
private static <T extends Comparable<?>> int maxLevel(Node<T> node) {
if (node == null)
return 0;
return Math.max(BTreePrinter.maxLevel(node.left),
BTreePrinter.maxLevel(node.right)) + 1;
}
private static <T> boolean isAllElementsNull(List<T> list) {
for (Object object : list) {
if (object != null)
return false;
}
return true;
}
}
Please note that BTreePrinter is a code I took somewhere in Stackoverflow long back and I modified to use with 2 digit numbers.It will be broken if we move to 3 digit numbers and it is only for simple understanding of how the Heap structure looks.A fix for 3 digit numbers is to keep everything as multiple of 3.
Also due credits to Sesh Venugopal for wonderful tutorial on Youtube on Heap data structure
public class PriorityQ<K extends Comparable<K>> {
private class TreeNode<T extends Comparable<T>> {
T val;
TreeNode<T> left, right, parent;
public String toString() {
return this.val.toString();
}
TreeNode(T v) {
this.val = v;
left = null;
right = null;
}
public TreeNode<T> insert(T val, int position) {
TreeNode<T> parent = findNode(position/2);
TreeNode<T> node = new TreeNode<T>(val);
if(position % 2 == 0) {
parent.left = node;
} else {
parent.right = node;
}
node.parent = parent;
heapify(node);
return node;
}
private void heapify(TreeNode<T> node) {
while(node.parent != null && (node.parent.val.compareTo(node.val) < 0)) {
T temp = node.val;
node.val = node.parent.val;
node.parent.val = temp;
node = node.parent;
}
}
private TreeNode<T> findNode(int pos) {
TreeNode<T> node = this;
int reversed = 1;
while(pos > 0) {
reversed <<= 1;
reversed |= (pos&1);
pos >>= 1;
}
reversed >>= 1;
while(reversed > 1) {
if((reversed & 1) == 0) {
node = node.left;
} else {
node = node.right;
}
reversed >>= 1;
}
return node;
}
public TreeNode<T> remove(int pos) {
if(pos <= 1) {
return null;
}
TreeNode<T> last = findNode(pos);
if(last.parent.right == last) {
last.parent.right = null;
} else {
last.parent.left = null;
}
this.val = last.val;
bubbleDown();
return null;
}
public void bubbleDown() {
TreeNode<T> node = this;
do {
TreeNode<T> left = node.left;
TreeNode<T> right = node.right;
if(left != null && right != null) {
T max = left.val.compareTo(right.val) > 0 ? left.val : right.val;
if(max.compareTo(node.val) > 0) {
if(left.val.equals(max)) {
left.val = node.val;
node.val = max;
node = left;
} else {
right.val = node.val;
node.val = max;
node = right;
}
} else {
break;
}
} else if(left != null) {
T max = left.val;
if(left.val.compareTo(node.val) > 0) {
left.val = node.val;
node.val = max;
node = left;
} else {
break;
}
} else {
break;
}
} while(true);
}
}
private TreeNode<K> root;
private int position;
PriorityQ(){
this.position = 1;
}
public void insert(K val) {
if(val == null) {
return;
}
if(root == null) {
this.position = 1;
root = new TreeNode<K>(val);
this.position++;
return ;
}
root.insert(val, position);
position++;
}
public K remove() {
if(root == null) {
return null;
}
K val = root.val;
root.remove(this.position-1);
this.position--;
if(position == 1) {
root = null;
}
return val;
}
public static void main(String[] args) {
PriorityQ<Integer> q = new PriorityQ<>();
System.out.println(q.remove());
q.insert(1);
q.insert(11);
q.insert(111);
q.insert(1111);
q.remove();
q.remove();
q.remove();
q.remove();
q.insert(2);
q.insert(4);
}
}
I've been trying all day to get this algorithm up and running, but I cant for the life of me. I've read many tutorials on the net, and source code in AS3, javascript, and C++; but I cannot adapt what I am seeing to my own code.
I have created an AStar class that has a nested class named Node. The map is a 2D array named MAP.
The biggest problem that I am having is pulling the F value in the pathfind function.
I have implemented the F = G + H, my problem is the actual AStar algorithm. Can someone please help, this is how far I've got as of yet:
import java.util.ArrayList;
public class AStar
{
int MAP[][];
Node startNode, endNode;
public AStar(int MAP[][], int startXNode, int startYNode,
int endXNode, int endYNode)
{
this.MAP = MAP;
startNode = new Node(startXNode, startYNode);
endNode = new Node(endXNode, endYNode);
}
public void pathfinder()
{
ArrayList openList = new ArrayList();
ArrayList closedList = new ArrayList();
}
public int F(Node startNode, Node endNode)
{
return (H(startNode, endNode) + G(startNode));
}
//H or Heuristic part of A* algorithm
public int H(Node startNode, Node endNode)
{
int WEIGHT = 10;
int distance = (Math.abs(startNode.getX() - endNode.getX()) + Math.abs(startNode.getY() - endNode.getY()));
return (distance * WEIGHT);
}
public int G(Node startNode)
{
if(MAP[startNode.getX() - 1][startNode.getY()] != 1)
{
return 10;
}
if(MAP[startNode.getX() + 1][startNode.getY()] != 1)
{
return 10;
}
if(MAP[startNode.getX()][startNode.getY() -1] != 1)
{
return 10;
}
if(MAP[startNode.getX()][startNode.getY() + 1] != 1)
{
return 0;
}
return 0;
}
public class Node
{
private int NodeX;
private int NodeY;
private int gScore;
private int hScore;
private int fScore;
public Node(int NodeX, int NodeY)
{
this.NodeX = NodeX;
this.NodeY = NodeY;
}
public int getX()
{
return NodeX;
}
public int getY()
{
return NodeY;
}
public int getG()
{
return gScore;
}
public void setG(int gScore)
{
this.gScore = gScore;
}
public int getH()
{
return hScore;
}
public void setH(int hScore)
{
this.hScore = hScore;
}
public int getF()
{
return fScore;
}
public void setF(int fScore)
{
this.fScore = fScore;
}
}
}
This is the furthest I can ever get with the pathfinder function:
public void pathfinder()
{
LinkedList<Node> openList = new LinkedList();
LinkedList<Node> closedList = new LinkedList();
Node currentNode;
openList.add(startNode);
while(openList.size() > 0)
{
currentNode = (Node) openList.get(0);
closedList.add(currentNode);
for(int i = 0; i < openList.size(); i++)
{
int cost = F(currentNode, endNode);
}
}
}
I recently threw this A* code together to solve a Project Euler problem. You'll have to fill in the details for a matrix of Node objects. Use it at your own risk, however I can say it solved the problem :)
public class Node {
List<Node> neighbors = new ArrayList<Node>();
Node parent;
int f;
int g;
int h;
int x;
int y;
int cost;
}
public List<Node> aStar(Node start, Node goal) {
Set<Node> open = new HashSet<Node>();
Set<Node> closed = new HashSet<Node>();
start.g = 0;
start.h = estimateDistance(start, goal);
start.f = start.h;
open.add(start);
while (true) {
Node current = null;
if (open.size() == 0) {
throw new RuntimeException("no route");
}
for (Node node : open) {
if (current == null || node.f < current.f) {
current = node;
}
}
if (current == goal) {
break;
}
open.remove(current);
closed.add(current);
for (Node neighbor : current.neighbors) {
if (neighbor == null) {
continue;
}
int nextG = current.g + neighbor.cost;
if (nextG < neighbor.g) {
open.remove(neighbor);
closed.remove(neighbor);
}
if (!open.contains(neighbor) && !closed.contains(neighbor)) {
neighbor.g = nextG;
neighbor.h = estimateDistance(neighbor, goal);
neighbor.f = neighbor.g + neighbor.h;
neighbor.parent = current;
open.add(neighbor);
}
}
}
List<Node> nodes = new ArrayList<Node>();
Node current = goal;
while (current.parent != null) {
nodes.add(current);
current = current.parent;
}
nodes.add(start);
return nodes;
}
public int estimateDistance(Node node1, Node node2) {
return Math.abs(node1.x - node2.x) + Math.abs(node1.y - node2.y);
}
I dont know if you are trying only to use simple types, or if you just didn't think about it, but you need to have a PriorityQueue to get your A* working.
A good way to think is that you put your startpoint into a priority queue with distance 0, and then start a loop that only stops when the prioriy queue is empty.
In the loop you take the min-node out, and check to see if it hasnt been open before, or if it has, if you have now found a shorter way to it.
If either these are true, you add the distance to the new node, add the edge/from-square to a map, and then add the distance + heuristic to the priority queue.
I have written this to work on a grid of booleans, and a constant conversion between 1D and 2D arrays, but I hope it is readable:
public void AStarRoute()
{
gridDist = new double[rows][cols];
System.out.println("Start of AStarRoute");
MinPriorityQueue pq = new MinPriorityQueue(rows * cols);
edgeTo = new HashMap<Integer, Integer>();
gridDist[x1Dto2D(start)][y1Dto2D(start)] = 0;
pq.insert(start, 0);
int from;
while (!pq.isEmpty()) {
from = pq.delMin();
int x = x1Dto2D(from);
int y = y1Dto2D(from);
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
int newX = x + i;
int newY = y + j;
if (newX >= 0 && newY >= 0 && newX < cols && newY < rows && !(i == 0 && j == 0)) {
if (grid[newX][newY]) {
//System.out.println("NewDist: " + gridDist[newX][newY] + " - OldDist+dist: " + (gridDist[x][y] + ((Math.abs(i) == Math.abs(j)) ? 1.4 : 1.0)) + ":" + (int)(gridDist[x][y] + ((Math.abs(i) == Math.abs(j)) ? 1.4 : 1.0)));
if (!edgeTo.containsKey(convert2Dto1D(newX, newY)) || gridDist[newX][newY] > (gridDist[x][y] + ((Math.abs(i) == Math.abs(j)) ? 14 : 10))) {
gridDist[newX][newY] = (int)(gridDist[x][y] + ((Math.abs(i) == Math.abs(j)) ? 14 : 10));
maxDistToEnd = (int)Math.max(maxDistToEnd, gridDist[newX][newY]);
edgeTo.put(convert2Dto1D(newX, newY), convert2Dto1D(x, y));
pq.insert(convert2Dto1D(newX, newY), gridDist[newX][newY] + (int)Math.sqrt(Math.pow((newX - x1Dto2D(end))*10, 2) + Math.pow((newY - y1Dto2D(end))*10, 2)));
if(convert2Dto1D(newX, newY) == end){
System.out.println("End found at (" + newX + ", " + newY + ")");
paintGridDist = true;
route = new ArrayList<Integer>();
int n = convert2Dto1D(newX, newY);
route.add(n);
do{
n = edgeTo.get(n);
route.add(n);
}while(start != n);
repaint();
return;
}
}
}
}
}
}
}
paintGridDist = true;
repaint();
}