|
1 | 1 | package com.thealgorithms.backtracking; |
2 | 2 |
|
| 3 | +/** |
| 4 | + * This class contains methods to solve a maze using recursive backtracking. |
| 5 | + * The maze is represented as a 2D array where walls, paths, and visited/dead |
| 6 | + * ends are marked with different integers. |
| 7 | + * |
| 8 | + * The goal is to find a path from a starting position to the target position |
| 9 | + * (map[6][5]) while navigating through the maze. |
| 10 | + */ |
3 | 11 | public final class MazeRecursion { |
| 12 | + |
4 | 13 | private MazeRecursion() { |
5 | 14 | } |
6 | 15 |
|
7 | | - public static void mazeRecursion() { |
8 | | - // First create a 2 dimensions array to mimic a maze map |
9 | | - int[][] map = new int[8][7]; |
10 | | - int[][] map2 = new int[8][7]; |
11 | | - |
12 | | - // We use 1 to indicate wall |
13 | | - // Set the ceiling and floor to 1 |
14 | | - for (int i = 0; i < 7; i++) { |
15 | | - map[0][i] = 1; |
16 | | - map[7][i] = 1; |
17 | | - } |
18 | | - |
19 | | - // Then we set the left and right wall to 1 |
20 | | - for (int i = 0; i < 8; i++) { |
21 | | - map[i][0] = 1; |
22 | | - map[i][6] = 1; |
23 | | - } |
24 | | - |
25 | | - // Now we have created a maze with its wall initialized |
26 | | - |
27 | | - // Here we set the obstacle |
28 | | - map[3][1] = 1; |
29 | | - map[3][2] = 1; |
30 | | - |
31 | | - // Print the current map |
32 | | - System.out.println("The condition of the map: "); |
33 | | - for (int i = 0; i < 8; i++) { |
34 | | - for (int j = 0; j < 7; j++) { |
35 | | - System.out.print(map[i][j] + " "); |
36 | | - } |
37 | | - System.out.println(); |
38 | | - } |
39 | | - |
40 | | - // clone another map for setWay2 method |
41 | | - for (int i = 0; i < map.length; i++) { |
42 | | - System.arraycopy(map[i], 0, map2[i], 0, map[i].length); |
43 | | - } |
44 | | - |
45 | | - // By using recursive backtracking to let your ball(target) find its way in the |
46 | | - // maze |
47 | | - // The first parameter is the map |
48 | | - // Second parameter is x coordinate of your target |
49 | | - // Third parameter is the y coordinate of your target |
50 | | - setWay(map, 1, 1); |
51 | | - setWay2(map2, 1, 1); |
52 | | - |
53 | | - // Print out the new map1, with the ball footprint |
54 | | - System.out.println("After the ball goes through the map1,show the current map1 condition"); |
55 | | - for (int i = 0; i < 8; i++) { |
56 | | - for (int j = 0; j < 7; j++) { |
57 | | - System.out.print(map[i][j] + " "); |
58 | | - } |
59 | | - System.out.println(); |
| 16 | + /** |
| 17 | + * This method solves the maze using the "down -> right -> up -> left" |
| 18 | + * movement strategy. |
| 19 | + * |
| 20 | + * @param map The 2D array representing the maze (walls, paths, etc.) |
| 21 | + * @return The solved maze with paths marked, or null if no solution exists. |
| 22 | + */ |
| 23 | + public static int[][] solveMazeUsingFirstStrategy(int[][] map) { |
| 24 | + if (setWay(map, 1, 1)) { |
| 25 | + return map; |
60 | 26 | } |
| 27 | + return null; |
| 28 | + } |
61 | 29 |
|
62 | | - // Print out the new map2, with the ball footprint |
63 | | - System.out.println("After the ball goes through the map2,show the current map2 condition"); |
64 | | - for (int i = 0; i < 8; i++) { |
65 | | - for (int j = 0; j < 7; j++) { |
66 | | - System.out.print(map2[i][j] + " "); |
67 | | - } |
68 | | - System.out.println(); |
| 30 | + /** |
| 31 | + * This method solves the maze using the "up -> right -> down -> left" |
| 32 | + * movement strategy. |
| 33 | + * |
| 34 | + * @param map The 2D array representing the maze (walls, paths, etc.) |
| 35 | + * @return The solved maze with paths marked, or null if no solution exists. |
| 36 | + */ |
| 37 | + public static int[][] solveMazeUsingSecondStrategy(int[][] map) { |
| 38 | + if (setWay2(map, 1, 1)) { |
| 39 | + return map; |
69 | 40 | } |
| 41 | + return null; |
70 | 42 | } |
71 | 43 |
|
72 | 44 | /** |
73 | | - * Using recursive path finding to help the ball find its way in the maze |
74 | | - * Description: |
75 | | - * 1. map (means the maze) |
76 | | - * 2. i, j (means the initial coordinate of the ball in the maze) |
77 | | - * 3. if the ball can reach the end of maze, that is position of map[6][5], |
78 | | - * means the we have found a path for the ball |
79 | | - * 4. Additional Information: 0 in the map[i][j] means the ball has not gone |
80 | | - * through this position, 1 means the wall, 2 means the path is feasible, 3 |
81 | | - * means the ball has gone through the path but this path is dead end |
82 | | - * 5. We will need strategy for the ball to pass through the maze for example: |
83 | | - * Down -> Right -> Up -> Left, if the path doesn't work, then backtrack |
| 45 | + * Attempts to find a path through the maze using a "down -> right -> up -> left" |
| 46 | + * movement strategy. The path is marked with '2' for valid paths and '3' for dead ends. |
84 | 47 | * |
85 | | - * @author OngLipWei |
86 | | - * @version Jun 23, 2021 11:36:14 AM |
87 | | - * @param map The maze |
88 | | - * @param i x coordinate of your ball(target) |
89 | | - * @param j y coordinate of your ball(target) |
90 | | - * @return If we did find a path for the ball,return true,else false |
| 48 | + * @param map The 2D array representing the maze (walls, paths, etc.) |
| 49 | + * @param i The current x-coordinate of the ball (row index) |
| 50 | + * @param j The current y-coordinate of the ball (column index) |
| 51 | + * @return True if a path is found to (6,5), otherwise false |
91 | 52 | */ |
92 | | - public static boolean setWay(int[][] map, int i, int j) { |
93 | | - if (map[6][5] == 2) { // means the ball find its path, ending condition |
| 53 | + private static boolean setWay(int[][] map, int i, int j) { |
| 54 | + if (map[6][5] == 2) { |
94 | 55 | return true; |
95 | 56 | } |
96 | | - if (map[i][j] == 0) { // if the ball haven't gone through this point |
97 | | - // then the ball follows the move strategy : down -> right -> up -> left |
98 | | - map[i][j] = 2; // we assume that this path is feasible first, set the current point to 2 |
99 | | - // first。 |
100 | | - if (setWay(map, i + 1, j)) { // go down |
| 57 | + |
| 58 | + // If the current position is unvisited (0), explore it |
| 59 | + if (map[i][j] == 0) { |
| 60 | + // Mark the current position as '2' |
| 61 | + map[i][j] = 2; |
| 62 | + |
| 63 | + // Move down |
| 64 | + if (setWay(map, i + 1, j)) { |
101 | 65 | return true; |
102 | | - } else if (setWay(map, i, j + 1)) { // go right |
| 66 | + } |
| 67 | + // Move right |
| 68 | + else if (setWay(map, i, j + 1)) { |
103 | 69 | return true; |
104 | | - } else if (setWay(map, i - 1, j)) { // go up |
| 70 | + } |
| 71 | + // Move up |
| 72 | + else if (setWay(map, i - 1, j)) { |
105 | 73 | return true; |
106 | | - } else if (setWay(map, i, j - 1)) { // go left |
| 74 | + } |
| 75 | + // Move left |
| 76 | + else if (setWay(map, i, j - 1)) { |
107 | 77 | return true; |
108 | | - } else { |
109 | | - // means that the current point is the dead end, the ball cannot proceed, set |
110 | | - // the current point to 3 and return false, the backtracking will start, it will |
111 | | - // go to the previous step and check for feasible path again |
112 | | - map[i][j] = 3; |
113 | | - return false; |
114 | 78 | } |
115 | | - } else { // if the map[i][j] != 0 , it will probably be 1,2,3, return false because the |
116 | | - // ball cannot hit the wall, cannot go to the path that has gone though before, |
117 | | - // and cannot head to deadened. |
| 79 | + |
| 80 | + map[i][j] = 3; // Mark as dead end (3) if no direction worked |
118 | 81 | return false; |
119 | 82 | } |
| 83 | + return false; |
120 | 84 | } |
121 | 85 |
|
122 | | - // Here is another move strategy for the ball: up->right->down->left |
123 | | - public static boolean setWay2(int[][] map, int i, int j) { |
124 | | - if (map[6][5] == 2) { // means the ball find its path, ending condition |
| 86 | + /** |
| 87 | + * Attempts to find a path through the maze using an alternative movement |
| 88 | + * strategy "up -> right -> down -> left". |
| 89 | + * |
| 90 | + * @param map The 2D array representing the maze (walls, paths, etc.) |
| 91 | + * @param i The current x-coordinate of the ball (row index) |
| 92 | + * @param j The current y-coordinate of the ball (column index) |
| 93 | + * @return True if a path is found to (6,5), otherwise false |
| 94 | + */ |
| 95 | + private static boolean setWay2(int[][] map, int i, int j) { |
| 96 | + if (map[6][5] == 2) { |
125 | 97 | return true; |
126 | 98 | } |
127 | | - if (map[i][j] == 0) { // if the ball haven't gone through this point |
128 | | - // then the ball follows the move strategy : up->right->down->left |
129 | | - map[i][j] = 2; // we assume that this path is feasible first, set the current point to 2 |
130 | | - // first。 |
131 | | - if (setWay2(map, i - 1, j)) { // go up |
| 99 | + |
| 100 | + if (map[i][j] == 0) { |
| 101 | + map[i][j] = 2; |
| 102 | + |
| 103 | + // Move up |
| 104 | + if (setWay2(map, i - 1, j)) { |
132 | 105 | return true; |
133 | | - } else if (setWay2(map, i, j + 1)) { // go right |
| 106 | + } |
| 107 | + // Move right |
| 108 | + else if (setWay2(map, i, j + 1)) { |
134 | 109 | return true; |
135 | | - } else if (setWay2(map, i + 1, j)) { // go down |
| 110 | + } |
| 111 | + // Move down |
| 112 | + else if (setWay2(map, i + 1, j)) { |
136 | 113 | return true; |
137 | | - } else if (setWay2(map, i, j - 1)) { // go left |
| 114 | + } |
| 115 | + // Move left |
| 116 | + else if (setWay2(map, i, j - 1)) { |
138 | 117 | return true; |
139 | | - } else { |
140 | | - // means that the current point is the dead end, the ball cannot proceed, set |
141 | | - // the current point to 3 and return false, the backtracking will start, it will |
142 | | - // go to the previous step and check for feasible path again |
143 | | - map[i][j] = 3; |
144 | | - return false; |
145 | 118 | } |
146 | | - } else { // if the map[i][j] != 0 , it will probably be 1,2,3, return false because the |
147 | | - // ball cannot hit the wall, cannot go to the path that has gone through before, |
148 | | - // and cannot head to deadend. |
| 119 | + |
| 120 | + map[i][j] = 3; // Mark as dead end (3) if no direction worked |
149 | 121 | return false; |
150 | 122 | } |
| 123 | + return false; |
151 | 124 | } |
152 | 125 | } |
0 commit comments