diff --git a/mazeWithManySolutions.txt b/mazeWithManySolutions.txt new file mode 100644 index 0000000..d72574a --- /dev/null +++ b/mazeWithManySolutions.txt @@ -0,0 +1,13 @@ +11 11 +⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛ +⬛⬜⬜⬜⬛⬜⬜⬜⬛⬜⬛ +⬛⬜⬛⬛⬛⬜⬛⬜⬛⬜⬛ +⬛⬜⬜⬜⬜⬜⬜⬜⬜⬜⬛ +⬛⬛⬛⬜⬛⬜⬛⬜⬛⬜⬛ +⬛⬜⬛⬜⬜⬜⬛⬜⬜⬜⬛ +⬛⬜⬛⬜⬛⬜⬛⬜⬛⬛⬛ +⬛⬜⬛⬜⬛⬜⬜⬜⬜⬜⬛ +⬛⬛⬛⬜⬛⬛⬛⬛⬛⬜⬛ +⬛⬜⬜⬜⬜⬜⬛⬜⬜⬜⬛ +⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛ + diff --git a/mazeWithOneSolution.txt b/mazeWithOneSolution.txt new file mode 100644 index 0000000..2da205d --- /dev/null +++ b/mazeWithOneSolution.txt @@ -0,0 +1,13 @@ +11 11 +⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛ +⬛⬜⬛⬜⬜⬜⬛⬜⬜⬜⬛ +⬛⬜⬛⬜⬛⬜⬛⬜⬛⬜⬛ +⬛⬜⬛⬜⬛⬜⬜⬜⬛⬜⬛ +⬛⬜⬛⬛⬛⬛⬛⬛⬛⬜⬛ +⬛⬜⬜⬜⬜⬜⬛⬜⬜⬜⬛ +⬛⬛⬛⬛⬛⬜⬛⬜⬛⬜⬛ +⬛⬜⬜⬜⬜⬜⬛⬜⬛⬜⬛ +⬛⬜⬛⬛⬛⬛⬛⬜⬛⬜⬛ +⬛⬜⬜⬜⬜⬜⬜⬜⬛⬜⬛ +⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛⬛ + diff --git a/pom.xml b/pom.xml index bf40001..a1bf538 100644 --- a/pom.xml +++ b/pom.xml @@ -218,4 +218,8 @@ + + + + diff --git a/prettyOutputMaze.txt b/prettyOutputMaze.txt new file mode 100644 index 0000000..acbb971 --- /dev/null +++ b/prettyOutputMaze.txt @@ -0,0 +1,11 @@ +⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️ +⬛️⬜️⬜️⬜️⬛️⬜️⬜️⬜️⬛️⬜️⬛️ +⬛️⬜️⬛️⬛️⬛️⬜️⬛️⬜️⬛️⬜️⬛️ +⬛️⬜️⬜️⬜️⬜️⬜️⬜️⬜️⬜️⬜️⬛️ +⬛️⬛️⬛️⬜️⬛️⬜️⬛️⬜️⬛️⬜️⬛️ +⬛️⬜️⬛️⬜️⬜️⬜️⬛️⬜️⬜️⬜️⬛️ +⬛️⬜️⬛️⬜️⬛️⬜️⬛️⬜️⬛️⬛️⬛️ +⬛️⬜️⬛️⬜️⬛️⬜️⬜️⬜️⬜️⬜️⬛️ +⬛️⬛️⬛️⬜️⬛️⬛️⬛️⬛️⬛️⬜️⬛️ +⬛️⬜️⬜️⬜️⬜️⬜️⬛️⬜️⬜️⬜️⬛️ +⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️ diff --git a/prettyOutputMazeWithSolution.txt b/prettyOutputMazeWithSolution.txt new file mode 100644 index 0000000..aaa9dad --- /dev/null +++ b/prettyOutputMazeWithSolution.txt @@ -0,0 +1,11 @@ +⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️ +⬛️🚩⬜️⬜️⬛️⬜️⬜️⬜️⬛️⬜️⬛️ +⬛️🟥⬛️⬛️⬛️⬜️⬛️⬜️⬛️⬜️⬛️ +⬛️🟥🟥🟥⬜️⬜️⬜️⬜️⬜️⬜️⬛️ +⬛️⬛️⬛️🟥⬛️⬜️⬛️⬜️⬛️⬜️⬛️ +⬛️⬜️⬛️🟥⬜️⬜️⬛️⬜️⬜️⬜️⬛️ +⬛️⬜️⬛️🟥⬛️⬜️⬛️⬜️⬛️⬛️⬛️ +⬛️⬜️⬛️🟥⬛️⬜️⬜️⬜️⬜️⬜️⬛️ +⬛️⬛️⬛️🟥⬛️⬛️⬛️⬛️⬛️⬜️⬛️ +⬛️🚩🟥🟥⬜️⬜️⬛️⬜️⬜️⬜️⬛️ +⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️ diff --git a/solution11to55.txt b/solution11to55.txt new file mode 100644 index 0000000..d676f80 --- /dev/null +++ b/solution11to55.txt @@ -0,0 +1,9 @@ +1 1 +2 1 +3 1 +4 1 +5 1 +5 2 +5 3 +5 4 +5 5 diff --git a/solution11to99.txt b/solution11to99.txt new file mode 100644 index 0000000..4ca9764 --- /dev/null +++ b/solution11to99.txt @@ -0,0 +1,33 @@ +1 1 +2 1 +3 1 +4 1 +5 1 +5 2 +5 3 +5 4 +5 5 +6 5 +7 5 +7 4 +7 3 +7 2 +7 1 +8 1 +9 1 +9 2 +9 3 +9 4 +9 5 +9 6 +9 7 +8 7 +7 7 +6 7 +5 7 +5 8 +5 9 +6 9 +7 9 +8 9 +9 9 diff --git a/src/main/java/edu/project2/Cell.java b/src/main/java/edu/project2/Cell.java new file mode 100644 index 0000000..f21e53c --- /dev/null +++ b/src/main/java/edu/project2/Cell.java @@ -0,0 +1,5 @@ +package edu.project2; + +public record Cell(int row, int col, Type type) { + public enum Type { WALL, PASSAGE } +} diff --git a/src/main/java/edu/project2/Coordinate.java b/src/main/java/edu/project2/Coordinate.java new file mode 100644 index 0000000..61e3915 --- /dev/null +++ b/src/main/java/edu/project2/Coordinate.java @@ -0,0 +1,9 @@ +package edu.project2; + +public record Coordinate(int row, int col) { + + @Override + public String toString() { + return row + " " + col; + } +} diff --git a/src/main/java/edu/project2/Generator.java b/src/main/java/edu/project2/Generator.java new file mode 100644 index 0000000..2ed3886 --- /dev/null +++ b/src/main/java/edu/project2/Generator.java @@ -0,0 +1,185 @@ +package edu.project2; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Random; +import java.util.Stack; + +public class Generator { + + static final int START_TO_FIND_NEIGHBOUR = -2; + + static final int STEP_TO_FIND_NEIGHBOUR = 4; + + static final int[] ROW_MOVE = {-1, 1, 0, 0}; + static final int[] COL_MOVE = {0, 0, -1, 1}; + + private Generator() { + } + + static public Maze generateWithDfs(int givenHeight, int givenWidth) { + assert givenHeight > 0; + assert givenWidth > 0; + + int height = givenHeight * 2 + 1; + int width = givenWidth * 2 + 1; + + Cell[][] grid = createDefaultMaze(height, width); + + HashSet unvisitedCells = createUnvisitedCellsSet(height, width); + + Coordinate currentCoord = new Coordinate(1, 1); + unvisitedCells.remove(currentCoord); + + Stack stack = new Stack<>(); + + while (!unvisitedCells.isEmpty()) { + Coordinate unvisitedNeighbour = getNeighbours(currentCoord, height, width, unvisitedCells); + if (unvisitedNeighbour != null) { + stack.push(currentCoord); + int row = currentCoord.row() + (unvisitedNeighbour.row() - currentCoord.row()) / 2; + int col = currentCoord.col() + (unvisitedNeighbour.col() - currentCoord.col()) / 2; + grid[row][col] = new Cell(row, col, Cell.Type.PASSAGE); + currentCoord = unvisitedNeighbour; + unvisitedCells.remove(currentCoord); + } else if (!stack.isEmpty()) { + currentCoord = stack.pop(); + } else { + currentCoord = unvisitedCells.iterator().next(); + unvisitedCells.remove(currentCoord); + } + } + + return new Maze(height, width, grid); + } + + static Cell[][] createDefaultMaze(int height, int width) { + + Cell[][] grid = new Cell[height][width]; + + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + if (i % 2 == 0 || j % 2 == 0) { + grid[i][j] = new Cell(i, j, Cell.Type.WALL); + } else { + grid[i][j] = new Cell(i, j, Cell.Type.PASSAGE); + } + } + } + + return grid; + } + + static Coordinate getNeighbours(Coordinate coordinate, int height, int width, HashSet unvisited) { + + ArrayList unvisitedNeighbours = new ArrayList<>(); + + for (int i = START_TO_FIND_NEIGHBOUR; i <= 2; i += STEP_TO_FIND_NEIGHBOUR) { + Solver.checkNeighbours(coordinate, height, width, unvisited, unvisitedNeighbours, i); + } + if (unvisitedNeighbours.isEmpty()) { + return null; + } + return unvisitedNeighbours.get(new Random().nextInt(unvisitedNeighbours.size())); + + } + + static HashSet createUnvisitedCellsSet(int height, int width) { + HashSet unvisitedCells = new HashSet<>(); + for (int i = 1; i < height; i += 2) { + for (int j = 1; j < width; j += 2) { + unvisitedCells.add(new Coordinate(i, j)); + } + } + return unvisitedCells; + } + + static boolean isValidCoordinate(int row, int col, int height, int width) { + return 1 <= row && row < height && 1 <= col && col < width; + } + + static public Maze generateWithPrimaAlgorithm(int givenHeight, int givenWidth) { + + assert givenHeight > 0; + assert givenWidth > 0; + int height = givenHeight * 2 + 1; + int width = givenWidth * 2 + 1; + Cell[][] grid = createAllWallsGrid(height, width); + + Random rd = new Random(); + int row = rd.nextInt(height / 2) * 2 + 1; + int col = rd.nextInt(width / 2) * 2 + 1; + grid[row][col] = new Cell(row, col, Cell.Type.PASSAGE); + + ArrayList cellsToCheck = createCellsToCheck(row, col, height, width); + + while (!cellsToCheck.isEmpty()) { + int index = rd.nextInt(cellsToCheck.size()); + Coordinate coordinate = cellsToCheck.get(index); + row = coordinate.row(); + col = coordinate.col(); + grid[row][col] = new Cell(row, col, Cell.Type.PASSAGE); + cellsToCheck.remove(index); + + ArrayList directions = new ArrayList<>(); + + for (int i = 0; i < ROW_MOVE.length; i++) { + directions.add(i); + } + + while (!directions.isEmpty()) { + int dirIndex = rd.nextInt(directions.size()); + int direction = directions.get(dirIndex); + + if (isValidCoordinate(row + ROW_MOVE[dirIndex] * 2, col + COL_MOVE[dirIndex] * 2, height, width) + && + grid[row + ROW_MOVE[dirIndex] * 2][col + COL_MOVE[dirIndex] * 2].type().equals(Cell.Type.PASSAGE)) { + int curRow = row + ROW_MOVE[dirIndex]; + int curCol = col + COL_MOVE[dirIndex]; + grid[curRow][curCol] = new Cell(curRow, curCol, Cell.Type.PASSAGE); + directions.clear(); + continue; + } + + directions.remove(dirIndex); + + } + + for (int i = 0; i < ROW_MOVE.length; i++) { + int curRow = row + ROW_MOVE[i] * 2; + int curCol = col + COL_MOVE[i] * 2; + if (isValidCoordinate(curRow, curCol, height, width) + && grid[curRow][curCol].type().equals(Cell.Type.WALL)) { + cellsToCheck.add(new Coordinate(curRow, curCol)); + } + } + + } + + return new Maze(height, width, grid); + } + + static ArrayList createCellsToCheck(int row, int col, int height, int width) { + + ArrayList cellsToCheck = new ArrayList<>(); + for (int i = 0; i < ROW_MOVE.length; i++) { + if (isValidCoordinate(row + ROW_MOVE[i] * 2, col + COL_MOVE[i] * 2, height, width)) { + cellsToCheck.add(new Coordinate(row + ROW_MOVE[i] * 2, col + COL_MOVE[i] * 2)); + } + } + return cellsToCheck; + } + + static Cell[][] createAllWallsGrid(int height, int width) { + Cell[][] grid = new Cell[width][height]; + + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + grid[i][j] = new Cell(i, j, Cell.Type.WALL); + } + } + return grid; + } + +} + diff --git a/src/main/java/edu/project2/Main.java b/src/main/java/edu/project2/Main.java new file mode 100644 index 0000000..8ea4cc2 --- /dev/null +++ b/src/main/java/edu/project2/Main.java @@ -0,0 +1,99 @@ +package edu.project2; + +import java.util.ArrayList; +import java.util.Scanner; +import static edu.project2.Generator.generateWithDfs; +import static edu.project2.Generator.generateWithPrimaAlgorithm; +import static edu.project2.Renderer.render; +import static edu.project2.Solver.solveWithBackTracking; +import static edu.project2.Solver.solveWithBfs; + +@SuppressWarnings("RegexpSinglelineJava") +class Main { + + static final int MAZE_SIZE = 9; + static final int LOWER_RIGHT_COORD = MAZE_SIZE * 2 - 1; + + private Main() { + } + + static void printStarting() { + System.out.println("Welcome to maze generation!"); + } + + static void printGenerationStart() { + System.out.println( + "Print 0, if you want to generate maze with dfs algorithm " + + "or 1, if you want to generate maze with Prima algorithm"); + System.out.println("Print -1 to quit"); + } + + static void printSolvingStart() { + System.out.println( + "Print 0, if you want to solve maze with bfs or 1, if you want to solve maze with dfs algorithm"); + } + + static void printIncorrectInput() { + System.out.println("Input is incorrect"); + } + + static void printNotSolved() { + System.out.println("Can't solve the maze"); + } + + static void printTryToFind() { + System.out.println("Trying to find the solution from upper left corner to lower right corner..."); + } + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + Maze maze; + int rows = MAZE_SIZE; + int cols = MAZE_SIZE; + printStarting(); + while (true) { + printGenerationStart(); + String userInput = scanner.nextLine(); + if (userInput.equals("-1")) { + break; + } + if (userInput.equals("0")) { + maze = generateWithDfs(rows, cols); + } else if (userInput.equals("1")) { + maze = generateWithPrimaAlgorithm(rows, cols); + } else { + printIncorrectInput(); + continue; + } + System.out.println(render(maze)); + printSolvingStart(); + String solveAlgorithm = scanner.nextLine(); + + if (solveAlgorithm.equals("-1")) { + break; + } + while (!solveAlgorithm.equals("0") && !solveAlgorithm.equals("1")) { + printIncorrectInput(); + solveAlgorithm = scanner.nextLine(); + } + ArrayList solution; + printTryToFind(); + if (solveAlgorithm.equals("0")) { + solution = + solveWithBfs(maze, new Coordinate(1, 1), new Coordinate(LOWER_RIGHT_COORD, LOWER_RIGHT_COORD)); + } else { + solution = solveWithBackTracking(maze, + new Coordinate(1, 1), + new Coordinate(LOWER_RIGHT_COORD, LOWER_RIGHT_COORD) + ); + } + if (solution.isEmpty()) { + printNotSolved(); + continue; + } + System.out.println(render(maze, solution)); + } + + } + +} diff --git a/src/main/java/edu/project2/Maze.java b/src/main/java/edu/project2/Maze.java new file mode 100644 index 0000000..567ce60 --- /dev/null +++ b/src/main/java/edu/project2/Maze.java @@ -0,0 +1,25 @@ +package edu.project2; + +public final class Maze { + private final int height; + private final int width; + private final Cell[][] grid; + + public Maze(int height, int width, Cell[][] grid) { + this.height = height; + this.width = width; + this.grid = grid; + } + + Cell.Type getCellType(int i, int j) { + return grid[i][j].type(); + } + + public int getHeight() { + return height; + } + + public int getWidth() { + return width; + } +} diff --git a/src/main/java/edu/project2/Renderer.java b/src/main/java/edu/project2/Renderer.java new file mode 100644 index 0000000..f96b9da --- /dev/null +++ b/src/main/java/edu/project2/Renderer.java @@ -0,0 +1,68 @@ +package edu.project2; + +import java.util.ArrayList; +import java.util.HashSet; + +public class Renderer { + + private Renderer() { + } + + static final String PASSAGE_SYMBOL = "⬜\uFE0F"; + static final String WALL_SYMBOL = "⬛\uFE0F"; + + static final String PATH_SYMBOL = "\uD83D\uDFE5"; + + @SuppressWarnings("MultipleStringLiterals") + static final String START_SYMBOL = "\uD83D\uDEA9"; + + static final String FINISH_SYMBOL = "\uD83D\uDEA9"; + + static public String render(Maze maze) { + + StringBuilder result = new StringBuilder(); + for (int i = 0; i < maze.getHeight(); i++) { + for (int j = 0; j < maze.getWidth(); j++) { + if (maze.getCellType(i, j).equals(Cell.Type.WALL)) { + result.append(WALL_SYMBOL); + } else { + result.append(PASSAGE_SYMBOL); + } + } + result.append('\n'); + } + return result.toString(); + } + + static public String render(Maze maze, ArrayList path) { + + assert !path.isEmpty(); + + Coordinate start = path.getFirst(); + Coordinate finish = path.getLast(); + + HashSet myPath = new HashSet<>(path); + StringBuilder result = new StringBuilder(); + + for (int i = 0; i < maze.getHeight(); i++) { + for (int j = 0; j < maze.getWidth(); j++) { + + Coordinate curCoord = new Coordinate(i, j); + if (curCoord.equals(start)) { + result.append(START_SYMBOL); + } else if (curCoord.equals(finish)) { + result.append(FINISH_SYMBOL); + } else if (myPath.contains(curCoord)) { + result.append(PATH_SYMBOL); + } else if (maze.getCellType(i, j).equals(Cell.Type.WALL)) { + result.append(WALL_SYMBOL); + } else { + result.append(PASSAGE_SYMBOL); + } + } + result.append('\n'); + } + return result.toString(); + + } +} diff --git a/src/main/java/edu/project2/Solver.java b/src/main/java/edu/project2/Solver.java new file mode 100644 index 0000000..cc0747b --- /dev/null +++ b/src/main/java/edu/project2/Solver.java @@ -0,0 +1,146 @@ +package edu.project2; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Random; +import java.util.Stack; +import static edu.project2.Generator.isValidCoordinate; + +public class Solver { + + private Solver() { + } + + static public ArrayList solveWithBfs(Maze maze, Coordinate start, Coordinate end) { + + boolean[][] visited = new boolean[maze.getHeight()][maze.getWidth()]; + Coordinate[][] comeFrom = new Coordinate[maze.getHeight()][maze.getWidth()]; + + for (boolean[] line : visited) { + Arrays.fill(line, false); + } + + visited[start.row()][start.col()] = true; + + ArrayDeque queue = new ArrayDeque<>(); + + queue.addLast(start); + + int[] rowMove = {-1, 1, 0, 0}; + int[] colMove = {0, 0, -1, 1}; + + while (!queue.isEmpty()) { + Coordinate currentCell = queue.pop(); + for (int i = 0; i < rowMove.length; i++) { + int newRow = currentCell.row() + rowMove[i]; + int newCol = currentCell.col() + colMove[i]; + if (!visited[newRow][newCol] && maze.getCellType(newRow, newCol) == Cell.Type.PASSAGE) { + comeFrom[newRow][newCol] = currentCell; + visited[newRow][newCol] = true; + queue.addLast(new Coordinate(newRow, newCol)); + } + } + if (visited[end.row()][end.col()]) { + break; + } + } + + ArrayList answer = new ArrayList<>(); + + if (!visited[end.row()][end.col()]) { + return answer; + } + + Coordinate currentCoord = end; + + while (currentCoord != start) { + answer.add(currentCoord); + currentCoord = comeFrom[currentCoord.row()][currentCoord.col()]; + } + answer.add(currentCoord); + + Collections.reverse(answer); + + return answer; + } + + static public ArrayList solveWithBackTracking(Maze maze, Coordinate start, Coordinate end) { + + HashSet unvisitedCells = new HashSet<>(); + + for (int i = 1; i < maze.getHeight(); i++) { + for (int j = 1; j < maze.getWidth(); j++) { + if (maze.getCellType(i, j) == Cell.Type.PASSAGE) { + unvisitedCells.add(new Coordinate(i, j)); + } + } + } + + Coordinate currentCoord = start; + unvisitedCells.remove(currentCoord); + + Stack stack = new Stack<>(); + + while (true) { + Coordinate unvisitedNeighbour = + getNeighbours(currentCoord, maze.getHeight(), maze.getWidth(), unvisitedCells); + if (unvisitedNeighbour != null) { + stack.push(currentCoord); + + if (unvisitedNeighbour.equals(end)) { + stack.push(unvisitedNeighbour); + break; + } + currentCoord = unvisitedNeighbour; + unvisitedCells.remove(currentCoord); + + } else if (!stack.isEmpty()) { + currentCoord = stack.pop(); + } else { + return new ArrayList<>(); + } + } + + ArrayList answer = new ArrayList<>(stack); + return answer; + + } + + static Coordinate getNeighbours(Coordinate coordinate, int height, int width, HashSet unvisited) { + ArrayList unvisitedNeighbours = new ArrayList<>(); + for (int i = -1; i <= 1; i += 2) { + checkNeighbours(coordinate, height, width, unvisited, unvisitedNeighbours, i); + } + + if (unvisitedNeighbours.isEmpty()) { + return null; + } + return unvisitedNeighbours.get(new Random().nextInt(unvisitedNeighbours.size())); + + } + + static void checkNeighbours( + Coordinate coordinate, + int height, + int width, + HashSet unvisited, + ArrayList unvisitedNeighbours, + int i + ) { + if (isValidCoordinate(coordinate.row(), coordinate.col() + i, height, width)) { + Coordinate currentCoord = new Coordinate(coordinate.row(), coordinate.col() + i); + if (unvisited.contains(currentCoord)) { + unvisitedNeighbours.add(currentCoord); + } + } + if (isValidCoordinate(coordinate.row() + i, coordinate.col(), height, width)) { + Coordinate currentCoord = new Coordinate(coordinate.row() + i, coordinate.col()); + if (unvisited.contains(currentCoord)) { + unvisitedNeighbours.add(currentCoord); + } + } + } +} diff --git a/src/test/java/edu/hw1/SampleTest.java b/src/test/java/edu/hw1/SampleTest.java deleted file mode 100644 index b16f423..0000000 --- a/src/test/java/edu/hw1/SampleTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package edu.hw1; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -public class SampleTest { - @Test - @DisplayName("Фильтрация четных чисел") - void filterEvenNumbers() { - // given - int[] numbers = new int[] {1, 2, 3, 4, 5}; - - // when - int[] evenNumbers = EvenArrayUtils.filter(numbers); - - // then - assertThat(evenNumbers) - .containsExactly(2, 4) - .hasSize(2); - } -} diff --git a/src/test/java/edu/project2/GeneratorTest.java b/src/test/java/edu/project2/GeneratorTest.java new file mode 100644 index 0000000..21d2708 --- /dev/null +++ b/src/test/java/edu/project2/GeneratorTest.java @@ -0,0 +1,28 @@ +package edu.project2; + +import org.junit.jupiter.api.Test; +import static edu.project2.Generator.generateWithDfs; +import static edu.project2.Generator.generateWithPrimaAlgorithm; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class GeneratorTest { + + private GeneratorTest() { + } + + @Test + void generateWithDfsTest() { + assertThrows(AssertionError.class, () -> generateWithDfs(-1, 2)); + assertThrows(AssertionError.class, () -> generateWithDfs(2, -1)); + assertThrows(AssertionError.class, () -> generateWithDfs(0, 0)); + + } + + @Test + void generateWithPrimaAlgorithmTest() { + assertThrows(AssertionError.class, () -> generateWithPrimaAlgorithm(-1, 2)); + assertThrows(AssertionError.class, () -> generateWithPrimaAlgorithm(2, -1)); + assertThrows(AssertionError.class, () -> generateWithPrimaAlgorithm(0, 0)); + + } +} diff --git a/src/test/java/edu/project2/RendererTest.java b/src/test/java/edu/project2/RendererTest.java new file mode 100644 index 0000000..2858540 --- /dev/null +++ b/src/test/java/edu/project2/RendererTest.java @@ -0,0 +1,64 @@ +package edu.project2; + +import org.junit.jupiter.api.Test; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import static edu.project2.Renderer.render; +import static edu.project2.Solver.solveWithBfs; +import static edu.project2.SolverTest.readMazeFromFile; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class RendererTest { + + @Test + void rendererWithPathTest() { + Maze maze = new Maze( + 3, + 3, + new Cell[][] { + {new Cell(0, 0, Cell.Type.WALL), new Cell(0, 0, Cell.Type.WALL), new Cell(0, 0, Cell.Type.WALL)}, + {new Cell(0, 0, Cell.Type.WALL), new Cell(0, 0, Cell.Type.PASSAGE), new Cell(0, 0, Cell.Type.WALL)}, + {new Cell(0, 0, Cell.Type.WALL), new Cell(0, 0, Cell.Type.PASSAGE), new Cell(0, 0, Cell.Type.WALL)}} + ); + + ArrayList path = new ArrayList<>(); + assertThrows(AssertionError.class, () -> render(maze, path)); + } + + @Test + void renderOutputTest() { + Maze maze = readMazeFromFile("mazeWithManySolutions.txt"); + String renderResult = render(maze); + assertEquals(readFromFile("prettyOutputMaze.txt"), renderResult); + } + + @Test + void renderWithPathOutputTest() { + Maze maze = readMazeFromFile("mazeWithManySolutions.txt"); + String renderResult = render(maze, solveWithBfs(maze, new Coordinate(1, 1), new Coordinate(9, 1))); + assertEquals(readFromFile("prettyOutputMazeWithSolution.txt"), renderResult); + } + + String readFromFile(String fileName) { + + StringBuilder expectedResult = new StringBuilder(); + try { + BufferedReader reader = new BufferedReader(new FileReader(fileName)); + while (reader.ready()) { + expectedResult.append(reader.readLine()); + expectedResult.append('\n'); + } + + return expectedResult.toString(); + + } catch (IOException ex) { + + System.out.println(ex.getMessage()); + } + return null; + } + +} diff --git a/src/test/java/edu/project2/SolverTest.java b/src/test/java/edu/project2/SolverTest.java new file mode 100644 index 0000000..75e90c5 --- /dev/null +++ b/src/test/java/edu/project2/SolverTest.java @@ -0,0 +1,110 @@ +package edu.project2; + +import org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import static edu.project2.Solver.solveWithBackTracking; +import static edu.project2.Solver.solveWithBfs; + +public class SolverTest { + + static Maze mazeWithOneSolution = readMazeFromFile("mazeWithOneSolution.txt"); + + static Maze mazeWithManySolutions = readMazeFromFile("mazeWithManySolutions.txt"); + + ArrayList mySolutionFrom11To99 = readSolutionfromFile("solution11to99.txt"); + ArrayList mySolutionFrom11To55 = readSolutionfromFile("solution11to55.txt"); + + Coordinate coordinate11 = new Coordinate(1, 1); + + Coordinate coordinate99 = new Coordinate(9, 9); + + Coordinate coordinate55 = new Coordinate(5, 5); + + Coordinate coordinate51 = new Coordinate(5, 1); + + ArrayList readSolutionfromFile(String fileName) { + try { + ArrayList result = new ArrayList<>(); + BufferedReader reader = new BufferedReader(new FileReader(fileName)); + + String line; + + while (reader.ready()) { + line = reader.readLine(); + String[] coordinate = line.split(" "); + result.add(new Coordinate(Integer.parseInt(coordinate[0]), Integer.parseInt(coordinate[1]))); + } + return result; + + } catch (IOException ex) { + + System.out.println(ex.getMessage()); + } + + return null; + } + + static Maze readMazeFromFile(String fileName) { + + try { + BufferedReader reader = new BufferedReader(new FileReader(fileName)); + + String size = reader.readLine(); + + String[] splittedSize = size.split(" "); + int height = Integer.parseInt(splittedSize[0]); + int width = Integer.parseInt(splittedSize[1]); + + Cell[][] grid = new Cell[height][width]; + + for (int i = 0; i < height; i++) { + String line = reader.readLine(); + for (int j = 0; j < width; j++) { + if (line.charAt(j) == '⬜') { + grid[i][j] = new Cell(i, j, Cell.Type.PASSAGE); + } else { + grid[i][j] = new Cell(i, j, Cell.Type.WALL); + } + } + } + return new Maze(height, width, grid); + } catch (IOException ex) { + + System.out.println(ex.getMessage()); + } + + return null; + + } + + @Test + void solveWithBfsTest() { + Assertions.assertEquals(mySolutionFrom11To99, solveWithBfs(mazeWithOneSolution, coordinate11, coordinate99)); + Assertions.assertEquals(mySolutionFrom11To55, solveWithBfs(mazeWithOneSolution, coordinate11, coordinate55)); + + Assertions.assertFalse(solveWithBfs(mazeWithManySolutions, coordinate11, coordinate55).isEmpty()); + Assertions.assertTrue(solveWithBfs(mazeWithManySolutions, coordinate11, coordinate51).isEmpty()); + Assertions.assertTrue(solveWithBfs(mazeWithManySolutions, coordinate51, coordinate99).isEmpty()); + + } + + @Test + void solveWithBackTrackingTest() { + + Assertions.assertEquals(mySolutionFrom11To99, solveWithBackTracking(mazeWithOneSolution, coordinate11, coordinate99)); + Assertions.assertEquals(mySolutionFrom11To55, solveWithBackTracking(mazeWithOneSolution, coordinate11, coordinate55)); + + Assertions.assertFalse(solveWithBackTracking(mazeWithManySolutions, coordinate11, coordinate55).isEmpty()); + Assertions.assertTrue(solveWithBackTracking(mazeWithManySolutions, coordinate11, coordinate51).isEmpty()); + Assertions.assertTrue(solveWithBackTracking(mazeWithManySolutions, coordinate51, coordinate99).isEmpty()); + + } + + + +}