Repository navigation
Expand file tree
/
Copy pathMazeRecursion.java
More file actions
140 lines (123 loc) · 6.13 KB
/
Copy pathMazeRecursion.java
File metadata and controls
140 lines (123 loc) · 6.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package com.thealgorithms.backtracking;
/**
* This class contains methods to solve a maze using recursive backtracking.
* The maze is represented as a 2D array where walls, paths, and visited/dead
* ends are marked with different integers.
*/
public final class MazeRecursion {
private static final int OPEN = 0;
private static final int PATH = 2;
private static final int DEAD_END = 3;
private static final int DEFAULT_START_ROW = 1;
private static final int DEFAULT_START_COLUMN = 1;
private static final int DEFAULT_GOAL_ROW = 6;
private static final int DEFAULT_GOAL_COLUMN = 5;
// Each entry is {rowDelta, colDelta}
// down -> right -> up -> left
private static final int[][] FIRST_STRATEGY_DIRECTIONS = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
// up -> right -> down -> left
private static final int[][] SECOND_STRATEGY_DIRECTIONS = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
private MazeRecursion() {
}
/**
* Solves the maze using the "down -> right -> up -> left" movement strategy,
* starting at (1, 1) and targeting (6, 5).
*
* @param map the 2D array representing the maze (walls, paths, etc.)
* @return the solved maze with paths marked, or null if no solution exists or a fixed endpoint is outside the maze
* @throws IllegalArgumentException if the maze is null, empty, or not rectangular
*/
public static int[][] solveMazeUsingFirstStrategy(int[][] map) {
return solveWithDefaultEndpoints(map, FIRST_STRATEGY_DIRECTIONS);
}
/**
* Solves the maze using the "up -> right -> down -> left" movement strategy,
* starting at (1, 1) and targeting (6, 5).
*
* @param map the 2D array representing the maze (walls, paths, etc.)
* @return the solved maze with paths marked, or null if no solution exists or a fixed endpoint is outside the maze
* @throws IllegalArgumentException if the maze is null, empty, or not rectangular
*/
public static int[][] solveMazeUsingSecondStrategy(int[][] map) {
return solveWithDefaultEndpoints(map, SECOND_STRATEGY_DIRECTIONS);
}
/**
* Solves the maze using the "down -> right -> up -> left" movement strategy.
*
* @param map the 2D array representing the maze (0 = open, non-zero = blocked)
* @param startRow the starting row
* @param startColumn the starting column
* @param goalRow the goal row
* @param goalColumn the goal column
* @return the solved maze with paths marked, or null if no solution exists
* @throws IllegalArgumentException if the maze is null, empty, not rectangular,
* or a coordinate is outside the maze
*/
public static int[][] solveMazeUsingFirstStrategy(int[][] map, int startRow, int startColumn, int goalRow, int goalColumn) {
validateCoordinates(map, startRow, startColumn, goalRow, goalColumn);
return solve(map, startRow, startColumn, goalRow, goalColumn, FIRST_STRATEGY_DIRECTIONS) ? map : null;
}
/**
* Solves the maze using the "up -> right -> down -> left" movement strategy.
*
* @param map the 2D array representing the maze (0 = open, non-zero = blocked)
* @param startRow the starting row
* @param startColumn the starting column
* @param goalRow the goal row
* @param goalColumn the goal column
* @return the solved maze with paths marked, or null if no solution exists
* @throws IllegalArgumentException if the maze is null, empty, not rectangular,
* or a coordinate is outside the maze
*/
public static int[][] solveMazeUsingSecondStrategy(int[][] map, int startRow, int startColumn, int goalRow, int goalColumn) {
validateCoordinates(map, startRow, startColumn, goalRow, goalColumn);
return solve(map, startRow, startColumn, goalRow, goalColumn, SECOND_STRATEGY_DIRECTIONS) ? map : null;
}
private static int[][] solveWithDefaultEndpoints(int[][] map, int[][] directions) {
validateMaze(map);
if (!isInBounds(map, DEFAULT_START_ROW, DEFAULT_START_COLUMN) || !isInBounds(map, DEFAULT_GOAL_ROW, DEFAULT_GOAL_COLUMN)) {
return null;
}
if (map[DEFAULT_GOAL_ROW][DEFAULT_GOAL_COLUMN] == PATH) {
return map;
}
return solve(map, DEFAULT_START_ROW, DEFAULT_START_COLUMN, DEFAULT_GOAL_ROW, DEFAULT_GOAL_COLUMN, directions) ? map : null;
}
private static boolean solve(int[][] map, int row, int column, int goalRow, int goalColumn, int[][] directions) {
if (!isInBounds(map, row, column) || map[row][column] != OPEN) {
return false;
}
map[row][column] = PATH;
if (row == goalRow && column == goalColumn) {
return true;
}
for (int[] direction : directions) {
if (solve(map, row + direction[0], column + direction[1], goalRow, goalColumn, directions)) {
return true;
}
}
map[row][column] = DEAD_END;
return false;
}
private static int validateMaze(int[][] map) {
if (map == null || map.length == 0 || map[0] == null || map[0].length == 0) {
throw new IllegalArgumentException("Maze must not be null or empty.");
}
int columnCount = map[0].length;
for (int[] row : map) {
if (row == null || row.length != columnCount) {
throw new IllegalArgumentException("Maze must be a non-empty rectangular matrix.");
}
}
return columnCount;
}
private static void validateCoordinates(int[][] map, int startRow, int startColumn, int goalRow, int goalColumn) {
int columnCount = validateMaze(map);
if (startRow < 0 || startRow >= map.length || startColumn < 0 || startColumn >= columnCount || goalRow < 0 || goalRow >= map.length || goalColumn < 0 || goalColumn >= columnCount) {
throw new IllegalArgumentException("Start and goal coordinates must be inside the maze.");
}
}
private static boolean isInBounds(int[][] map, int row, int column) {
return row >= 0 && row < map.length && column >= 0 && column < map[row].length;
}
}