diff --git a/maven-settings.xml b/maven-settings.xml
index b98bb47..9e840fd 100644
--- a/maven-settings.xml
+++ b/maven-settings.xml
@@ -10,7 +10,7 @@
ossrh
- 4etdRvZF
+ fritteli
${env.REPO_TOKEN_OSSRH}
diff --git a/pom.xml b/pom.xml
index 980deec..80c5513 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,12 +5,12 @@
ch.fritteli
fritteli-build-parent
- 5.1.0
+ 5.0.0
ch.fritteli.a-maze-r
maze-generator
- 0.3.1-SNAPSHOT
+ 0.2.0
A-Maze-R, The Maze Generator. It is a library for generating mazes in various output formats.
@@ -43,7 +43,7 @@
scm:git:https://gittr.ch/java/maze-generator.git
scm:git:ssh://git@gittr.ch/java/maze-generator.git
https://gittr.ch/java/maze-generator
- HEAD
+ v0.2.0
@@ -55,16 +55,22 @@
+ 3.25.3
2.17.1
1.2.1
+ 1.5.6
+ 1.18.32
+ 21
4.0.0-M8
3.0.2
+ 2.0.12
org.projectlombok
lombok
+ ${lombok.version}
org.jetbrains
@@ -74,11 +80,6 @@
io.vavr
vavr
-
- com.google.guava
- guava
- 33.2.1-jre
-
org.apache.pdfbox
pdfbox
@@ -97,10 +98,12 @@
org.slf4j
slf4j-api
+ ${slf4j.version}
ch.qos.logback
logback-classic
+ ${logback.version}
org.junit.jupiter
@@ -109,6 +112,7 @@
org.assertj
assertj-core
+ ${assertj.version}
test
diff --git a/src/main/java/ch/fritteli/maze/generator/algorithm/AbstractMazeGeneratorAlgorithm.java b/src/main/java/ch/fritteli/maze/generator/algorithm/AbstractMazeGeneratorAlgorithm.java
deleted file mode 100644
index 2037f76..0000000
--- a/src/main/java/ch/fritteli/maze/generator/algorithm/AbstractMazeGeneratorAlgorithm.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package ch.fritteli.maze.generator.algorithm;
-
-import ch.fritteli.maze.generator.model.Maze;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Random;
-
-public abstract class AbstractMazeGeneratorAlgorithm implements MazeGeneratorAlgorithm {
- @NotNull
- protected final Maze maze;
- @NotNull
- protected final Random random;
-
-
- protected AbstractMazeGeneratorAlgorithm(@NotNull final Maze maze, @NotNull final String algorithmName) {
- this.maze = maze;
- this.random = new Random(maze.getRandomSeed());
- this.maze.setAlgorithm(algorithmName);
- }
-}
diff --git a/src/main/java/ch/fritteli/maze/generator/algorithm/MazeGeneratorAlgorithm.java b/src/main/java/ch/fritteli/maze/generator/algorithm/MazeGeneratorAlgorithm.java
deleted file mode 100644
index 0cc091a..0000000
--- a/src/main/java/ch/fritteli/maze/generator/algorithm/MazeGeneratorAlgorithm.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package ch.fritteli.maze.generator.algorithm;
-
-public interface MazeGeneratorAlgorithm {
- void run();
-}
diff --git a/src/main/java/ch/fritteli/maze/generator/algorithm/RandomDepthFirst.java b/src/main/java/ch/fritteli/maze/generator/algorithm/RandomDepthFirst.java
index eab53a9..2c1b3d2 100644
--- a/src/main/java/ch/fritteli/maze/generator/algorithm/RandomDepthFirst.java
+++ b/src/main/java/ch/fritteli/maze/generator/algorithm/RandomDepthFirst.java
@@ -6,17 +6,23 @@ import ch.fritteli.maze.generator.model.Position;
import ch.fritteli.maze.generator.model.Tile;
import io.vavr.control.Option;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.util.Deque;
import java.util.LinkedList;
+import java.util.Random;
-public class RandomDepthFirst extends AbstractMazeGeneratorAlgorithm {
+public class RandomDepthFirst {
+
+ @NotNull
+ private final Maze maze;
+ @NotNull
+ private final Random random;
@NotNull
private final Deque positions = new LinkedList<>();
public RandomDepthFirst(@NotNull final Maze maze) {
- super(maze, "Random Depth First");
+ this.maze = maze;
+ this.random = new Random(maze.getRandomSeed());
}
public void run() {
@@ -27,11 +33,20 @@ public class RandomDepthFirst extends AbstractMazeGeneratorAlgorithm {
private void preDig() {
final Position end = this.maze.getEnd();
- final Direction direction = this.determineDirectionForDigging(end);
+ final Tile endTile = this.maze.getEndTile();
- if (direction != null) {
- final Tile endTile = this.maze.getEndTile();
- this.digFrom(endTile, direction);
+ if (end.y() == 0) {
+ endTile.enableDiggingToOrFrom(Direction.TOP);
+ endTile.digFrom(Direction.TOP);
+ } else if (end.x() == 0) {
+ endTile.enableDiggingToOrFrom(Direction.LEFT);
+ endTile.digFrom(Direction.LEFT);
+ } else if (end.y() == this.maze.getHeight() - 1) {
+ endTile.enableDiggingToOrFrom(Direction.BOTTOM);
+ endTile.digFrom(Direction.BOTTOM);
+ } else if (end.x() == this.maze.getWidth() - 1) {
+ endTile.enableDiggingToOrFrom(Direction.RIGHT);
+ endTile.digFrom(Direction.RIGHT);
}
this.positions.push(end);
@@ -70,38 +85,20 @@ public class RandomDepthFirst extends AbstractMazeGeneratorAlgorithm {
private void postDig() {
final Position start = this.maze.getStart();
+ final Tile startTile = this.maze.getStartTile();
- final Direction direction = this.determineDirectionForDigging(start);
- if (direction != null) {
- final Tile startTile = this.maze.getStartTile();
- this.digTo(startTile, direction);
+ if (start.y() == 0) {
+ startTile.enableDiggingToOrFrom(Direction.TOP);
+ startTile.digTo(Direction.TOP);
+ } else if (start.x() == 0) {
+ startTile.enableDiggingToOrFrom(Direction.LEFT);
+ startTile.digTo(Direction.LEFT);
+ } else if (start.y() == this.maze.getHeight() - 1) {
+ startTile.enableDiggingToOrFrom(Direction.BOTTOM);
+ startTile.digTo(Direction.BOTTOM);
+ } else if (start.x() == this.maze.getWidth() - 1) {
+ startTile.enableDiggingToOrFrom(Direction.RIGHT);
+ startTile.digTo(Direction.RIGHT);
}
}
-
- @Nullable
- private Direction determineDirectionForDigging(@NotNull final Position position) {
- if (position.y() == 0) {
- return Direction.TOP;
- }
- if (position.x() == 0) {
- return Direction.LEFT;
- }
- if (position.y() == this.maze.getHeight() - 1) {
- return Direction.BOTTOM;
- }
- if (position.x() == this.maze.getWidth() - 1) {
- return Direction.RIGHT;
- }
- return null;
- }
-
- private void digFrom(@NotNull final Tile tile, @NotNull final Direction direction) {
- tile.enableDiggingToOrFrom(direction);
- tile.digFrom(direction);
- }
-
- private void digTo(@NotNull final Tile tile, @NotNull final Direction direction) {
- tile.enableDiggingToOrFrom(direction);
- tile.digTo(direction);
- }
}
diff --git a/src/main/java/ch/fritteli/maze/generator/algorithm/wilson/MazeSolver.java b/src/main/java/ch/fritteli/maze/generator/algorithm/wilson/MazeSolver.java
deleted file mode 100644
index f84a20c..0000000
--- a/src/main/java/ch/fritteli/maze/generator/algorithm/wilson/MazeSolver.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package ch.fritteli.maze.generator.algorithm.wilson;
-
-import ch.fritteli.maze.generator.model.Direction;
-import ch.fritteli.maze.generator.model.Maze;
-import ch.fritteli.maze.generator.model.Position;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.EnumSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Stack;
-import java.util.stream.Collectors;
-
-public class MazeSolver {
- @NotNull
- private final Maze maze;
-
- MazeSolver(@NotNull final Maze maze) {
- this.maze = maze;
- }
-
- void solve() {
- final Direction directionToOuterWall = Wilson.getDirectionToOuterWall(
- this.maze.getStart(),
- this.maze.getWidth(),
- this.maze.getHeight()
- );
-
- final List solution = this.getSolution(this.maze.getStart(), directionToOuterWall);
- for (Position position : solution) {
- this.maze.getTileAt(position).get().setSolution();
- }
- }
-
- private List getSolution(@NotNull Position position,
- @NotNull Direction forbidden) {
- record PathElement(@NotNull Position position,
- @NotNull EnumSet possibleDirections) {
- }
- final Stack solution = new Stack<>();
- final EnumSet directions = this.maze.getTileAt(position).get().getOpenDirections();
- directions.remove(forbidden);
- PathElement head = new PathElement(position, directions);
- solution.push(head);
- while (!head.position.equals(this.maze.getEnd())) {
- if (head.possibleDirections.isEmpty()) {
- solution.pop();
- head = solution.peek();
- } else {
- final Iterator iterator = head.possibleDirections.iterator();
- final Direction direction = iterator.next();
- iterator.remove();
- final Position next = head.position.move(direction);
- final EnumSet openDirections = this.maze.getTileAt(next).get().getOpenDirections();
- openDirections.remove(direction.invert());
- head = new PathElement(next, openDirections);
- solution.push(head);
- }
- }
- return solution.stream().map(PathElement::position).collect(Collectors.toList());
- }
-}
diff --git a/src/main/java/ch/fritteli/maze/generator/algorithm/wilson/Path.java b/src/main/java/ch/fritteli/maze/generator/algorithm/wilson/Path.java
deleted file mode 100644
index ab18ec2..0000000
--- a/src/main/java/ch/fritteli/maze/generator/algorithm/wilson/Path.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package ch.fritteli.maze.generator.algorithm.wilson;
-
-import ch.fritteli.maze.generator.model.Direction;
-import ch.fritteli.maze.generator.model.Position;
-import io.vavr.collection.List;
-import io.vavr.collection.Stream;
-import io.vavr.collection.Traversable;
-import io.vavr.control.Option;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Random;
-
-class Path {
- private final int width;
- private final int height;
- @NotNull
- private List positions;
-
- Path(@NotNull final Position start, int width, int height) {
- this.positions = List.of(start);
- this.width = width;
- this.height = height;
- }
-
- @NotNull
- Position growRandom(@NotNull final Random random) {
- final Position position = this.nextRandomPosition(random);
- if (this.contains(position)) {
- this.removeLoopUpTo(position);
- return this.growRandom(random);
- }
- this.positions = this.positions.prepend(position);
- return position;
- }
-
- @NotNull
- List getPositions() {
- return this.positions;
- }
-
- @NotNull
- Position getStart() {
- return this.positions.last();
- }
-
- @NotNull
- Traversable getMovesFromStart() {
- return this.positions.reverse().sliding(2)
- .flatMap(positions1 -> Option.when(
- positions1.size() == 2,
- // DEV-NOTE: .get() is safe here, because in the context of a path, there MUST be a direction
- // from one position to the next.
- () -> positions1.head().getDirectionTo(positions1.last()).get()
- ));
- }
-
- @NotNull
- private Position nextRandomPosition(@NotNull final Random random) {
- final Direction randomDirection = this.getRandomDirection(random);
- final Position nextPosition = this.positions.head().move(randomDirection);
- if (this.isWithinBounds(nextPosition) && !nextPosition.equals(this.positions.head())) {
- return nextPosition;
- }
- return this.nextRandomPosition(random);
- }
-
- private boolean isWithinBounds(@NotNull final Position position) {
- return position.x() >= 0 && position.x() < this.width && position.y() >= 0 && position.y() < this.height;
- }
-
- private boolean contains(@NotNull final Position position) {
- return this.positions.contains(position);
- }
-
- private void removeLoopUpTo(@NotNull final Position position) {
- this.positions = this.positions.dropUntil(position::equals);
- }
-
- @NotNull
- private Direction getRandomDirection(@NotNull final Random random) {
- final Direction[] array = Direction.values();
- return array[random.nextInt(array.length)];
- }
-
- @Override
- public String toString() {
- return Stream.ofAll(this.positions)
- .map(position -> "(%s,%s)".formatted(position.x(), position.y()))
- .mkString("Path[", "->", "]");
- }
-}
diff --git a/src/main/java/ch/fritteli/maze/generator/algorithm/wilson/PathsBuilder.java b/src/main/java/ch/fritteli/maze/generator/algorithm/wilson/PathsBuilder.java
deleted file mode 100644
index 098ed81..0000000
--- a/src/main/java/ch/fritteli/maze/generator/algorithm/wilson/PathsBuilder.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package ch.fritteli.maze.generator.algorithm.wilson;
-
-import ch.fritteli.maze.generator.model.Maze;
-import ch.fritteli.maze.generator.model.Position;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import io.vavr.Tuple;
-import io.vavr.collection.Stream;
-import io.vavr.collection.Traversable;
-import io.vavr.control.Option;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Random;
-
-/**
- * This class will build paths such that in the end all fields of the maze are covered by exactly one path.
- */
-class PathsBuilder {
- private final int width;
- private final int height;
- @NotNull
- private final Random random;
- @NotNull
- private final Multimap availablePositions;
-
- PathsBuilder(@NotNull final Maze maze,
- @NotNull final Random random) {
- this.width = maze.getWidth();
- this.height = maze.getHeight();
- this.random = random;
- this.availablePositions = HashMultimap.create(this.width, this.height);
-
- // Initialize the available positions.
- for (int x = 0; x < this.width; x++) {
- for (int y = 0; y < this.height; y++) {
- this.availablePositions.put(x, y);
- }
- }
- }
-
- /**
- * Create all the paths such that the maze will be completely filled and every field of it will be covered by
- * exactly one path.
- *
- * @return A {@link Traversable} of generated {@link Path Paths}.
- */
- @NotNull
- Traversable buildPaths() {
- this.initializeWithRandomStartingPosition();
-
- return Stream.unfoldLeft(
- this,
- builder -> builder.buildPath()
- .map(path -> {
- builder.setPartOfMaze(path);
- return Tuple.of(builder, path);
- })
- );
- }
-
- private void initializeWithRandomStartingPosition() {
- this.popRandomPosition();
- }
-
- /**
- * Creates one new path, if possible. If the maze is already filled, {@link io.vavr.control.Option.None} is
- * returned.
- *
- * @return An {@link Option} of a new {@link Path} instance.
- */
- @NotNull
- private Option buildPath() {
- return this.initializeNewPath()
- .map(this::growPath);
- }
-
- @NotNull
- private Option initializeNewPath() {
- return this.popRandomPosition()
- .map(position -> new Path(position, this.width, this.height));
- }
-
- /**
- * Randomly grow the {@code path} until it reaches a field that is part of the maze and return it. The resulting
- * path will contain no loops.
- *
- * @param path The {@link Path} to grow.
- * @return The final {@link Path} that reaches the maze.
- */
- @NotNull
- private Path growPath(@NotNull final Path path) {
- Position lastPosition;
- do {
- lastPosition = path.growRandom(this.random);
- } while (this.isNotPartOfMaze(lastPosition));
- return path;
- }
-
- private boolean isNotPartOfMaze(@NotNull final Position position) {
- return this.availablePositions.containsEntry(position.x(), position.y());
- }
-
- private void setPartOfMaze(@NotNull final Position position) {
- this.availablePositions.remove(position.x(), position.y());
- }
-
- private void setPartOfMaze(@NotNull final Path path) {
- path.getPositions().forEach(this::setPartOfMaze);
- }
-
- /**
- * Finds a random {@link Position}, that is not yet part of the maze, marks it as being part of the maze and returns
- * it. If no position is available, {@link io.vavr.control.Option.None} is returned.
- *
- * @return An available position or {@link io.vavr.control.Option.None}.
- */
- @NotNull
- private Option popRandomPosition() {
- if (this.availablePositions.isEmpty()) {
- return Option.none();
- }
-
- final Integer[] keys = this.availablePositions.keySet().toArray(Integer[]::new);
- final int key = keys[this.random.nextInt(keys.length)];
- final Integer[] values = this.availablePositions.get(key).toArray(Integer[]::new);
- final int value = values[this.random.nextInt(values.length)];
-
- this.availablePositions.remove(key, value);
- return Option.some(new Position(key, value));
- }
-}
diff --git a/src/main/java/ch/fritteli/maze/generator/algorithm/wilson/Wilson.java b/src/main/java/ch/fritteli/maze/generator/algorithm/wilson/Wilson.java
deleted file mode 100644
index 1587e6e..0000000
--- a/src/main/java/ch/fritteli/maze/generator/algorithm/wilson/Wilson.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package ch.fritteli.maze.generator.algorithm.wilson;
-
-import ch.fritteli.maze.generator.algorithm.AbstractMazeGeneratorAlgorithm;
-import ch.fritteli.maze.generator.model.Direction;
-import ch.fritteli.maze.generator.model.Maze;
-import ch.fritteli.maze.generator.model.Position;
-import ch.fritteli.maze.generator.model.Tile;
-import io.vavr.collection.Traversable;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * An implementation of Wilson's Algorithm.
- * In short:
- *
- * - Pick random location, add to maze
- * - While locations that are not part of the maze exist, loop:
- *
- * - Pick random location that's not part of the maze
- * - Randomly walk from this location, until ...
- *
- * - ... either you hit the current path, forming a loop. Then remove the entire loop and continue
- * walking.
- * - ... or you hit a position that is part of the maze. Then add the path to the maze and start the next
- * walk.
- *
- *
- *
- */
-public class Wilson extends AbstractMazeGeneratorAlgorithm {
-
- public Wilson(@NotNull final Maze maze) {
- super(maze, "Wilson");
- }
-
- @Nullable
- static Direction getDirectionToOuterWall(@NotNull final Position position,
- final int width,
- final int height) {
- if (position.y() == 0) {
- return Direction.TOP;
- }
- if (position.y() == height - 1) {
- return Direction.BOTTOM;
- }
- if (position.x() == 0) {
- return Direction.LEFT;
- }
- if (position.x() == width - 1) {
- return Direction.RIGHT;
- }
- return null;
- }
-
- @Override
- public void run() {
- final Traversable paths = new PathsBuilder(this.maze, this.random)
- .buildPaths();
-
- this.applyPathsToMaze(paths);
- }
-
- private void applyPathsToMaze(@NotNull final Traversable paths) {
- this.openStartAndEndWalls();
- paths.forEach(path -> path.getMovesFromStart()
- .foldLeft(
- path.getStart(),
- (position, direction) -> {
- this.maze.getTileAt(position).get()
- .digTo(direction);
- final Position next = position.move(direction);
- this.maze.getTileAt(next).get()
- .digTo(direction.invert());
- return next;
- }));
-
- final MazeSolver solver = new MazeSolver(this.maze);
- solver.solve();
- }
-
- private void openStartAndEndWalls() {
- this.openWall(this.maze.getStart(), this.maze.getStartTile());
- this.openWall(this.maze.getEnd(), this.maze.getEndTile());
- }
-
- private void openWall(@NotNull final Position position, @NotNull final Tile tile) {
- final Direction direction = this.getDirectionToOuterWall(position);
- tile.enableDiggingToOrFrom(direction);
- tile.digTo(direction);
- }
-
- @Nullable
- private Direction getDirectionToOuterWall(@NotNull final Position position) {
- return getDirectionToOuterWall(position, this.maze.getWidth(), this.maze.getHeight());
- }
-}
diff --git a/src/main/java/ch/fritteli/maze/generator/model/Direction.java b/src/main/java/ch/fritteli/maze/generator/model/Direction.java
index 75ee1c4..e50ba6c 100644
--- a/src/main/java/ch/fritteli/maze/generator/model/Direction.java
+++ b/src/main/java/ch/fritteli/maze/generator/model/Direction.java
@@ -1,14 +1,11 @@
package ch.fritteli.maze.generator.model;
-import org.jetbrains.annotations.NotNull;
-
public enum Direction {
TOP,
RIGHT,
BOTTOM,
LEFT;
- @NotNull
public Direction invert() {
return switch (this) {
case TOP -> BOTTOM;
diff --git a/src/main/java/ch/fritteli/maze/generator/model/Maze.java b/src/main/java/ch/fritteli/maze/generator/model/Maze.java
index 633e1b3..14d7af6 100644
--- a/src/main/java/ch/fritteli/maze/generator/model/Maze.java
+++ b/src/main/java/ch/fritteli/maze/generator/model/Maze.java
@@ -3,7 +3,6 @@ package ch.fritteli.maze.generator.model;
import io.vavr.control.Option;
import lombok.EqualsAndHashCode;
import lombok.Getter;
-import lombok.Setter;
import lombok.ToString;
import org.jetbrains.annotations.NotNull;
@@ -22,9 +21,6 @@ public class Maze {
private final Position start;
@Getter
private final Position end;
- @Getter
- @Setter
- private String algorithm;
public Maze(final int width, final int height) {
this(width, height, System.nanoTime());
@@ -38,11 +34,7 @@ public class Maze {
this(width, height, randomSeed, new Position(0, 0), new Position(width - 1, height - 1));
}
- public Maze(final int width,
- final int height,
- final long randomSeed,
- @NotNull final Position start,
- @NotNull final Position end) {
+ public Maze(final int width, final int height, final long randomSeed, @NotNull final Position start, @NotNull final Position end) {
if (width <= 1 || height <= 1) {
throw new IllegalArgumentException("width and height must be >1");
}
@@ -79,12 +71,7 @@ public class Maze {
/**
* INTERNAL API. Exists only for deserialization. Not to be called from user code.
*/
- private Maze(@NotNull final Tile[][] field,
- final int width,
- final int height,
- @NotNull final Position start,
- @NotNull final Position end,
- final long randomSeed) {
+ private Maze(@NotNull final Tile[][] field, final int width, final int height, @NotNull final Position start, @NotNull final Position end, final long randomSeed) {
this.field = field;
this.width = width;
this.height = height;
@@ -93,25 +80,6 @@ public class Maze {
this.end = end;
}
- /**
- * INTERNAL API. Exists only for deserialization. Not to be called from user code.
- */
- private Maze(@NotNull final Tile[][] field,
- final int width,
- final int height,
- @NotNull final Position start,
- @NotNull final Position end,
- final long randomSeed,
- @NotNull final String algorithm) {
- this.field = field;
- this.width = width;
- this.height = height;
- this.randomSeed = randomSeed;
- this.algorithm = algorithm;
- this.start = start;
- this.end = end;
- }
-
@NotNull
public Option getTileAt(@NotNull final Position position) {
return this.getTileAt(position.x(), position.y());
diff --git a/src/main/java/ch/fritteli/maze/generator/model/Position.java b/src/main/java/ch/fritteli/maze/generator/model/Position.java
index a6fa788..4b91543 100644
--- a/src/main/java/ch/fritteli/maze/generator/model/Position.java
+++ b/src/main/java/ch/fritteli/maze/generator/model/Position.java
@@ -1,12 +1,10 @@
package ch.fritteli.maze.generator.model;
-import io.vavr.control.Option;
import lombok.With;
import org.jetbrains.annotations.NotNull;
@With
public record Position(int x, int y) {
- @NotNull
public Position move(@NotNull final Direction direction) {
return switch (direction) {
case BOTTOM -> this.withY(this.y + 1);
@@ -15,20 +13,4 @@ public record Position(int x, int y) {
case TOP -> this.withY(this.y - 1);
};
}
-
- @NotNull
- public Option getDirectionTo(@NotNull final Position position) {
- final int xDiff = position.x - this.x;
- final int yDiff = position.y - this.y;
- return switch (xDiff) {
- case -1 -> Option.when(yDiff == 0, Direction.LEFT);
- case 0 -> switch (yDiff) {
- case -1 -> Option.some(Direction.TOP);
- case 1 -> Option.some(Direction.BOTTOM);
- default -> Option.none();
- };
- case 1 -> Option.when(yDiff == 0, Direction.RIGHT);
- default -> Option.none();
- };
- }
}
diff --git a/src/main/java/ch/fritteli/maze/generator/model/Tile.java b/src/main/java/ch/fritteli/maze/generator/model/Tile.java
index b4428f1..c6f9367 100644
--- a/src/main/java/ch/fritteli/maze/generator/model/Tile.java
+++ b/src/main/java/ch/fritteli/maze/generator/model/Tile.java
@@ -1,6 +1,6 @@
package ch.fritteli.maze.generator.model;
-import io.vavr.collection.Vector;
+import io.vavr.collection.Stream;
import io.vavr.control.Option;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
@@ -17,7 +17,6 @@ import java.util.Random;
@ToString
public class Tile {
final Walls walls = new Walls();
- @EqualsAndHashCode.Exclude
boolean visited = false;
@Getter
boolean solution = false;
@@ -36,18 +35,18 @@ public class Tile {
private Tile(@NotNull final EnumSet walls, final boolean solution) {
for (final Direction direction : walls) {
this.walls.set(direction);
- this.walls.seal(direction);
+ this.walls.harden(direction);
}
this.visited = true;
this.solution = solution;
}
public void preventDiggingToOrFrom(@NotNull final Direction direction) {
- this.walls.seal(direction);
+ this.walls.harden(direction);
}
public void enableDiggingToOrFrom(@NotNull final Direction direction) {
- this.walls.unseal(direction);
+ this.walls.unharden(direction);
}
public boolean digFrom(@NotNull final Direction direction) {
@@ -66,23 +65,13 @@ public class Tile {
this.walls.set(direction);
}
- @NotNull
- public EnumSet getOpenDirections() {
- return this.walls.getOpen();
- }
-
- @NotNull
public Option getRandomAvailableDirection(@NotNull final Random random) {
- final EnumSet availableDirections = this.walls.getUnsealedSet();
+ final Stream availableDirections = this.walls.getUnhardenedSet();
if (availableDirections.isEmpty()) {
return Option.none();
}
- if (availableDirections.size() == 1) {
- return Option.some(availableDirections.iterator().next());
- }
- final Vector directions = Vector.ofAll(availableDirections);
- final int index = random.nextInt(directions.size());
- return Option.of(directions.get(index));
+ final int index = random.nextInt(availableDirections.length());
+ return Option.of(availableDirections.get(index));
}
public boolean hasWallAt(@NotNull final Direction direction) {
diff --git a/src/main/java/ch/fritteli/maze/generator/model/Walls.java b/src/main/java/ch/fritteli/maze/generator/model/Walls.java
index 4a899c7..f77ceaa 100644
--- a/src/main/java/ch/fritteli/maze/generator/model/Walls.java
+++ b/src/main/java/ch/fritteli/maze/generator/model/Walls.java
@@ -1,17 +1,21 @@
package ch.fritteli.maze.generator.model;
+import io.vavr.collection.Stream;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.jetbrains.annotations.NotNull;
import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
@EqualsAndHashCode
@ToString
public class Walls {
- private final EnumSet directions = EnumSet.noneOf(Direction.class);
- @EqualsAndHashCode.Exclude
- private final EnumSet sealed = EnumSet.noneOf(Direction.class);
+ private final SortedSet directions = new TreeSet<>();
+ private final Set hardened = new HashSet<>();
public void set(@NotNull final Direction direction) {
this.directions.add(direction);
@@ -22,7 +26,7 @@ public class Walls {
}
public boolean clear(@NotNull final Direction direction) {
- if (this.sealed.contains(direction)) {
+ if (this.hardened.contains(direction)) {
return false;
}
return this.directions.remove(direction);
@@ -32,26 +36,19 @@ public class Walls {
return this.directions.contains(direction);
}
- @NotNull
- public EnumSet getUnsealedSet() {
- final EnumSet result = EnumSet.copyOf(this.directions);
- result.removeAll(this.sealed);
- return result;
+ public Stream getUnhardenedSet() {
+ return Stream.ofAll(this.directions)
+ .removeAll(this.hardened);
}
- public void seal(@NotNull final Direction direction) {
+ public void harden(@NotNull final Direction direction) {
if (!this.directions.contains(direction)) {
- throw new IllegalStateException("Trying to seal cleared Direction: " + direction);
+ throw new IllegalStateException("Trying to harden cleared Direction: " + direction);
}
- this.sealed.add(direction);
+ this.hardened.add(direction);
}
- public void unseal(@NotNull final Direction direction) {
- this.sealed.remove(direction);
- }
-
- @NotNull
- public EnumSet getOpen() {
- return EnumSet.complementOf(this.directions);
+ public void unharden(@NotNull final Direction direction) {
+ this.hardened.remove(direction);
}
}
diff --git a/src/main/java/ch/fritteli/maze/generator/renderer/html/HTMLRenderer.java b/src/main/java/ch/fritteli/maze/generator/renderer/html/HTMLRenderer.java
index a2de552..1242ac3 100644
--- a/src/main/java/ch/fritteli/maze/generator/renderer/html/HTMLRenderer.java
+++ b/src/main/java/ch/fritteli/maze/generator/renderer/html/HTMLRenderer.java
@@ -6,109 +6,108 @@ import org.jetbrains.annotations.NotNull;
public class HTMLRenderer implements Renderer {
- private static final String POSTAMBLE = """
-