From df3b5d6d91210fef7d8bf6467045edff3dd51ad9 Mon Sep 17 00:00:00 2001 From: krishnayak986-lang Date: Fri, 30 Oct 2026 15:45:33 +0530 Subject: [PATCH 1/6] fix: handle bounds, validation and custom start/target in MazeRecursion --- .../backtracking/MazeRecursion.java | 177 ++++++++++-------- .../backtracking/MazeRecursionTest.java | 51 ++++- 2 files changed, 145 insertions(+), 83 deletions(-) diff --git a/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java b/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java index 8247172e7ee0..7871d120bd91 100644 --- a/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java +++ b/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java @@ -5,121 +5,136 @@ * The maze is represented as a 2D array where walls, paths, and visited/dead * ends are marked with different integers. * - * The goal is to find a path from a starting position to the target position - * (map[6][5]) while navigating through the maze. + * Cell values: 0 = open, 1 = wall, 2 = path, 3 = dead end. */ 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_COL = 1; + private static final int DEFAULT_TARGET_ROW = 6; + private static final int DEFAULT_TARGET_COL = 5; + + // Each entry is {rowDelta, colDelta} + // down -> right -> up -> left + private static final int[][] FIRST_STRATEGY = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + // up -> right -> down -> left + private static final int[][] SECOND_STRATEGY = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; + private MazeRecursion() { } /** - * This method solves the maze using the "down -> right -> up -> left" - * movement strategy. + * Solves the maze from (1,1) to (6,5) using "down -> right -> up -> left". * - * @param map The 2D array representing the maze (walls, paths, etc.) - * @return The solved maze with paths marked, or null if no solution exists. + * @param map the maze + * @return the solved maze, or null if no solution exists + * @throws IllegalArgumentException if the maze is invalid or the default + * start/target lie outside the maze */ public static int[][] solveMazeUsingFirstStrategy(int[][] map) { - if (setWay(map, 1, 1)) { - return map; - } - return null; + return solveMazeUsingFirstStrategy(map, DEFAULT_START_ROW, DEFAULT_START_COL, DEFAULT_TARGET_ROW, DEFAULT_TARGET_COL); } /** - * This method solves the maze using the "up -> right -> down -> left" - * movement strategy. + * Solves the maze from (1,1) to (6,5) using "up -> right -> down -> left". * - * @param map The 2D array representing the maze (walls, paths, etc.) - * @return The solved maze with paths marked, or null if no solution exists. + * @param map the maze + * @return the solved maze, or null if no solution exists + * @throws IllegalArgumentException if the maze is invalid or the default + * start/target lie outside the maze */ public static int[][] solveMazeUsingSecondStrategy(int[][] map) { - if (setWay2(map, 1, 1)) { - return map; - } - return null; + return solveMazeUsingSecondStrategy(map, DEFAULT_START_ROW, DEFAULT_START_COL, DEFAULT_TARGET_ROW, DEFAULT_TARGET_COL); } /** - * Attempts to find a path through the maze using a "down -> right -> up -> left" - * movement strategy. The path is marked with '2' for valid paths and '3' for dead ends. + * Solves the maze between custom positions using "down -> right -> up -> left". * - * @param map The 2D array representing the maze (walls, paths, etc.) - * @param i The current x-coordinate of the ball (row index) - * @param j The current y-coordinate of the ball (column index) - * @return True if a path is found to (6,5), otherwise false + * @param map the maze + * @param startRow start row index + * @param startCol start column index + * @param targetRow target row index + * @param targetCol target column index + * @return the solved maze, or null if no solution exists + * @throws IllegalArgumentException if the maze is null, empty, jagged, or + * start/target are outside the maze */ - private static boolean setWay(int[][] map, int i, int j) { - if (map[6][5] == 2) { - return true; - } + public static int[][] solveMazeUsingFirstStrategy(int[][] map, int startRow, int startCol, int targetRow, int targetCol) { + return solve(map, startRow, startCol, targetRow, targetCol, FIRST_STRATEGY); + } - // If the current position is unvisited (0), explore it - if (map[i][j] == 0) { - // Mark the current position as '2' - map[i][j] = 2; + /** + * Solves the maze between custom positions using "up -> right -> down -> left". + * + * @param map the maze + * @param startRow start row index + * @param startCol start column index + * @param targetRow target row index + * @param targetCol target column index + * @return the solved maze, or null if no solution exists + * @throws IllegalArgumentException if the maze is null, empty, jagged, or + * start/target are outside the maze + */ + public static int[][] solveMazeUsingSecondStrategy(int[][] map, int startRow, int startCol, int targetRow, int targetCol) { + return solve(map, startRow, startCol, targetRow, targetCol, SECOND_STRATEGY); + } - // Move down - if (setWay(map, i + 1, j)) { - return true; - } - // Move right - else if (setWay(map, i, j + 1)) { - return true; - } - // Move up - else if (setWay(map, i - 1, j)) { - return true; - } - // Move left - else if (setWay(map, i, j - 1)) { - return true; - } + private static int[][] solve(int[][] map, int startRow, int startCol, int targetRow, int targetCol, int[][] directions) { + validate(map, startRow, startCol, targetRow, targetCol); + return setWay(map, startRow, startCol, targetRow, targetCol, directions) ? map : null; + } - map[i][j] = 3; // Mark as dead end (3) if no direction worked - return false; + private static void validate(int[][] map, int startRow, int startCol, int targetRow, int targetCol) { + if (map == null || map.length == 0) { + throw new IllegalArgumentException("Maze must not be null or empty"); + } + int cols = map[0] == null ? 0 : map[0].length; + if (cols == 0) { + throw new IllegalArgumentException("Maze rows must not be null or empty"); + } + for (int[] row : map) { + if (row == null || row.length != cols) { + throw new IllegalArgumentException("Maze must be rectangular"); + } + } + if (!isInside(map, startRow, startCol)) { + throw new IllegalArgumentException("Start position is outside the maze"); + } + if (!isInside(map, targetRow, targetCol)) { + throw new IllegalArgumentException("Target position is outside the maze"); } - return false; + } + + private static boolean isInside(int[][] map, int row, int col) { + return row >= 0 && row < map.length && col >= 0 && col < map[0].length; } /** - * Attempts to find a path through the maze using an alternative movement - * strategy "up -> right -> down -> left". - * - * @param map The 2D array representing the maze (walls, paths, etc.) - * @param i The current x-coordinate of the ball (row index) - * @param j The current y-coordinate of the ball (column index) - * @return True if a path is found to (6,5), otherwise false + * Shared recursive backtracking logic used by both strategies. + * Marks the route with 2 and dead ends with 3. */ - private static boolean setWay2(int[][] map, int i, int j) { - if (map[6][5] == 2) { - return true; + private static boolean setWay(int[][] map, int row, int col, int targetRow, int targetCol, int[][] directions) { + if (!isInside(map, row, col) || map[row][col] != OPEN) { + return false; } - if (map[i][j] == 0) { - map[i][j] = 2; + map[row][col] = PATH; - // Move up - if (setWay2(map, i - 1, j)) { - return true; - } - // Move right - else if (setWay2(map, i, j + 1)) { - return true; - } - // Move down - else if (setWay2(map, i + 1, j)) { - return true; - } - // Move left - else if (setWay2(map, i, j - 1)) { + if (row == targetRow && col == targetCol) { + return true; + } + + for (int[] direction : directions) { + if (setWay(map, row + direction[0], col + direction[1], targetRow, targetCol, directions)) { return true; } - - map[i][j] = 3; // Mark as dead end (3) if no direction worked - return false; } + + map[row][col] = DEAD_END; return false; } -} +} \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java b/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java index b8e77fb38bad..a2022b5443e2 100644 --- a/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java +++ b/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java @@ -1,6 +1,8 @@ package com.thealgorithms.backtracking; import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Test; @@ -62,6 +64,51 @@ public void testSolveMazeUsingFirstAndSecondStrategy() { // Assert the results assertArrayEquals(expectedMap1, solvedMap1); - assertArrayEquals(expectedMap2, solvedMap2); + assertArrayEquals(expectedMap2, solvedMap2); + + @Test + void testSmallMazeWithCustomStartAndTarget() { + int[][] map = {{0, 0}, {0, 0}}; + int[][] result = MazeRecursion.solveMazeUsingFirstStrategy(map, 0, 0, 1, 1); + assertArrayEquals(new int[][] {{2, 0}, {2, 2}}, result); // down -> right + } + + @Test + void testSecondStrategyKeepsItsTraversalOrder() { + int[][] map = {{0, 0}, {0, 0}}; + int[][] result = MazeRecursion.solveMazeUsingSecondStrategy(map, 0, 0, 1, 1); + assertArrayEquals(new int[][] {{2, 2}, {0, 2}}, result); // right -> down + } + + @Test + void testDefaultTargetOutsideSmallMazeThrowsIllegalArgument() { + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0, 0}})); + } + + @Test + void testNullAndEmptyMaze() { + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(null)); + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {})); + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{}})); + } + + @Test + void testJaggedMazeThrows() { + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0}}, 0, 0, 0, 1)); + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {{0}, {0, 0}}, 0, 0, 1, 1)); + } + + @Test + void testStartOrTargetOutOfBoundsThrows() { + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0, 0}}, -1, 0, 1, 1)); + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {{0, 0}, {0, 0}}, 0, 0, 2, 2)); + } + + @Test + void testUnsolvableMazeReturnsNull() { + int[][] map = {{0, 1}, {1, 0}}; + assertNull(MazeRecursion.solveMazeUsingFirstStrategy(map, 0, 0, 1, 1)); + } } -} +} + From 37b10713441860ed14f7d48e6a20b17b0c15fb80 Mon Sep 17 00:00:00 2001 From: krishnayak986-lang Date: Thu, 12 Nov 2026 20:12:39 +0530 Subject: [PATCH 2/6] style: apply clang-format --- .../backtracking/MazeRecursionTest.java | 89 +++++++++---------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java b/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java index da52da1408f8..0ac92208fa2e 100644 --- a/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java +++ b/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java @@ -161,51 +161,50 @@ public void testSolveMazeUsingFirstAndSecondStrategy() { // Assert the results assertArrayEquals(expectedMap1, solvedMap1); - assertArrayEquals(expectedMap2, solvedMap2); + assertArrayEquals(expectedMap2, solvedMap2); @Test - void testSmallMazeWithCustomStartAndTarget() { - int[][] map = {{0, 0}, {0, 0}}; - int[][] result = MazeRecursion.solveMazeUsingFirstStrategy(map, 0, 0, 1, 1); - assertArrayEquals(new int[][] {{2, 0}, {2, 2}}, result); // down -> right - } - - @Test - void testSecondStrategyKeepsItsTraversalOrder() { - int[][] map = {{0, 0}, {0, 0}}; - int[][] result = MazeRecursion.solveMazeUsingSecondStrategy(map, 0, 0, 1, 1); - assertArrayEquals(new int[][] {{2, 2}, {0, 2}}, result); // right -> down - } - - @Test - void testDefaultTargetOutsideSmallMazeThrowsIllegalArgument() { - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0, 0}})); - } - - @Test - void testNullAndEmptyMaze() { - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(null)); - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {})); - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{}})); - } - - @Test - void testJaggedMazeThrows() { - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0}}, 0, 0, 0, 1)); - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {{0}, {0, 0}}, 0, 0, 1, 1)); - } - - @Test - void testStartOrTargetOutOfBoundsThrows() { - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0, 0}}, -1, 0, 1, 1)); - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {{0, 0}, {0, 0}}, 0, 0, 2, 2)); - } - - @Test - void testUnsolvableMazeReturnsNull() { - int[][] map = {{0, 1}, {1, 0}}; - assertNull(MazeRecursion.solveMazeUsingFirstStrategy(map, 0, 0, 1, 1)); - } - } -} + void testSmallMazeWithCustomStartAndTarget() { + int[][] map = {{0, 0}, {0, 0}}; + int[][] result = MazeRecursion.solveMazeUsingFirstStrategy(map, 0, 0, 1, 1); + assertArrayEquals(new int[][] {{2, 0}, {2, 2}}, result); // down -> right + } + + @Test + void testSecondStrategyKeepsItsTraversalOrder() { + int[][] map = {{0, 0}, {0, 0}}; + int[][] result = MazeRecursion.solveMazeUsingSecondStrategy(map, 0, 0, 1, 1); + assertArrayEquals(new int[][] {{2, 2}, {0, 2}}, result); // right -> down + } + + @Test + void testDefaultTargetOutsideSmallMazeThrowsIllegalArgument() { + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0, 0}})); + } + + @Test + void testNullAndEmptyMaze() { + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(null)); + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {})); + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{}})); + } + + @Test + void testJaggedMazeThrows() { + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0}}, 0, 0, 0, 1)); + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {{0}, {0, 0}}, 0, 0, 1, 1)); + } + + @Test + void testStartOrTargetOutOfBoundsThrows() { + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0, 0}}, -1, 0, 1, 1)); + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {{0, 0}, {0, 0}}, 0, 0, 2, 2)); + } + @Test + void testUnsolvableMazeReturnsNull() { + int[][] map = {{0, 1}, {1, 0}}; + assertNull(MazeRecursion.solveMazeUsingFirstStrategy(map, 0, 0, 1, 1)); + } + } +} From a6ede9587267ebe46d9d0e182912084a8d5494fc Mon Sep 17 00:00:00 2001 From: krishnayak986-lang Date: Thu, 12 Nov 2026 20:46:26 +0530 Subject: [PATCH 3/6] test: fix formatting and use fresh maze per strategy --- .../backtracking/MazeRecursionTest.java | 75 ++++++++++--------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java b/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java index 0ac92208fa2e..26602c9ad743 100644 --- a/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java +++ b/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java @@ -162,49 +162,50 @@ public void testSolveMazeUsingFirstAndSecondStrategy() { // Assert the results assertArrayEquals(expectedMap1, solvedMap1); assertArrayEquals(expectedMap2, solvedMap2); + } - @Test - void testSmallMazeWithCustomStartAndTarget() { - int[][] map = {{0, 0}, {0, 0}}; - int[][] result = MazeRecursion.solveMazeUsingFirstStrategy(map, 0, 0, 1, 1); - assertArrayEquals(new int[][] {{2, 0}, {2, 2}}, result); // down -> right - } + @Test + void testSmallMazeWithCustomStartAndTarget() { + int[][] map = {{0, 0}, {0, 0}}; + int[][] result = MazeRecursion.solveMazeUsingFirstStrategy(map, 0, 0, 1, 1); + assertArrayEquals(new int[][] {{2, 0}, {2, 2}}, result); // down -> right + } - @Test - void testSecondStrategyKeepsItsTraversalOrder() { - int[][] map = {{0, 0}, {0, 0}}; - int[][] result = MazeRecursion.solveMazeUsingSecondStrategy(map, 0, 0, 1, 1); - assertArrayEquals(new int[][] {{2, 2}, {0, 2}}, result); // right -> down - } + @Test + void testSecondStrategyKeepsItsTraversalOrder() { + int[][] map = {{0, 0}, {0, 0}}; + int[][] result = MazeRecursion.solveMazeUsingSecondStrategy(map, 0, 0, 1, 1); + assertArrayEquals(new int[][] {{2, 2}, {0, 2}}, result); // right -> down + } - @Test - void testDefaultTargetOutsideSmallMazeThrowsIllegalArgument() { - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0, 0}})); - } + @Test + void testDefaultTargetOutsideSmallMazeThrowsIllegalArgument() { + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0, 0}})); + } - @Test - void testNullAndEmptyMaze() { - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(null)); - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {})); - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{}})); - } + @Test + void testNullAndEmptyMaze() { + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(null)); + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {})); + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{}})); + } - @Test - void testJaggedMazeThrows() { - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0}}, 0, 0, 0, 1)); - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {{0}, {0, 0}}, 0, 0, 1, 1)); - } + @Test + void testJaggedMazeThrows() { + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0}}, 0, 0, 0, 1)); + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {{0}, {0, 0}}, 0, 0, 1, 1)); + } - @Test - void testStartOrTargetOutOfBoundsThrows() { - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0, 0}}, -1, 0, 1, 1)); - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {{0, 0}, {0, 0}}, 0, 0, 2, 2)); - } + @Test + void testStartOrTargetOutOfBoundsThrows() { + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0, 0}}, -1, 0, 1, 1)); + assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {{0, 0}, {0, 0}}, 0, 0, 2, 2)); + } - @Test - void testUnsolvableMazeReturnsNull() { - int[][] map = {{0, 1}, {1, 0}}; - assertNull(MazeRecursion.solveMazeUsingFirstStrategy(map, 0, 0, 1, 1)); - } + @Test + void testUnsolvableMazeReturnsNull() { + int[][] map = {{0, 1}, {1, 0}}; + assertNull(MazeRecursion.solveMazeUsingFirstStrategy(map, 0, 0, 1, 1)); + assertNull(MazeRecursion.solveMazeUsingSecondStrategy(map, 0, 0, 1, 1)); } } From 471c5f6f140e4d901a5773382acc042cb62501ce Mon Sep 17 00:00:00 2001 From: krishnayak986-lang Date: Thu, 12 Nov 2026 22:47:10 +0530 Subject: [PATCH 4/6] test: expect null for default target outside small maze --- .../backtracking/MazeRecursion.java | 50 ++++++++----------- .../backtracking/MazeRecursionTest.java | 5 +- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java b/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java index c6be553bd3ca..b252dd1a55d7 100644 --- a/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java +++ b/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java @@ -6,23 +6,20 @@ * ends are marked with different integers. */ public final class MazeRecursion { - private static final int[][] FIRST_STRATEGY_DIRECTIONS = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; - private static final int[][] SECOND_STRATEGY_DIRECTIONS = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; - 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_COL = 1; - private static final int DEFAULT_TARGET_ROW = 6; - private static final int DEFAULT_TARGET_COL = 5; + 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 = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + 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 = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; + private static final int[][] SECOND_STRATEGY_DIRECTIONS = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; private MazeRecursion() { } @@ -36,14 +33,7 @@ private MazeRecursion() { * @throws IllegalArgumentException if the maze is null, empty, or not rectangular */ public static int[][] solveMazeUsingFirstStrategy(int[][] map) { - validateMaze(map); - if (!isInBounds(map, 1, 1) || !isInBounds(map, 6, 5)) { - return null; - } - if (map[6][5] == 2) { - return map; - } - return solve(map, 1, 1, 6, 5, FIRST_STRATEGY_DIRECTIONS) ? map : null; + return solveWithDefaultEndpoints(map, FIRST_STRATEGY_DIRECTIONS); } /** @@ -55,14 +45,7 @@ public static int[][] solveMazeUsingFirstStrategy(int[][] map) { * @throws IllegalArgumentException if the maze is null, empty, or not rectangular */ public static int[][] solveMazeUsingSecondStrategy(int[][] map) { - validateMaze(map); - if (!isInBounds(map, 1, 1) || !isInBounds(map, 6, 5)) { - return null; - } - if (map[6][5] == 2) { - return map; - } - return solve(map, 1, 1, 6, 5, SECOND_STRATEGY_DIRECTIONS) ? map : null; + return solveWithDefaultEndpoints(map, SECOND_STRATEGY_DIRECTIONS); } /** @@ -99,12 +82,23 @@ public static int[][] solveMazeUsingSecondStrategy(int[][] map, int startRow, in 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] != 0) { + if (!isInBounds(map, row, column) || map[row][column] != OPEN) { return false; } - map[row][column] = 2; + map[row][column] = PATH; if (row == goalRow && column == goalColumn) { return true; } @@ -115,7 +109,7 @@ private static boolean solve(int[][] map, int row, int column, int goalRow, int } } - map[row][column] = 3; + map[row][column] = DEAD_END; return false; } @@ -143,4 +137,4 @@ private static void validateCoordinates(int[][] map, int startRow, int startColu private static boolean isInBounds(int[][] map, int row, int column) { return row >= 0 && row < map.length && column >= 0 && column < map[row].length; } -} +} diff --git a/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java b/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java index 26602c9ad743..7af4c9ea7fca 100644 --- a/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java +++ b/src/test/java/com/thealgorithms/backtracking/MazeRecursionTest.java @@ -179,8 +179,9 @@ void testSecondStrategyKeepsItsTraversalOrder() { } @Test - void testDefaultTargetOutsideSmallMazeThrowsIllegalArgument() { - assertThrows(IllegalArgumentException.class, () -> MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0, 0}})); + void testDefaultTargetOutsideSmallMazeReturnsNull() { + assertNull(MazeRecursion.solveMazeUsingFirstStrategy(new int[][] {{0, 0}, {0, 0}})); + assertNull(MazeRecursion.solveMazeUsingSecondStrategy(new int[][] {{0, 0}, {0, 0}})); } @Test From 625b89ce3d4a36cb4a06ae83436749bbfa044587 Mon Sep 17 00:00:00 2001 From: krishnayak986-lang Date: Thu, 12 Nov 2026 22:59:04 +0530 Subject: [PATCH 5/6] style: remove trailing whitespace in MazeRecursion --- src/main/java/com/thealgorithms/backtracking/MazeRecursion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java b/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java index b252dd1a55d7..e3fecef4e6fa 100644 --- a/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java +++ b/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java @@ -137,4 +137,4 @@ private static void validateCoordinates(int[][] map, int startRow, int startColu private static boolean isInBounds(int[][] map, int row, int column) { return row >= 0 && row < map.length && column >= 0 && column < map[row].length; } -} +} From e2484be8a71b40bc1973d88262a3ddfdceeecfda Mon Sep 17 00:00:00 2001 From: krishnayak986-lang Date: Thu, 12 Nov 2026 23:11:06 +0530 Subject: [PATCH 6/6] style: remove trailing whitespace --- src/main/java/com/thealgorithms/backtracking/MazeRecursion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java b/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java index e3fecef4e6fa..c818aa8c888c 100644 --- a/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java +++ b/src/main/java/com/thealgorithms/backtracking/MazeRecursion.java @@ -137,4 +137,4 @@ private static void validateCoordinates(int[][] map, int startRow, int startColu private static boolean isInBounds(int[][] map, int row, int column) { return row >= 0 && row < map.length && column >= 0 && column < map[row].length; } -} +}