Reputation: 373
In a number maze, a player always starts from the square at the upper left and makes a certain number of moves which will take him/her to the square marked Goal if a solution exist. The value in each cell in the maze indicates how far a player must move horizontally or vertically from its current position. My task is to find out if the shortest path to the cell labeled “Goal” and print it.
Input the maze is in the form of square 2D array. The goal square is indicated by the number -1 in the maze description. Output For the maze, output the solution of the maze or the phrase “No Solution Possible.” Solutions should be output as a list of square coordinates in the format “(Row, Column)”, in the order in which they are visited from the start to the goal, including the starting cell. You will need to report the shortest solution from start to the goal. The shortest solution will be unique. I have tried some solution, but I think there is problem that is the solution is always the first path I found not the shortest..
public class findShoretstPath
{
private static Stack<Node> stack = new Stack<>();
private static class Node
{
private int[] coordinate = new int[2];
private int data;
private Node Right, Left, Top, Bottom;
public Node(){}
}
public static boolean isValid(int[][] a, int x, int y)
{
if(x >= 0 && x < a.length && y >= 0 && y < a.length)
return true;
return false;
}
public static Node[][] nodeArray(int[][] a)
{
Node[][] nodeA = new Node[a.length][a.length];
for(int i = 0; i<nodeA.length; i++)
for(int j = 0; j<nodeA[i].length; j++)
{
nodeA[i][j] = new Node();
nodeA[i][j].coordinate[0] = i;
nodeA[i][j].coordinate[1] = j;
nodeA[i][j].data = a[i][j];
}
for(int i = 0; i<nodeA.length; i++)
for(int j = 0; j<nodeA[i].length; j++)
{
if(isValid(a, i, j+nodeA[i][j].data))
nodeA[i][j].Right = nodeA[i][j+nodeA[i][j].data];
if(isValid(a, i, j-nodeA[i][j].data))
nodeA[i][j].Left = nodeA[i][j-nodeA[i][j].data];
if(isValid(a, i+nodeA[i][j].data, j))
nodeA[i][j].Bottom = nodeA[i+nodeA[i][j].data][j];
if(isValid(a, i-nodeA[i][j].data, j))
nodeA[i][j].Top = nodeA[i-nodeA[i][j].data][j];
}
return nodeA;
}
public static boolean findPath(Node[][] s, int[][] t, int x, int y)
{
boolean b = false;
if(t[x][y] == 0)
{
t[x][y] = 1;
if(s[x][y].data == -1) b = true;
else
{
if(s[x][y].Right != null) b = findPath(s, t, x, y+s[x][y].data);
if(!b && s[x][y].Bottom != null) b = findPath(s, t, x+s[x][y].data, y);
if(!b && s[x][y].Left != null) b = findPath(s, t, x, y-s[x][y].data);
if(!b && s[x][y].Top != null) b = findPath(s, t, x-s[x][y].data, y);
}
if(b) stack.add(s[x][y]);
}
return b;
}
public static void main(String[] args)
{
int[][] maze = {{1,1,1,1,1},
{1,1,1,1,1},
{1,1,1,1,1},
{1,1,1,1,3},
{4,1,1,3,-1}};
Node[][] net = nodeArray(maze);
int[][] path = new int[maze.length][maze[0].lenght];
if(findPath(net, path, 0, 0))
{
Node temp;
while(!stack.isEmpty())
{
temp = stack.pop();
System.out.print("("+temp.coordinate[0]+" "+temp.coordinate[1]+") ");
}
}
else System.out.println("No Solution Possible.");
}
}
for this example the output should be:
(0 0) (1 0) (2 0) (3 0) (4 0) (4 4)
but I have this output:
(0 0) (0 1) (0 2) (0 3) (0 4) (1 4) (2 4) (3 4) (3 1) (3 2) (3 3) (4 3) (4 0) (4 4)
Please, any help how to fix the code so the solution will be the shortest path?!
Upvotes: 1
Views: 1622
Reputation: 373
After searching about BFS, now I know the difference between DFS and BFS. DFS algorithm travels a path from the source to the last node, if the goal is found stop, else try another path again from the source to the last node, and so until the goal is reached. While BFS algorithm travels from the source to the level below, if the goal is found stop, else go to the next level and so on.. For my problem, BFS is a suitable algorithm to find the shortest path. The code after some modifications:
public class findShoretstPath
{
private static class Node
{
private int[] coordinate = new int[2];
private int data;
private Node Right, Left, Top, Bottom;
public Node(){}
}
public static boolean isLinked(Node s, Node d) //method to determine if the node d is linked to the node s
{
if(d.Right == s) return true;
if(d.Bottom == s) return true;
if(d.Left == s) return true;
if(d.Top == s) return true;
return false;
}
public static boolean isValid(int[][] a, int x, int y)
{
if(x >= 0 && x < a.length && y >= 0 && y < a.length)
return true;
return false;
}
public static Node[][] nodeArray(int[][] a)
{
Node[][] nodeA = new Node[a.length][a.length];
for(int i = 0; i<nodeA.length; i++)
for(int j = 0; j<nodeA[i].length; j++)
{
nodeA[i][j] = new Node();
nodeA[i][j].coordinate[0] = i;
nodeA[i][j].coordinate[1] = j;
nodeA[i][j].data = a[i][j];
}
for(int i = 0; i<nodeA.length; i++)
for(int j = 0; j<nodeA[i].length; j++)
{
if(isValid(a, i, j+nodeA[i][j].data))
nodeA[i][j].Right = nodeA[i][j+nodeA[i][j].data];
if(isValid(a, i, j-nodeA[i][j].data))
nodeA[i][j].Left = nodeA[i][j-nodeA[i][j].data];
if(isValid(a, i+nodeA[i][j].data, j))
nodeA[i][j].Bottom = nodeA[i+nodeA[i][j].data][j];
if(isValid(a, i-nodeA[i][j].data, j))
nodeA[i][j].Top = nodeA[i-nodeA[i][j].data][j];
}
return nodeA;
}
public static void shortestPath(Node[][] nodes, int x, int y)
{
Stack<Node> stack = new Stack<>();
Queue<Node> queue = new LinkedList<>();
int[][] path = new int[nodes.length][nodes[0].length];
boolean b = false;
int level = 1;//to keep tracking each level viseted
queue.add(nodes[x][y]);
path[x][y] = level;
while(!queue.isEmpty())
{
Node temp;
level++;
int size = queue.size();
for(int i = 0; i<size; i++)
{
temp = queue.remove();
if(temp.data == -1) {b = true; break;}
if(temp.Right != null && path[temp.Right.coordinate[0]][temp.Right.coordinate[1]] == 0)
{
queue.add(temp.Right);
path[temp.Right.coordinate[0]][temp.Right.coordinate[1]] = level;
}
if(temp.Bottom != null && path[temp.Bottom.coordinate[0]][temp.Bottom.coordinate[1]] == 0)
{
queue.add(temp.Bottom);
path[temp.Bottom.coordinate[0]][temp.Bottom.coordinate[1]] = level;
}
if(temp.Left != null && path[temp.Left.coordinate[0]][temp.Left.coordinate[1]] == 0)
{
queue.add(temp.Left);
path[temp.Left.coordinate[0]][temp.Left.coordinate[1]] = level;
}
if(temp.Top != null && path[temp.Top.coordinate[0]][temp.Top.coordinate[1]] == 0)
{
queue.add(temp.Top);
path[temp.Top.coordinate[0]][temp.Top.coordinate[1]] = level;
}
}
if(b) break;
}
if(b)
{
int x1 = 0, y1 = 0;
for(int i = 0; i<nodes.length; i++)// to locate the position of the goal
for(int j = 0; j<nodes.length; j++)
if(nodes[i][j].data == -1)
{
x1 = i; y1 = j;
}
stack.add(nodes[x1][y1]);
int d = path[x1][y1];
while(d > 0)//go back from the goal to the source
{
for(int i = 0; i<path.length; i++)
{
if(path[x1][i] == d-1 && isLinked(nodes[x1][y1], nodes[x1][i]))
{
stack.add(nodes[x1][i]);
y1 = i;
break;
}
else if(path[i][y1] == d-1 && isLinked(nodes[x1][y1], nodes[i][y1]))
{
stack.add(nodes[i][y1]);
x1 = i;
break;
}
}
d--;
}
Node temp;
int stackSize = stack.size();
for(int i = 0; i<stackSize; i++)// print the final result
{
temp = stack.pop();
System.out.print("("+temp.coordinate[0]+" "+temp.coordinate[1]+") ");
}
}
else System.out.print("No Solution Possible.");
}
public static void main(String[] args)
{
int[][] maze = {{1,1,1,1,1},
{1,1,1,1,1},
{1,1,1,1,1},
{1,1,1,1,3},
{4,1,1,3,-1}};
Node[][] net = nodeArray(maze);
shortestPath(net, 0, 0));
System.out.println("");
}
}
and the output now is:
(0 0) (1 0) (2 0) (3 0) (4 0) (4 4)
Upvotes: 1