0

I'm currently working on a little maze solver project where you find the shortest path in a maze so as to get a better understanding of path searching algorithms, like in this example the breadth-first search algorithm. My implementation of it uses a boolean visitation matrix to mark visited cells to avoid repeating steps, it then works in the following steps.

Step 1 - Uses visitation queue to holds the adjacent cells.

Step 2 - Removes the cell at the front of the queue and adds it to a visitation list, increments steps variable.

Step 3 - Checks adjacent cells and if they aren't walls and they aren't visited, they'll be added to the visitation queue.

Step 4 - Repeat steps 2 and step 3 until the entire queue is empty.

The breadth-first search implementation works and it turns paths(i.e. 0s) into visited paths(i.e. 2s) but I'm having the problem where I can't get it to decrements distance(variable) to goal and change dead end paths back 0s so that it only shows the shortest path and shortest amount of steps needed to reach it? Maybe some fresh new eyes will see what it is that I'm missing. Thanks in advance!

It turns out like this:BFS with problems

Instead of this:BFS fixed

BFS Maze solver implementation

import java.util.LinkedList;
import java.util.Queue;

public class BFS {
    
    private static int distance = 0;
    
    // Solves given maze iteratively, input starting position in maze and size of the maze.
    public static boolean solve(int[][] maze, int x, int y, int sizeX, int sizeY) {
        
        boolean[][] visited = new boolean[sizeX][sizeY];
        Queue<Point> vQueue = new LinkedList<Point>();
        vQueue.add(new Point(x, y, null));
        
        while (!vQueue.isEmpty()) {
            distance++;
            Point p = vQueue.remove();
            visited[p.x][p.y] = true;
            
            // 3 is the cell the algorithm is supposed to find.
            if (maze[p.x][p.y] == 3) {
                maze[p.x][p.y] = 2;
                System.out.println("Shortest path has "+ distance + " steps.");
                return true;
            }
            
            maze[p.x][p.y] = 2;
            // Down.
            if (visited[p.x-1][p.y] == false && (maze[p.x-1][p.y] == 0 || maze[p.x-1][p.y] == 3)) {
                Point nextPoint = new Point(p.x-1, p.y, p);
                vQueue.add(nextPoint);
            }
            
            // Up.
            if (visited[p.x+1][p.y] == false  && (maze[p.x+1][p.y] == 0 || maze[p.x+1][p.y] == 3)) {
                Point nextPoint = new Point(p.x+1, p.y, p);
                vQueue.add(nextPoint);
            }
            
            // Right.
            if (visited[p.x][p.y+1] == false  && (maze[p.x][p.y+1] == 0 || maze[p.x][p.y+1] == 3)) {
                Point nextPoint = new Point(p.x, p.y+1, p);
                vQueue.add(nextPoint);
            }
            
            // Left.
            if (visited[p.x][y-1] == false  && (maze[p.x][p.y-1] == 0 || maze[p.x][p.y-1] == 3)) {
                Point nextPoint = new Point(p.x, p.y-1, p);
                vQueue.add(nextPoint);
            }
        }
        
        return false;
    }
    
    // Node class that holds current position and visitation list.
    private static class Point{
        int x;
        int y;
        Point parent;
        
        public Point(int x, int y, Point parent) {
            this.x = x;
            this.y = y;
            this.parent = parent;
        }
        
        
    }
    
}

Test Maze

public class TestMazeDFS {
    private static int[][] maze = {
            {1, 1, 1, 1, 1, 1, 1, 1, 1},        
            {1, 0, 0, 0, 0, 0, 0, 0, 1},
            {1, 0, 1, 0, 1, 1, 1, 1, 1},
            {1, 0, 1, 0, 0, 0, 0, 0, 1},
            {1, 1, 1, 1, 1, 0, 1, 0, 1},
            {1, 0, 0, 0, 1, 0, 1, 0, 1},
            {1, 0, 1, 1, 1, 1, 1, 0, 1},
            {1, 0, 0, 0, 0, 0, 0 ,3, 1},
            {1, 1, 1, 1, 1, 1, 1, 1, 1},
        };
    
    public int[][] getMaze(){
        
        return this.maze;
    }
    
    // prints the maze.
    public static void printMaze() {
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
//              if (maze[i][j] == 1) {
//                  System.out.print('#');
//              } else {
//                  System.out.print(' ');
//              }
                System.out.print(maze[i][j]);
            }
            System.out.println();
        }
        System.out.println();
    }
    
    public static void main(String[] args) {
        TestMazeDFS maze = new TestMazeDFS();
        boolean test = BFS.solve(maze.getMaze(), 1, 1, 9, 9);
        System.out.println(test);
        printMaze();
        
    }
}
Codexing
  • 133
  • 1
  • 11

1 Answers1

2

I am not sure how you thought to output the shortest path. But an alternative approach would be to use an integer matrix, instead of a boolean matrix. Then record in each cell how far away from the start it is.

That is, when processing a point, read the current distance to the start from the integer matrix. Then determine all its valid neighbours that still have a distance 0 in their cells, write the current distance + 1 into those cells, and add them to the queue.

At the end, you can then find the shortest path by backtracking from goal, following the path that decreases with 1 every step.

fishinear
  • 6,101
  • 3
  • 36
  • 84
  • Basically the distance should've be calculated so that when it backtracks it also decrements the distance variable so that it only gets incremented when it has the shortest path. For example if it follows a path it increments but if that path happen to be a dead end, it'll decrement as it backtracks. My problem is how should I handle the decrementing when backtracking? – Codexing Jan 06 '21 at 20:04
  • I should add so that only the shortest path has 2s, and all the other paths whether they are dead end or not will only show 0s. – Codexing Jan 06 '21 at 20:18
  • 1
    There is no need to backtrack in a breadth-first algorithm. If you hit a dead-end, you have already filled in all the cells that lead up to that dead-end, so you can simply abandon that branch. – fishinear Jan 06 '21 at 21:28
  • 1
    When using an integer matrix as I propose, each cell will contain the shortest distance to the start. I'll clarify the answer. – fishinear Jan 06 '21 at 21:31
  • I managed to get it to work by backtracking the visitation list from the end to the start and on my way mark the nodes to show the path. Thank you so much! – Codexing Jan 07 '21 at 15:40