Make the generation of a labyrinth reproducible and refactor the
PDFRenderer a bit.
This commit is contained in:
		
							parent
							
								
									fd38b141a1
								
							
						
					
					
						commit
						6060a08573
					
				
					 6 changed files with 114 additions and 74 deletions
				
			
		|  | @ -6,9 +6,36 @@ import lombok.NonNull; | ||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
| 
 | 
 | ||||||
| public class HTMLRenderer implements Renderer<String> { | public class HTMLRenderer implements Renderer<String> { | ||||||
|     private static final String PREAMBLE = "<!DOCTYPE html><html lang=\"en\">" + |     private static final String POSTAMBLE = "</body></html>"; | ||||||
|  | 
 | ||||||
|  |     private HTMLRenderer() { | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @NonNull | ||||||
|  |     public static HTMLRenderer newInstance() { | ||||||
|  |         return new HTMLRenderer(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @NonNull | ||||||
|  |     public String render(@NonNull final Labyrinth labyrinth) { | ||||||
|  |         if (labyrinth.getWidth() == 0 || labyrinth.getHeight() == 0) { | ||||||
|  |             return this.getPreamble(labyrinth) + POSTAMBLE; | ||||||
|  |         } | ||||||
|  |         final Generator generator = new Generator(labyrinth); | ||||||
|  |         final StringBuilder sb = new StringBuilder(this.getPreamble(labyrinth)); | ||||||
|  |         sb.append("<table>"); | ||||||
|  |         while (generator.hasNext()) { | ||||||
|  |             sb.append(generator.next()); | ||||||
|  |         } | ||||||
|  |         sb.append("</table>"); | ||||||
|  |         sb.append(POSTAMBLE); | ||||||
|  |         return sb.toString(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private String getPreamble(@NonNull final Labyrinth labyrinth) { | ||||||
|  |         return "<!DOCTYPE html><html lang=\"en\">" + | ||||||
|                 "<head>" + |                 "<head>" + | ||||||
|             "<title>Labyrinth</title>" + |                 "<title>Labyrinth " + labyrinth.getWidth() + "x" + labyrinth.getHeight() + ", ID " + labyrinth.getRandomSeed() + "</title>" + | ||||||
|                 "<meta charset=\"utf-8\">" + |                 "<meta charset=\"utf-8\">" + | ||||||
|                 "<style>" + |                 "<style>" + | ||||||
|                 "table{border-collapse:collapse;}" + |                 "table{border-collapse:collapse;}" + | ||||||
|  | @ -33,30 +60,6 @@ public class HTMLRenderer implements Renderer<String> { | ||||||
|                 "</head>" + |                 "</head>" + | ||||||
|                 "<body>" + |                 "<body>" + | ||||||
|                 "<input type=\"checkbox\" onclick=\"toggleSolution()\">show solution</input>"; |                 "<input type=\"checkbox\" onclick=\"toggleSolution()\">show solution</input>"; | ||||||
|     private static final String POSTAMBLE = "</body></html>"; |  | ||||||
| 
 |  | ||||||
|     private HTMLRenderer() { |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @NonNull |  | ||||||
|     public static HTMLRenderer newInstance() { |  | ||||||
|         return new HTMLRenderer(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @NonNull |  | ||||||
|     public String render(@NonNull final Labyrinth labyrinth) { |  | ||||||
|         if (labyrinth.getWidth() == 0 || labyrinth.getHeight() == 0) { |  | ||||||
|             return PREAMBLE + POSTAMBLE; |  | ||||||
|         } |  | ||||||
|         final Generator generator = new Generator(labyrinth); |  | ||||||
|         final StringBuilder sb = new StringBuilder(PREAMBLE); |  | ||||||
|         sb.append("<table>"); |  | ||||||
|         while (generator.hasNext()) { |  | ||||||
|             sb.append(generator.next()); |  | ||||||
|         } |  | ||||||
|         sb.append("</table>"); |  | ||||||
|         sb.append(POSTAMBLE); |  | ||||||
|         return sb.toString(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @RequiredArgsConstructor |     @RequiredArgsConstructor | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ import lombok.NonNull; | ||||||
| 
 | 
 | ||||||
| import java.util.Deque; | import java.util.Deque; | ||||||
| import java.util.LinkedList; | import java.util.LinkedList; | ||||||
|  | import java.util.Random; | ||||||
| 
 | 
 | ||||||
| public class Labyrinth { | public class Labyrinth { | ||||||
|     private final Tile[][] field; |     private final Tile[][] field; | ||||||
|  | @ -14,13 +15,22 @@ public class Labyrinth { | ||||||
|     @Getter |     @Getter | ||||||
|     private final int height; |     private final int height; | ||||||
|     @Getter |     @Getter | ||||||
|  |     private final long randomSeed; | ||||||
|  |     private final Random random; | ||||||
|  |     @Getter | ||||||
|     private final Position start; |     private final Position start; | ||||||
|     @Getter |     @Getter | ||||||
|     private final Position end; |     private final Position end; | ||||||
| 
 | 
 | ||||||
|     public Labyrinth(final int width, final int height) { |     public Labyrinth(final int width, final int height) { | ||||||
|  |         this(width, height, System.nanoTime()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Labyrinth(final int width, final int height, final long randomSeed) { | ||||||
|         this.width = width; |         this.width = width; | ||||||
|         this.height = height; |         this.height = height; | ||||||
|  |         this.randomSeed = randomSeed; | ||||||
|  |         this.random = new Random(this.randomSeed); | ||||||
|         this.field = new Tile[width][height]; |         this.field = new Tile[width][height]; | ||||||
|         this.start = new Position(0, 0); |         this.start = new Position(0, 0); | ||||||
|         this.end = new Position(this.width - 1, this.height - 1); |         this.end = new Position(this.width - 1, this.height - 1); | ||||||
|  | @ -94,7 +104,7 @@ public class Labyrinth { | ||||||
|             while (!this.positions.isEmpty()) { |             while (!this.positions.isEmpty()) { | ||||||
|                 final Position currentPosition = this.positions.peek(); |                 final Position currentPosition = this.positions.peek(); | ||||||
|                 final Tile currentTile = Labyrinth.this.getTileAt(currentPosition); |                 final Tile currentTile = Labyrinth.this.getTileAt(currentPosition); | ||||||
|                 final Option<Direction> directionToDigTo = currentTile.getRandomAvailableDirection(); |                 final Option<Direction> directionToDigTo = currentTile.getRandomAvailableDirection(Labyrinth.this.random); | ||||||
|                 if (directionToDigTo.isDefined()) { |                 if (directionToDigTo.isDefined()) { | ||||||
|                     final Direction digTo = directionToDigTo.get(); |                     final Direction digTo = directionToDigTo.get(); | ||||||
|                     final Direction digFrom = digTo.invert(); |                     final Direction digFrom = digTo.invert(); | ||||||
|  |  | ||||||
|  | @ -9,17 +9,20 @@ public class Main { | ||||||
|     public static void main(@NonNull final String[] args) { |     public static void main(@NonNull final String[] args) { | ||||||
|         int width = 100; |         int width = 100; | ||||||
|         int height = 100; |         int height = 100; | ||||||
|         final Labyrinth labyrinth = new Labyrinth(width, height); |         final Labyrinth labyrinth = new Labyrinth(width, height/*, 0*/); | ||||||
|         final TextRenderer textRenderer = TextRenderer.newInstance(); |         final TextRenderer textRenderer = TextRenderer.newInstance(); | ||||||
|         final HTMLRenderer htmlRenderer = HTMLRenderer.newInstance(); |         final HTMLRenderer htmlRenderer = HTMLRenderer.newInstance(); | ||||||
|         final Path userHome = Paths.get(System.getProperty("user.home")); |         final Path userHome = Paths.get(System.getProperty("user.home")); | ||||||
|  |         final String baseFilename = getBaseFilename(labyrinth); | ||||||
|         final TextFileRenderer textFileRenderer = TextFileRenderer.newInstance() |         final TextFileRenderer textFileRenderer = TextFileRenderer.newInstance() | ||||||
|                 .setTargetLabyrinthFile(userHome.resolve("labyrinth.txt")) |                 .setTargetLabyrinthFile(userHome.resolve(baseFilename + ".txt")) | ||||||
|                 .setTargetSolutionFile(userHome.resolve("labyrinth-solution.txt")); |                 .setTargetSolutionFile(userHome.resolve(baseFilename + "-solution.txt")); | ||||||
|         final HTMLFileRenderer htmlFileRenderer = HTMLFileRenderer.newInstance() |         final HTMLFileRenderer htmlFileRenderer = HTMLFileRenderer.newInstance() | ||||||
|                 .setTargetFile(userHome.resolve("labyrinth.html")); |                 .setTargetFile(userHome.resolve(baseFilename + ".html")); | ||||||
|         final PDFFileRenderer pdfFileRenderer = PDFFileRenderer.newInstance().setTargetFile(userHome.resolve("labyrinth.pdf")); |         final PDFFileRenderer pdfFileRenderer = PDFFileRenderer.newInstance() | ||||||
|  |                 .setTargetFile(userHome.resolve(baseFilename + ".pdf")); | ||||||
| 
 | 
 | ||||||
|  |         System.out.println("Labyrinth-ID: " + labyrinth.getRandomSeed()); | ||||||
|         // Render Labyrinth to stdout |         // Render Labyrinth to stdout | ||||||
|         System.out.println(textRenderer.render(labyrinth)); |         System.out.println(textRenderer.render(labyrinth)); | ||||||
|         // Render Labyrinth solution to stdout |         // Render Labyrinth solution to stdout | ||||||
|  | @ -33,4 +36,8 @@ public class Main { | ||||||
|         // Render PDF to file |         // Render PDF to file | ||||||
|         System.out.println(pdfFileRenderer.render(labyrinth)); |         System.out.println(pdfFileRenderer.render(labyrinth)); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     private static String getBaseFilename(@NonNull final Labyrinth labyrinth) { | ||||||
|  |         return "labyrinth-" + labyrinth.getWidth() + "x" + labyrinth.getHeight() + "-" + labyrinth.getRandomSeed(); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ package ch.fritteli.labyrinth; | ||||||
| 
 | 
 | ||||||
| import lombok.NonNull; | import lombok.NonNull; | ||||||
| import org.apache.pdfbox.pdmodel.PDDocument; | import org.apache.pdfbox.pdmodel.PDDocument; | ||||||
|  | import org.apache.pdfbox.pdmodel.PDDocumentInformation; | ||||||
| import org.apache.pdfbox.pdmodel.PDPage; | import org.apache.pdfbox.pdmodel.PDPage; | ||||||
| import org.apache.pdfbox.pdmodel.PDPageContentStream; | import org.apache.pdfbox.pdmodel.PDPageContentStream; | ||||||
| import org.apache.pdfbox.pdmodel.common.PDRectangle; | import org.apache.pdfbox.pdmodel.common.PDRectangle; | ||||||
|  | @ -35,30 +36,22 @@ public class PDFRenderer implements Renderer<byte[]> { | ||||||
|         final float pageHeight = labyrinth.getHeight() * SCALE + 2 * MARGIN; |         final float pageHeight = labyrinth.getHeight() * SCALE + 2 * MARGIN; | ||||||
| 
 | 
 | ||||||
|         final PDDocument pdDocument = new PDDocument(); |         final PDDocument pdDocument = new PDDocument(); | ||||||
|  |         final PDDocumentInformation info = new PDDocumentInformation(); | ||||||
|  |         info.setTitle("Labyrinth " + labyrinth.getWidth() + "x" + labyrinth.getHeight() + ", ID " + labyrinth.getRandomSeed()); | ||||||
|  |         pdDocument.setDocumentInformation(info); | ||||||
|         final PDPage page = new PDPage(new PDRectangle(pageWidth, pageHeight)); |         final PDPage page = new PDPage(new PDRectangle(pageWidth, pageHeight)); | ||||||
|         pdDocument.addPage(page); |  | ||||||
|         try (PDPageContentStream pdPageContentStream = new PDPageContentStream(pdDocument, page)) { |  | ||||||
|             pdPageContentStream.setLineCapStyle(BasicStroke.CAP_ROUND); |  | ||||||
|             pdPageContentStream.setLineJoinStyle(BasicStroke.JOIN_MITER); |  | ||||||
|             pdPageContentStream.setLineWidth(1.0f); |  | ||||||
|             pdPageContentStream.setStrokingColor(Color.BLACK); |  | ||||||
|             pdPageContentStream.setNonStrokingColor(Color.BLACK); |  | ||||||
|             this.drawHorizonzalLines(labyrinth, pdPageContentStream); |  | ||||||
|             this.drawVerticalLines(labyrinth, pdPageContentStream); |  | ||||||
|         } catch (IOException e) { |  | ||||||
|             e.printStackTrace(); |  | ||||||
|         } |  | ||||||
|         final PDPage solution = new PDPage(new PDRectangle(pageWidth, pageHeight)); |         final PDPage solution = new PDPage(new PDRectangle(pageWidth, pageHeight)); | ||||||
|  |         pdDocument.addPage(page); | ||||||
|         pdDocument.addPage(solution); |         pdDocument.addPage(solution); | ||||||
|         try (PDPageContentStream pdPageContentStream = new PDPageContentStream(pdDocument, solution)) { |         try (final PDPageContentStream labyrinthPageContentStream = new PDPageContentStream(pdDocument, page); | ||||||
|             pdPageContentStream.setLineCapStyle(BasicStroke.CAP_ROUND); |              final PDPageContentStream solutionPageContentStream = new PDPageContentStream(pdDocument, solution)) { | ||||||
|             pdPageContentStream.setLineJoinStyle(BasicStroke.JOIN_MITER); |             setUpPageContentStream(labyrinthPageContentStream); | ||||||
|             pdPageContentStream.setLineWidth(1.0f); |             setUpPageContentStream(solutionPageContentStream); | ||||||
|             pdPageContentStream.setStrokingColor(Color.BLACK); |             this.drawHorizonzalLines(labyrinth, labyrinthPageContentStream); | ||||||
|             pdPageContentStream.setNonStrokingColor(Color.BLACK); |             this.drawVerticalLines(labyrinth, labyrinthPageContentStream); | ||||||
|             this.drawHorizonzalLines(labyrinth, pdPageContentStream); |             this.drawHorizonzalLines(labyrinth, solutionPageContentStream); | ||||||
|             this.drawVerticalLines(labyrinth, pdPageContentStream); |             this.drawVerticalLines(labyrinth, solutionPageContentStream); | ||||||
|             this.drawSolution(labyrinth, pdPageContentStream); |             this.drawSolution(labyrinth, solutionPageContentStream); | ||||||
|         } catch (IOException e) { |         } catch (IOException e) { | ||||||
|             e.printStackTrace(); |             e.printStackTrace(); | ||||||
|         } |         } | ||||||
|  | @ -72,51 +65,65 @@ public class PDFRenderer implements Renderer<byte[]> { | ||||||
|         return output.toByteArray(); |         return output.toByteArray(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private void setUpPageContentStream(@NonNull final PDPageContentStream pageContentStream) throws IOException { | ||||||
|  |         pageContentStream.setLineCapStyle(BasicStroke.CAP_ROUND); | ||||||
|  |         pageContentStream.setLineJoinStyle(BasicStroke.JOIN_ROUND); | ||||||
|  |         pageContentStream.setLineWidth(1.0f); | ||||||
|  |         pageContentStream.setStrokingColor(Color.BLACK); | ||||||
|  |         pageContentStream.setNonStrokingColor(Color.BLACK); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private void drawHorizonzalLines(@NonNull final Labyrinth labyrinth, |     private void drawHorizonzalLines(@NonNull final Labyrinth labyrinth, | ||||||
|                                      @NonNull final PDPageContentStream pdPageContentStream) throws IOException { |                                      @NonNull final PDPageContentStream pdPageContentStream) throws IOException { | ||||||
|         // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. |         // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. | ||||||
|         final float labyrinthHeight = labyrinth.getHeight() * SCALE; |         final float labyrinthHeight = labyrinth.getHeight() * SCALE; | ||||||
|         for (int y = 0; y < labyrinth.getHeight(); y++) { |         for (int y = 0; y < labyrinth.getHeight(); y++) { | ||||||
|             boolean isPainting = false; |             boolean isPainting = false; | ||||||
|  |             final float yCoordinate = labyrinthHeight - y * SCALE + MARGIN; | ||||||
|             for (int x = 0; x < labyrinth.getWidth(); x++) { |             for (int x = 0; x < labyrinth.getWidth(); x++) { | ||||||
|                 final Tile currentTile = labyrinth.getTileAt(x, y); |                 final Tile currentTile = labyrinth.getTileAt(x, y); | ||||||
|  |                 final float xCoordinate = x * SCALE + MARGIN; | ||||||
|                 if (currentTile.hasWallAt(Direction.TOP)) { |                 if (currentTile.hasWallAt(Direction.TOP)) { | ||||||
|                     if (!isPainting) { |                     if (!isPainting) { | ||||||
|                         pdPageContentStream.moveTo(x * SCALE + MARGIN, labyrinthHeight - y * SCALE + MARGIN); |                         pdPageContentStream.moveTo(xCoordinate, yCoordinate); | ||||||
|                         isPainting = true; |                         isPainting = true; | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } else { | ||||||
|                     if (isPainting) { |                     if (isPainting) { | ||||||
|                         pdPageContentStream.lineTo(x * SCALE + MARGIN, labyrinthHeight - y * SCALE + MARGIN); |                         pdPageContentStream.lineTo(xCoordinate, yCoordinate); | ||||||
|                         pdPageContentStream.stroke(); |                         pdPageContentStream.stroke(); | ||||||
|                         isPainting = false; |                         isPainting = false; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (isPainting) { |             if (isPainting) { | ||||||
|                 pdPageContentStream.lineTo(labyrinth.getWidth() * SCALE + MARGIN, labyrinthHeight - y * SCALE + MARGIN); |                 final float xCoordinate = labyrinth.getWidth() * SCALE + MARGIN; | ||||||
|  |                 pdPageContentStream.lineTo(xCoordinate, yCoordinate); | ||||||
|                 pdPageContentStream.stroke(); |                 pdPageContentStream.stroke(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         boolean isPainting = false; |         boolean isPainting = false; | ||||||
|         int y = labyrinth.getHeight(); |         int y = labyrinth.getHeight(); | ||||||
|  |         final float yCoordinate = /*labyrinthHeight - y * SCALE +*/ MARGIN; | ||||||
|         for (int x = 0; x < labyrinth.getWidth(); x++) { |         for (int x = 0; x < labyrinth.getWidth(); x++) { | ||||||
|             final Tile currentTile = labyrinth.getTileAt(x, y - 1); |             final Tile currentTile = labyrinth.getTileAt(x, y - 1); | ||||||
|  |             final float xCoordinate = x * SCALE + MARGIN; | ||||||
|             if (currentTile.hasWallAt(Direction.BOTTOM)) { |             if (currentTile.hasWallAt(Direction.BOTTOM)) { | ||||||
|                 if (!isPainting) { |                 if (!isPainting) { | ||||||
|                     pdPageContentStream.moveTo(x * SCALE + MARGIN, labyrinthHeight - y * SCALE + MARGIN); |                     pdPageContentStream.moveTo(xCoordinate, yCoordinate); | ||||||
|                     isPainting = true; |                     isPainting = true; | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 if (isPainting) { |                 if (isPainting) { | ||||||
|                     pdPageContentStream.lineTo(x * SCALE + MARGIN, labyrinthHeight - y * SCALE + MARGIN); |                     pdPageContentStream.lineTo(xCoordinate, yCoordinate); | ||||||
|                     pdPageContentStream.stroke(); |                     pdPageContentStream.stroke(); | ||||||
|                     isPainting = false; |                     isPainting = false; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |         final float xCoordinate = labyrinth.getWidth() * SCALE + MARGIN; | ||||||
|         if (isPainting) { |         if (isPainting) { | ||||||
|             pdPageContentStream.lineTo(labyrinth.getWidth() * SCALE + MARGIN, labyrinthHeight - labyrinth.getHeight() * SCALE + MARGIN); |             pdPageContentStream.lineTo(xCoordinate, yCoordinate); | ||||||
|             pdPageContentStream.stroke(); |             pdPageContentStream.stroke(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -127,45 +134,49 @@ public class PDFRenderer implements Renderer<byte[]> { | ||||||
|         final float labyrinthHeight = labyrinth.getHeight() * SCALE; |         final float labyrinthHeight = labyrinth.getHeight() * SCALE; | ||||||
|         for (int x = 0; x < labyrinth.getWidth(); x++) { |         for (int x = 0; x < labyrinth.getWidth(); x++) { | ||||||
|             boolean isPainting = false; |             boolean isPainting = false; | ||||||
|  |             final float xCoordinate = x * SCALE + MARGIN; | ||||||
|             for (int y = 0; y < labyrinth.getHeight(); y++) { |             for (int y = 0; y < labyrinth.getHeight(); y++) { | ||||||
|                 final Tile currentTile = labyrinth.getTileAt(x, y); |                 final Tile currentTile = labyrinth.getTileAt(x, y); | ||||||
|  |                 final float yCoordinate = labyrinthHeight - y * SCALE + MARGIN; | ||||||
|                 if (currentTile.hasWallAt(Direction.LEFT)) { |                 if (currentTile.hasWallAt(Direction.LEFT)) { | ||||||
|                     if (!isPainting) { |                     if (!isPainting) { | ||||||
|                         pdPageContentStream.moveTo(x * SCALE + MARGIN, labyrinthHeight - y * SCALE + MARGIN); |                         pdPageContentStream.moveTo(xCoordinate, yCoordinate); | ||||||
|                         isPainting = true; |                         isPainting = true; | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } else { | ||||||
|                     if (isPainting) { |                     if (isPainting) { | ||||||
|                         pdPageContentStream.lineTo(x * SCALE + MARGIN, labyrinthHeight - y * SCALE + MARGIN); |                         pdPageContentStream.lineTo(xCoordinate, yCoordinate); | ||||||
|                         pdPageContentStream.stroke(); |                         pdPageContentStream.stroke(); | ||||||
|                         isPainting = false; |                         isPainting = false; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (isPainting) { |             if (isPainting) { | ||||||
|                 pdPageContentStream.lineTo(x * SCALE + MARGIN, labyrinthHeight - labyrinth.getHeight() * SCALE + MARGIN); |                 pdPageContentStream.lineTo(xCoordinate, MARGIN); | ||||||
|                 pdPageContentStream.stroke(); |                 pdPageContentStream.stroke(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         boolean isPainting = false; |         boolean isPainting = false; | ||||||
|         int x = labyrinth.getWidth(); |         int x = labyrinth.getWidth(); | ||||||
|  |         final float xCoordinate = x * SCALE + MARGIN; | ||||||
|         for (int y = 0; y < labyrinth.getHeight(); y++) { |         for (int y = 0; y < labyrinth.getHeight(); y++) { | ||||||
|             final Tile currentTile = labyrinth.getTileAt(x - 1, y); |             final Tile currentTile = labyrinth.getTileAt(x - 1, y); | ||||||
|  |             final float yCoordinate = labyrinthHeight - y * SCALE + MARGIN; | ||||||
|             if (currentTile.hasWallAt(Direction.RIGHT)) { |             if (currentTile.hasWallAt(Direction.RIGHT)) { | ||||||
|                 if (!isPainting) { |                 if (!isPainting) { | ||||||
|                     pdPageContentStream.moveTo(x * SCALE + MARGIN, labyrinthHeight - y * SCALE + MARGIN); |                     pdPageContentStream.moveTo(xCoordinate, yCoordinate); | ||||||
|                     isPainting = true; |                     isPainting = true; | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 if (isPainting) { |                 if (isPainting) { | ||||||
|                     pdPageContentStream.lineTo(x * SCALE + MARGIN, labyrinthHeight - y * SCALE + MARGIN); |                     pdPageContentStream.lineTo(xCoordinate, yCoordinate); | ||||||
|                     pdPageContentStream.stroke(); |                     pdPageContentStream.stroke(); | ||||||
|                     isPainting = false; |                     isPainting = false; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (isPainting) { |         if (isPainting) { | ||||||
|             pdPageContentStream.lineTo(labyrinth.getWidth() * SCALE + MARGIN, labyrinthHeight - labyrinth.getHeight() * SCALE + MARGIN); |             pdPageContentStream.lineTo(xCoordinate, MARGIN); | ||||||
|             pdPageContentStream.stroke(); |             pdPageContentStream.stroke(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -184,11 +195,14 @@ public class PDFRenderer implements Renderer<byte[]> { | ||||||
|             Position newCurrent = this.findNextSolutionPosition(labyrinth, previousPosition, currentPosition); |             Position newCurrent = this.findNextSolutionPosition(labyrinth, previousPosition, currentPosition); | ||||||
|             previousPosition = currentPosition; |             previousPosition = currentPosition; | ||||||
|             currentPosition = newCurrent; |             currentPosition = newCurrent; | ||||||
|             pdPageContentStream.lineTo(MARGIN + currentPosition.getX() * SCALE + SCALE / 2, MARGIN + labyrinthHeight - (currentPosition.getY() * SCALE + SCALE / 2)); |             final float xCoordinate = MARGIN + currentPosition.getX() * SCALE + SCALE / 2; | ||||||
|  |             final float yCoordinate = MARGIN + labyrinthHeight - (currentPosition.getY() * SCALE + SCALE / 2); | ||||||
|  |             pdPageContentStream.lineTo(xCoordinate, yCoordinate); | ||||||
|         } while (!currentPosition.equals(end)); |         } while (!currentPosition.equals(end)); | ||||||
|         pdPageContentStream.stroke(); |         pdPageContentStream.stroke(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @NonNull | ||||||
|     private Position findNextSolutionPosition(@NonNull final Labyrinth labyrinth, @Nullable final Position previousPosition, @NonNull final Position currentPosition) { |     private Position findNextSolutionPosition(@NonNull final Labyrinth labyrinth, @Nullable final Position previousPosition, @NonNull final Position currentPosition) { | ||||||
|         final Tile currentTile = labyrinth.getTileAt(currentPosition); |         final Tile currentTile = labyrinth.getTileAt(currentPosition); | ||||||
|         for (final Direction direction : Direction.values()) { |         for (final Direction direction : Direction.values()) { | ||||||
|  | @ -202,7 +216,6 @@ public class PDFRenderer implements Renderer<byte[]> { | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         // We *SHOULD* never get here. ... famous last words ... |         throw new IllegalStateException("We *SHOULD* never have gotten here. ... famous last words ..."); | ||||||
|         return null; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -7,6 +7,8 @@ import lombok.Getter; | ||||||
| import lombok.NonNull; | import lombok.NonNull; | ||||||
| import lombok.experimental.FieldDefaults; | import lombok.experimental.FieldDefaults; | ||||||
| 
 | 
 | ||||||
|  | import java.util.Random; | ||||||
|  | 
 | ||||||
| @FieldDefaults(level = AccessLevel.PRIVATE) | @FieldDefaults(level = AccessLevel.PRIVATE) | ||||||
| public class Tile { | public class Tile { | ||||||
|     final Walls walls = new Walls(); |     final Walls walls = new Walls(); | ||||||
|  | @ -42,8 +44,13 @@ public class Tile { | ||||||
|         this.walls.set(direction); |         this.walls.set(direction); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public Option<Direction> getRandomAvailableDirection() { |     public Option<Direction> getRandomAvailableDirection(@NonNull final Random random) { | ||||||
|         return Stream.ofAll(this.walls.getUnhardenedSet()).shuffle().headOption(); |         final Stream<Direction> availableDirections = this.walls.getUnhardenedSet(); | ||||||
|  |         if (availableDirections.isEmpty()) { | ||||||
|  |             return Option.none(); | ||||||
|  |         } | ||||||
|  |         final int index = random.nextInt(availableDirections.length()); | ||||||
|  |         return Option.of(availableDirections.get(index)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public boolean hasWallAt(@NonNull final Direction direction) { |     public boolean hasWallAt(@NonNull final Direction direction) { | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ public class Walls { | ||||||
|         return this.directions.contains(direction); |         return this.directions.contains(direction); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public Iterable<Direction> getUnhardenedSet() { |     public Stream<Direction> getUnhardenedSet() { | ||||||
|         return Stream.ofAll(this.directions) |         return Stream.ofAll(this.directions) | ||||||
|                 .removeAll(this.hardened); |                 .removeAll(this.hardened); | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue