Recursive maze

problem

On a map, you are given a starting point, an end point and obstacles on the map, so that you can formulate a route out of the end point (you do not need to find the shortest path)
As shown in the figure:

"1" indicates an obstacle, "0" indicates a walkable Road, (1,1) is the starting point, and (6,5) is the end point
(peripheral obstacles are not coordinates, and the array subscript starts from 0)

problem analysis

To solve this problem is to find the path from the entrance to the exit. When solving, the method of "exhaustive solution" is usually used, that is, starting from the entrance, probe forward in a certain direction. If it can pass, continue to move forward. Otherwise, go back along the original Road (backtracking), and continue to probe in another direction until the end point is reached.

It is similar to depth first search (depth first search seeks the shortest path, that is, the optimal solution. I will summarize the depth first algorithm later).

If we think carefully, we will find that the way to find the way is the same

  1. First, check whether the current position can go. If not, go back and go back
  2. If the current position is OK, go to the next step to see if the up, down, left and right paths of the current position are OK (of course, the order of "go up first, go down first, go left first, go right first" is determined by yourself, and this decision will affect the final route you find)

In this way, in fact, we have divided the big problem from the beginning to the end into small problems to find the next step from the current position.

code implementation

Coding convention

  • I use a two-dimensional array to represent the map
  • The number "1" represents the wall and the number "0" represents the road
  • (1,1) position represents the starting point and (6,5) position represents the ending point
  • The mark of the number "2" indicates that the point has passed, and the mark of the number "3" indicates that the point is a dead end and the front is impassable
  • The value of the end point (6,5) is 0 by default. If you reach this point, you will assign it to the number "6" (sounds auspicious)

Upper code

    public static void main(String[] args) {
		//First create a two-dimensional array to simulate the maze
        int[][] map = new int[8][7];
        //Use 1 to represent the wall, and the top and bottom are all 1
        for (int i = 0; i < 7; i++) {
            map[0][i] = 1;
            map[7][i] = 1;
        }
        //Left and right are all 1
        for (int i = 0; i < 8; i++) {
            map[i][0] = 1;
            map[i][6] = 1;
        }
        map[6][1] = 1;
        map[3][2] = 1;
        map[5][2] = 1;
        map[4][2] = 1;
        map[2][3] = 1;
		// map[1][3] = 1;

        //Printout maze, that is, printout two-dimensional array
        System.out.println("Map:");
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 7; j++) {
                System.out.print(map[i][j] + "\t");
            }
            System.out.println();
        }
        System.out.println("=========================================");
        //Call the custom setWay method to find the way
        setWay(map, 1, 1);
        System.out.println("Detected maps:");

        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 7; j++) {
                System.out.print(map[i][j] + "\t");
            }
            System.out.println();
        }
    }


    public static void setWay(int[][] map,int i,int j){
        if (i==6 && j==5)
        {
            //We have reached the end
            System.out.println("We have reached the end");
            map[i][j] = 6;
            return;     // to flash back
        }
        else
        {
            if (map[i][j] == 0){    // If the current position is 0, it means that the current position can go. Then go to the next step according to the strategy, and go in the direction of lower right, upper left
                // Assign the current position to 2 to mark that the position has gone
                map[i][j] = 2;
                // Start looking for the next step
                if (map[i+1][j] == 0){          //It means going down
                    System.out.println("towards↓go");
                    setWay(map, i+1, j);
                    // If you return from the sub stack frame setWay, there are two situations: 1. Return only after the previous road has been blocked (can't go); 2. Return only after the end of the maze has been found
                    System.out.println("from"+(i+1)+"that 's ok"+j+"The column is back, ↑");
                    // If the destination is found, we need to go back and return directly. Otherwise, we will not return, but choose to go in other directions
                    if (map[6][5] == 6) return;
                }
                if (map[i][j+1] == 0){    //It means to go right
                    System.out.println("towards→go");
                    setWay(map, i, j+1);
                    System.out.println("from"+i+"that 's ok"+(j+1)+"The column is back, ←");
                    if (map[6][5] == 6) return;
                }
                if (map[i-1][j] == 0){    //It means going up
                    System.out.println("towards↑go");
                    setWay(map, i-1, j);
                    System.out.println("from"+(i-1)+"that 's ok"+j+"The column is back, ↓");
                    if (map[6][5] == 6) return;
                }
                if (map[i][j-1] == 0){    //It means to go left
                    System.out.println("towards←go");
                    setWay(map, i, j-1);
                    System.out.println("from"+i+"that 's ok"+(j-1)+"The column is back, →");
                    if (map[6][5] == 6) return;
                }
                //If you can't walk in the order of bottom, right, top and left, the current point is marked as 3, which is a dead end
                map[i][j] = 3;
                System.out.println("can't go through"+i+"that 's ok"+j+"column");
                return;     // to flash back
            }
            else {
                //If the current point is not 0, it may also be 1, 2, or 3, which means it cannot go
                return;     // to flash back
            }
        }
    }

Simple version of setWay method (or the above logic)

/**
     * Way finding method
     * @param map :  Represents the entire map
     * @param row
     * @param col   (row,col) It means to explore from this point
     */
    public static void setWay1(int[][] map, int row, int col) {
        if (row==6 && col==5) { // If you reach (6,5), it means that you have reached the end point. Go back directly
            map[row][col] = 6;  // Assign it 6 (this 6 is only a special value and has no special meaning)
            return;
        }else {
            if (map[row][col] == 0) {   // If the point is 0, it means you can go
                // 1. First, set the point to 2 to indicate that the point has passed
                map[row][col] = 2;
                // 2. Find the next step according to the plan. Go to the next step in the order of ↓ then → then ↑ and finally ←
                if (map[row+1][col] == 0) { // If you go to ↓
                    setWay1(map, row+1, col);   // Go back in this direction
                    /**
                     * If it is executed from the above setWay1 sub stack frame, there are two cases
                     * 1,(6,5)This point has been found. We just need to go back all the time (we need to return all the time, because we don't have to look any more. We have found the end point)
                     * 2,It's just because there's a dead end ahead (we don't need to return, because we still need to find a way in other directions)
                     */
                    if (map[6][5] == 6) return;
                }
                if (map[row][col+1] == 0) { // If you go to → you can go
                    setWay1(map, row, col+1);   // Go back in this direction
                    if (map[6][5] == 6) return;
                }
                if (map[row-1][col] == 0) { // If you go to ↑
                    setWay1(map, row-1, col);   // Go back in this direction
                    if (map[6][5] == 6) return;
                }
                if (map[row][col-1] == 0) { // If you can go to ←
                    setWay1(map, row, col-1);   // Go back in this direction
                    if (map[6][5] == 6) return;
                }
                // 3. If you can't go in all four directions, it means that this point is a dead end. Assign it to 3 and return
                map[row][col] = 3;
                return;
            }else {     // If it is not 0, it means that the point cannot go. It may be 2, 3 or 6 direct return backtracking
                return;
            }
        }
    }

Conclusion

Algorithm is not only to see more and think more, but also to practice more. It is more effective to knock it with your own hand.
If this article is helpful to you, click like (* ^ ▽ ^ *)!

Tags: Java Algorithm

Posted on Sun, 10 Oct 2021 01:34:06 -0400 by Jason Batten