Enable showing/rendering the solution.

This commit is contained in:
Manuel Friedli 2020-10-02 18:07:56 +02:00
parent 0a655bd617
commit c6b8b0e3bd
4 changed files with 83 additions and 23 deletions

View file

@ -1,9 +1,36 @@
package ch.fritteli.labyrinth;
import io.vavr.collection.HashSet;
import io.vavr.collection.Set;
import lombok.NonNull;
public class HTMLRenderer {
private static final String PREAMBLE = "<!DOCTYPE html><html><head><title>Labyrinth</title><style>table{border-collapse:collapse;}td{border:0 solid black;height:1em;width:1em;}td.top{border-top-width:1px;}td.right{border-right-width:1px;}td.bottom{border-bottom-width:1px;}td.left{border-left-width:1px;}</style></head><body>";
private static final String PREAMBLE = "<!DOCTYPE html><html lang=\"en\">" +
"<head>" +
"<title>Labyrinth</title>" +
"<style>" +
"table{border-collapse:collapse;}" +
"td{border:0 solid black;height:1em;width:1em;}" +
"td.top{border-top-width:1px;}" +
"td.right{border-right-width:1px;}" +
"td.bottom{border-bottom-width:1px;}" +
"td.left{border-left-width:1px;}" +
"</style>" +
"<script>" +
"let solution = false;" +
"function toggleSolution() {" +
"let stylesheet = document.styleSheets[0];" +
"if(solution){" +
"stylesheet.deleteRule(0);" +
"}else{" +
"stylesheet.insertRule(\"td.solution{background-color:lightgray;}\", 0);" +
"}" +
"solution = !solution;" +
"}" +
"</script>" +
"</head>" +
"<body>" +
"<input type=\"checkbox\" onclick=\"toggleSolution()\">show solution</input>";
private static final String POSTAMBLE = "</body></html>";
private final Labyrinth labyrinth;
private final int width;
@ -44,22 +71,31 @@ public class HTMLRenderer {
for (int x = 0; x < this.width; x++) {
final Tile currentTile = this.labyrinth.getTileAt(x, this.y);
sb.append("<td class=\"");
if (currentTile.hasWallAt(Direction.TOP)) {
sb.append("top ");
}
if (currentTile.hasWallAt(Direction.RIGHT)) {
sb.append("right ");
}
if (currentTile.hasWallAt(Direction.BOTTOM)) {
sb.append("bottom ");
}
if (currentTile.hasWallAt(Direction.LEFT)) {
sb.append("left ");
}
sb.append(this.getClasses(currentTile).mkString(" "));
sb.append("\">&nbsp;</td>");
}
sb.append("</tr>");
this.y++;
return sb.toString();
}
private Set<String> getClasses(@NonNull final Tile tile) {
Set<String> result = HashSet.empty();
if (tile.hasWallAt(Direction.TOP)) {
result = result.add("top");
}
if (tile.hasWallAt(Direction.RIGHT)) {
result = result.add("right");
}
if (tile.hasWallAt(Direction.BOTTOM)) {
result = result.add("bottom");
}
if (tile.hasWallAt(Direction.LEFT)) {
result = result.add("left");
}
if (tile.isSolution()) {
result = result.add("solution");
}
return result;
}
}

View file

@ -13,11 +13,15 @@ public class Labyrinth {
private final int width;
@Getter
private final int height;
private final Position start;
private final Position end;
public Labyrinth(final int width, final int height) {
this.width = width;
this.height = height;
this.field = new Tile[width][height];
this.start = new Position(0, 0);
this.end = new Position(this.width - 1, this.height - 1);
this.initField();
this.generate();
}
@ -30,6 +34,14 @@ public class Labyrinth {
return this.field[x][y];
}
Tile getStartTile() {
return this.getTileAt(this.start);
}
Tile getEndTile() {
return this.getTileAt(this.end);
}
private void initField() {
for (int x = 0; x < this.width; x++) {
this.field[x] = new Tile[this.height];
@ -70,11 +82,10 @@ public class Labyrinth {
}
private void preDig() {
final Position bottomRight = new Position(Labyrinth.this.width - 1, Labyrinth.this.height - 1);
final Tile bottomRightTile = Labyrinth.this.getTileAt(bottomRight);
bottomRightTile.enableDiggingToOrFrom(Direction.BOTTOM);
bottomRightTile.digFrom(Direction.BOTTOM);
this.positions.push(bottomRight);
final Tile endTile = Labyrinth.this.getEndTile();
endTile.enableDiggingToOrFrom(Direction.BOTTOM);
endTile.digFrom(Direction.BOTTOM);
this.positions.push(Labyrinth.this.end);
}
private void dig() {
@ -90,6 +101,9 @@ public class Labyrinth {
if (currentTile.digTo(digTo) && neighborTile.digFrom(digFrom)) {
// all ok!
this.positions.push(neighborPosition);
if (neighborPosition.equals(Labyrinth.this.start)) {
this.markSolution();
}
} else {
// Hm, didn't work.
currentTile.undigTo(digTo);
@ -101,11 +115,14 @@ public class Labyrinth {
}
}
private void markSolution() {
this.positions.forEach(position -> Labyrinth.this.getTileAt(position).setSolution());
}
private void postDig() {
final Position topLeft = new Position(0, 0);
final Tile topLeftTile = Labyrinth.this.getTileAt(topLeft);
topLeftTile.enableDiggingToOrFrom(Direction.TOP);
topLeftTile.digTo(Direction.TOP);
final Tile startTile = Labyrinth.this.getStartTile();
startTile.enableDiggingToOrFrom(Direction.TOP);
startTile.digTo(Direction.TOP);
}
}
}

View file

@ -141,7 +141,7 @@ public class TextRenderer {
charDef2.vertical();
}
result = charDef1 + " ";
result = charDef1 + (currentTile.isSolution() ? "x" : " ");
if (this.x == this.width - 1) {
result += charDef2 + "\n";

View file

@ -3,6 +3,7 @@ package ch.fritteli.labyrinth;
import io.vavr.collection.Stream;
import io.vavr.control.Option;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import lombok.experimental.FieldDefaults;
@ -10,6 +11,8 @@ import lombok.experimental.FieldDefaults;
public class Tile {
final Walls walls = new Walls();
boolean visited = false;
@Getter
boolean solution = false;
public Tile() {
this.walls.setAll();
@ -46,4 +49,8 @@ public class Tile {
public boolean hasWallAt(@NonNull final Direction direction) {
return this.walls.isSet(direction);
}
public void setSolution() {
this.solution = true;
}
}