Enable showing/rendering the solution.
This commit is contained in:
		
							parent
							
								
									0a655bd617
								
							
						
					
					
						commit
						c6b8b0e3bd
					
				
					 4 changed files with 83 additions and 23 deletions
				
			
		|  | @ -1,9 +1,36 @@ | ||||||
| package ch.fritteli.labyrinth; | package ch.fritteli.labyrinth; | ||||||
| 
 | 
 | ||||||
|  | import io.vavr.collection.HashSet; | ||||||
|  | import io.vavr.collection.Set; | ||||||
| import lombok.NonNull; | import lombok.NonNull; | ||||||
| 
 | 
 | ||||||
| public class HTMLRenderer { | 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 static final String POSTAMBLE = "</body></html>"; | ||||||
|     private final Labyrinth labyrinth; |     private final Labyrinth labyrinth; | ||||||
|     private final int width; |     private final int width; | ||||||
|  | @ -44,22 +71,31 @@ public class HTMLRenderer { | ||||||
|         for (int x = 0; x < this.width; x++) { |         for (int x = 0; x < this.width; x++) { | ||||||
|             final Tile currentTile = this.labyrinth.getTileAt(x, this.y); |             final Tile currentTile = this.labyrinth.getTileAt(x, this.y); | ||||||
|             sb.append("<td class=\""); |             sb.append("<td class=\""); | ||||||
|             if (currentTile.hasWallAt(Direction.TOP)) { |             sb.append(this.getClasses(currentTile).mkString(" ")); | ||||||
|                 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("\"> </td>"); |             sb.append("\"> </td>"); | ||||||
|         } |         } | ||||||
|         sb.append("</tr>"); |         sb.append("</tr>"); | ||||||
|         this.y++; |         this.y++; | ||||||
|         return sb.toString(); |         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; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -13,11 +13,15 @@ public class Labyrinth { | ||||||
|     private final int width; |     private final int width; | ||||||
|     @Getter |     @Getter | ||||||
|     private final int height; |     private final int height; | ||||||
|  |     private final Position start; | ||||||
|  |     private final Position end; | ||||||
| 
 | 
 | ||||||
|     public Labyrinth(final int width, final int height) { |     public Labyrinth(final int width, final int height) { | ||||||
|         this.width = width; |         this.width = width; | ||||||
|         this.height = height; |         this.height = height; | ||||||
|         this.field = new Tile[width][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.initField(); | ||||||
|         this.generate(); |         this.generate(); | ||||||
|     } |     } | ||||||
|  | @ -30,6 +34,14 @@ public class Labyrinth { | ||||||
|         return this.field[x][y]; |         return this.field[x][y]; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     Tile getStartTile() { | ||||||
|  |         return this.getTileAt(this.start); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Tile getEndTile() { | ||||||
|  |         return this.getTileAt(this.end); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private void initField() { |     private void initField() { | ||||||
|         for (int x = 0; x < this.width; x++) { |         for (int x = 0; x < this.width; x++) { | ||||||
|             this.field[x] = new Tile[this.height]; |             this.field[x] = new Tile[this.height]; | ||||||
|  | @ -70,11 +82,10 @@ public class Labyrinth { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private void preDig() { |         private void preDig() { | ||||||
|             final Position bottomRight = new Position(Labyrinth.this.width - 1, Labyrinth.this.height - 1); |             final Tile endTile = Labyrinth.this.getEndTile(); | ||||||
|             final Tile bottomRightTile = Labyrinth.this.getTileAt(bottomRight); |             endTile.enableDiggingToOrFrom(Direction.BOTTOM); | ||||||
|             bottomRightTile.enableDiggingToOrFrom(Direction.BOTTOM); |             endTile.digFrom(Direction.BOTTOM); | ||||||
|             bottomRightTile.digFrom(Direction.BOTTOM); |             this.positions.push(Labyrinth.this.end); | ||||||
|             this.positions.push(bottomRight); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private void dig() { |         private void dig() { | ||||||
|  | @ -90,6 +101,9 @@ public class Labyrinth { | ||||||
|                     if (currentTile.digTo(digTo) && neighborTile.digFrom(digFrom)) { |                     if (currentTile.digTo(digTo) && neighborTile.digFrom(digFrom)) { | ||||||
|                         // all ok! |                         // all ok! | ||||||
|                         this.positions.push(neighborPosition); |                         this.positions.push(neighborPosition); | ||||||
|  |                         if (neighborPosition.equals(Labyrinth.this.start)) { | ||||||
|  |                             this.markSolution(); | ||||||
|  |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         // Hm, didn't work. |                         // Hm, didn't work. | ||||||
|                         currentTile.undigTo(digTo); |                         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() { |         private void postDig() { | ||||||
|             final Position topLeft = new Position(0, 0); |             final Tile startTile = Labyrinth.this.getStartTile(); | ||||||
|             final Tile topLeftTile = Labyrinth.this.getTileAt(topLeft); |             startTile.enableDiggingToOrFrom(Direction.TOP); | ||||||
|             topLeftTile.enableDiggingToOrFrom(Direction.TOP); |             startTile.digTo(Direction.TOP); | ||||||
|             topLeftTile.digTo(Direction.TOP); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -141,7 +141,7 @@ public class TextRenderer { | ||||||
|             charDef2.vertical(); |             charDef2.vertical(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         result = charDef1 + " "; |         result = charDef1 + (currentTile.isSolution() ? "x" : " "); | ||||||
| 
 | 
 | ||||||
|         if (this.x == this.width - 1) { |         if (this.x == this.width - 1) { | ||||||
|             result += charDef2 + "\n"; |             result += charDef2 + "\n"; | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ package ch.fritteli.labyrinth; | ||||||
| import io.vavr.collection.Stream; | import io.vavr.collection.Stream; | ||||||
| import io.vavr.control.Option; | import io.vavr.control.Option; | ||||||
| import lombok.AccessLevel; | import lombok.AccessLevel; | ||||||
|  | import lombok.Getter; | ||||||
| import lombok.NonNull; | import lombok.NonNull; | ||||||
| import lombok.experimental.FieldDefaults; | import lombok.experimental.FieldDefaults; | ||||||
| 
 | 
 | ||||||
|  | @ -10,6 +11,8 @@ import lombok.experimental.FieldDefaults; | ||||||
| public class Tile { | public class Tile { | ||||||
|     final Walls walls = new Walls(); |     final Walls walls = new Walls(); | ||||||
|     boolean visited = false; |     boolean visited = false; | ||||||
|  |     @Getter | ||||||
|  |     boolean solution = false; | ||||||
| 
 | 
 | ||||||
|     public Tile() { |     public Tile() { | ||||||
|         this.walls.setAll(); |         this.walls.setAll(); | ||||||
|  | @ -46,4 +49,8 @@ public class Tile { | ||||||
|     public boolean hasWallAt(@NonNull final Direction direction) { |     public boolean hasWallAt(@NonNull final Direction direction) { | ||||||
|         return this.walls.isSet(direction); |         return this.walls.isSet(direction); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     public void setSolution() { | ||||||
|  |         this.solution = true; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue