diff --git a/src/main/java/ch/fritteli/labyrinth/TextRenderer.java b/src/main/java/ch/fritteli/labyrinth/TextRenderer.java index 4cf07b9..1cfb405 100644 --- a/src/main/java/ch/fritteli/labyrinth/TextRenderer.java +++ b/src/main/java/ch/fritteli/labyrinth/TextRenderer.java @@ -54,15 +54,17 @@ public class TextRenderer implements Renderer { private String next() { final Tile currentTile = this.labyrinth.getTileAt(this.x, this.y); - final Tile leftTile = this.getTileOrNull(this.x - 1, this.y); final Tile topTile = this.getTileOrNull(this.x, this.y - 1); + final Tile rightTile = this.getTileOrNull(this.x + 1, this.y); + final Tile bottomTile = this.getTileOrNull(this.x, this.y + 1); + final Tile leftTile = this.getTileOrNull(this.x - 1, this.y); final String s; switch (this.line) { case 0: s = this.renderTopLine(currentTile, leftTile, topTile); break; case 1: - s = this.renderCenterLine(currentTile); + s = this.renderCenterLine(currentTile, topTile, rightTile, bottomTile, leftTile); break; case 2: s = this.renderBottomLine(currentTile, leftTile); @@ -117,20 +119,22 @@ public class TextRenderer implements Renderer { charDef1.right(); charDef2.horizontal(); charDef3.left(); + } else { + if (this.isSolution(currentTile) && (this.isSolution(topTile) || topTile == null)) { + charDef2.solution().vertical(); + } } if (currentTile.hasWallAt(Direction.RIGHT)) { charDef3.down(); } - if (leftTile != null && leftTile.hasWallAt(Direction.TOP)) { + if (this.hasWallAt(leftTile, Direction.TOP)) { charDef1.left(); } - if (topTile != null) { - if (topTile.hasWallAt(Direction.LEFT)) { - charDef1.up(); - } - if (topTile.hasWallAt(Direction.RIGHT)) { - charDef3.up(); - } + if (this.hasWallAt(topTile, Direction.LEFT)) { + charDef1.up(); + } + if (this.hasWallAt(topTile, Direction.RIGHT)) { + charDef3.up(); } result = charDef1.toString() + charDef2; if (this.x == this.labyrinth.getWidth() - 1) { @@ -139,21 +143,49 @@ public class TextRenderer implements Renderer { return result; } - private String renderCenterLine(@NonNull final Tile currentTile) { + private String renderCenterLine(@NonNull final Tile currentTile, + @Nullable final Tile topTile, + @Nullable final Tile rightTile, + @Nullable final Tile bottomTile, + @Nullable final Tile leftTile) { final CharDefinition charDef1 = new CharDefinition(); final CharDefinition charDef2 = new CharDefinition(); + final CharDefinition charDef3 = new CharDefinition(); String result; if (currentTile.hasWallAt(Direction.LEFT)) { charDef1.vertical(); + } else { + if (this.isSolution(currentTile) && this.isSolution(leftTile)) { + charDef1.solution().horizontal(); + } + } + if (this.isSolution(currentTile)) { + charDef2.solution(); + if (!currentTile.hasWallAt(Direction.LEFT) && (this.isSolution(leftTile) || leftTile == null)) { + charDef2.left(); + } + if (!currentTile.hasWallAt(Direction.TOP) && (this.isSolution(topTile) || topTile == null)) { + charDef2.up(); + } + if (!currentTile.hasWallAt(Direction.RIGHT) && (this.isSolution(rightTile) || rightTile == null)) { + charDef2.right(); + } + if (!currentTile.hasWallAt(Direction.BOTTOM) && (this.isSolution(bottomTile) || bottomTile == null)) { + charDef2.down(); + } } if (currentTile.hasWallAt(Direction.RIGHT)) { - charDef2.vertical(); + charDef3.vertical(); + } else { + if (this.isSolution(currentTile) && this.isSolution(rightTile)) { + charDef3.solution().horizontal(); + } } - result = charDef1 + (currentTile.isSolution() && this.renderSolution ? "x" : " "); + result = charDef1.toString() + charDef2; if (this.x == this.labyrinth.getWidth() - 1) { - result += charDef2 + "\n"; + result += charDef3 + "\n"; } return result; @@ -172,11 +204,15 @@ public class TextRenderer implements Renderer { charDef1.right(); charDef2.horizontal(); charDef3.left(); + } else { + if (this.isSolution(currentTile)) { + charDef2.solution().vertical(); + } } if (currentTile.hasWallAt(Direction.RIGHT)) { charDef3.up(); } - if (leftTile != null && leftTile.hasWallAt(Direction.BOTTOM)) { + if (this.hasWallAt(leftTile, Direction.BOTTOM)) { charDef1.left(); } @@ -188,6 +224,14 @@ public class TextRenderer implements Renderer { return result; } + private boolean hasWallAt(@Nullable final Tile tile, @NonNull final Direction direction) { + return tile != null && tile.hasWallAt(direction); + } + + private boolean isSolution(@Nullable final Tile tile) { + return this.renderSolution && tile != null && tile.isSolution(); + } + @FieldDefaults(level = AccessLevel.PRIVATE) @NoArgsConstructor @AllArgsConstructor @@ -222,10 +266,24 @@ public class TextRenderer implements Renderer { static final String HORIZONTAL_UP = "\u2534"; // ┼ static final String CROSS = "\u253c"; + // ╭ + static final String SOLUTION_DOWN_RIGHT = "\u256d"; + // ╮ + static final String SOLUTION_DOWN_LEFT = "\u256e"; + // ╯ + static final String SOLUTION_UP_LEFT = "\u256f"; + // ╰ + static final String SOLUTION_UP_RIGHT = "\u2570"; boolean up = false; boolean down = false; boolean left = false; boolean right = false; + boolean solution = false; + + CharDefinition solution() { + this.solution = true; + return this; + } CharDefinition up() { this.up = true; @@ -276,11 +334,11 @@ public class TextRenderer implements Renderer { if (this.right) { return HORIZONTAL_UP; } else { - return UP_LEFT; + return this.solution ? SOLUTION_UP_LEFT : UP_LEFT; } } else { if (this.right) { - return UP_RIGHT; + return this.solution ? SOLUTION_UP_RIGHT : UP_RIGHT; } else { return UP; } @@ -292,11 +350,11 @@ public class TextRenderer implements Renderer { if (this.right) { return HORIZONTAL_DOWN; } else { - return DOWN_LEFT; + return this.solution ? SOLUTION_DOWN_LEFT : DOWN_LEFT; } } else { if (this.right) { - return DOWN_RIGHT; + return this.solution ? SOLUTION_DOWN_RIGHT : DOWN_RIGHT; } else { return DOWN; } diff --git a/src/test/java/ch/fritteli/labyrinth/TextRendererTest.java b/src/test/java/ch/fritteli/labyrinth/TextRendererTest.java index 2eabeea..58b36e4 100644 --- a/src/test/java/ch/fritteli/labyrinth/TextRendererTest.java +++ b/src/test/java/ch/fritteli/labyrinth/TextRendererTest.java @@ -10,23 +10,43 @@ class TextRendererTest { @Nested class CharDefinitionTest { @Test - void testRendering() { - assertEquals(" ", new CharDefinition(false, false, false, false).toString()); - assertEquals("╶", new CharDefinition(false, false, false, true).toString()); - assertEquals("╴", new CharDefinition(false, false, true, false).toString()); - assertEquals("─", new CharDefinition(false, false, true, true).toString()); - assertEquals("╷", new CharDefinition(false, true, false, false).toString()); - assertEquals("┌", new CharDefinition(false, true, false, true).toString()); - assertEquals("┐", new CharDefinition(false, true, true, false).toString()); - assertEquals("┬", new CharDefinition(false, true, true, true).toString()); - assertEquals("╵", new CharDefinition(true, false, false, false).toString()); - assertEquals("└", new CharDefinition(true, false, false, true).toString()); - assertEquals("┘", new CharDefinition(true, false, true, false).toString()); - assertEquals("┴", new CharDefinition(true, false, true, true).toString()); - assertEquals("│", new CharDefinition(true, true, false, false).toString()); - assertEquals("├", new CharDefinition(true, true, false, true).toString()); - assertEquals("┤", new CharDefinition(true, true, true, false).toString()); - assertEquals("┼", new CharDefinition(true, true, true, true).toString()); + void testRenderingWall() { + assertEquals(" ", new CharDefinition(false, false, false, false, false).toString()); + assertEquals("╶", new CharDefinition(false, false, false, true, false).toString()); + assertEquals("╴", new CharDefinition(false, false, true, false, false).toString()); + assertEquals("─", new CharDefinition(false, false, true, true, false).toString()); + assertEquals("╷", new CharDefinition(false, true, false, false, false).toString()); + assertEquals("┌", new CharDefinition(false, true, false, true, false).toString()); + assertEquals("┐", new CharDefinition(false, true, true, false, false).toString()); + assertEquals("┬", new CharDefinition(false, true, true, true, false).toString()); + assertEquals("╵", new CharDefinition(true, false, false, false, false).toString()); + assertEquals("└", new CharDefinition(true, false, false, true, false).toString()); + assertEquals("┘", new CharDefinition(true, false, true, false, false).toString()); + assertEquals("┴", new CharDefinition(true, false, true, true, false).toString()); + assertEquals("│", new CharDefinition(true, true, false, false, false).toString()); + assertEquals("├", new CharDefinition(true, true, false, true, false).toString()); + assertEquals("┤", new CharDefinition(true, true, true, false, false).toString()); + assertEquals("┼", new CharDefinition(true, true, true, true, false).toString()); + } + + @Test + void testRenderingSolution() { + assertEquals(" ", new CharDefinition(false, false, false, false, true).toString()); + assertEquals("╶", new CharDefinition(false, false, false, true, true).toString()); + assertEquals("╴", new CharDefinition(false, false, true, false, true).toString()); + assertEquals("─", new CharDefinition(false, false, true, true, true).toString()); + assertEquals("╷", new CharDefinition(false, true, false, false, true).toString()); + assertEquals("╭", new CharDefinition(false, true, false, true, true).toString()); + assertEquals("╮", new CharDefinition(false, true, true, false, true).toString()); + assertEquals("┬", new CharDefinition(false, true, true, true, true).toString()); + assertEquals("╵", new CharDefinition(true, false, false, false, true).toString()); + assertEquals("╰", new CharDefinition(true, false, false, true, true).toString()); + assertEquals("╯", new CharDefinition(true, false, true, false, true).toString()); + assertEquals("┴", new CharDefinition(true, false, true, true, true).toString()); + assertEquals("│", new CharDefinition(true, true, false, false, true).toString()); + assertEquals("├", new CharDefinition(true, true, false, true, true).toString()); + assertEquals("┤", new CharDefinition(true, true, true, false, true).toString()); + assertEquals("┼", new CharDefinition(true, true, true, true, true).toString()); } } }