Cleanup and refactoring: Eliminate duplicated code.
This commit is contained in:
		
							parent
							
								
									9579066cb5
								
							
						
					
					
						commit
						5a642b354b
					
				
					 10 changed files with 132 additions and 246 deletions
				
			
		|  | @ -0,0 +1,100 @@ | ||||||
|  | package ch.fritteli.maze.generator.serialization; | ||||||
|  | 
 | ||||||
|  | import ch.fritteli.maze.generator.model.Direction; | ||||||
|  | import ch.fritteli.maze.generator.model.Tile; | ||||||
|  | import lombok.experimental.UtilityClass; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
|  | 
 | ||||||
|  | import java.lang.reflect.Constructor; | ||||||
|  | import java.lang.reflect.InvocationTargetException; | ||||||
|  | import java.util.EnumSet; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Binary format description of a {@link Tile}.<br> | ||||||
|  |  * A tile is stored in one byte: | ||||||
|  |  * <ul> | ||||||
|  |  *     <li>bits 0..2: always 0</li> | ||||||
|  |  *     <li>bit 3: 1=solution, 0=not solution</li> | ||||||
|  |  *     <li>bits 4..7: encode walls</li> | ||||||
|  |  * </ul> | ||||||
|  |  * The values for bits 4..7 are as follows: | ||||||
|  |  * <pre> | ||||||
|  |  * decimal hex bin  border | ||||||
|  |  *       0   0 0000 no border | ||||||
|  |  *       1   1 0001 top | ||||||
|  |  *       2   2 0010 right | ||||||
|  |  *       3   3 0011 top+right | ||||||
|  |  *       4   4 0100 bottom | ||||||
|  |  *       5   5 0101 top+bottom | ||||||
|  |  *       6   6 0110 right+bottom | ||||||
|  |  *       7   7 0111 top+right+bottom | ||||||
|  |  *       8   8 1000 left | ||||||
|  |  *       9   9 1001 top+left | ||||||
|  |  *      10   a 1010 right+left | ||||||
|  |  *      11   b 1011 top+right+left | ||||||
|  |  *      12   c 1100 bottom+left | ||||||
|  |  *      13   d 1101 top+bottom+left | ||||||
|  |  *      14   e 1110 right+bottom+left | ||||||
|  |  *      15   f 1111 top+right+bottom+left | ||||||
|  |  * </pre> | ||||||
|  |  */ | ||||||
|  | @UtilityClass | ||||||
|  | public class CommonTileHandler { | ||||||
|  |     private final byte TOP_BIT = 0b0000_0001; | ||||||
|  |     private final byte RIGHT_BIT = 0b0000_0010; | ||||||
|  |     private final byte BOTTOM_BIT = 0b0000_0100; | ||||||
|  |     private final byte LEFT_BIT = 0b0000_1000; | ||||||
|  |     private final byte SOLUTION_BIT = 0b0001_0000; | ||||||
|  | 
 | ||||||
|  |     public byte getBitmaskForTile(@NotNull final Tile tile) { | ||||||
|  |         byte bitmask = 0; | ||||||
|  |         if (tile.hasWallAt(Direction.TOP)) { | ||||||
|  |             bitmask |= TOP_BIT; | ||||||
|  |         } | ||||||
|  |         if (tile.hasWallAt(Direction.RIGHT)) { | ||||||
|  |             bitmask |= RIGHT_BIT; | ||||||
|  |         } | ||||||
|  |         if (tile.hasWallAt(Direction.BOTTOM)) { | ||||||
|  |             bitmask |= BOTTOM_BIT; | ||||||
|  |         } | ||||||
|  |         if (tile.hasWallAt((Direction.LEFT))) { | ||||||
|  |             bitmask |= LEFT_BIT; | ||||||
|  |         } | ||||||
|  |         if (tile.isSolution()) { | ||||||
|  |             bitmask |= SOLUTION_BIT; | ||||||
|  |         } | ||||||
|  |         return bitmask; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @NotNull | ||||||
|  |     public Tile getTileForBitmask(final byte bitmask) { | ||||||
|  |         final EnumSet<Direction> walls = EnumSet.noneOf(Direction.class); | ||||||
|  |         if ((bitmask & TOP_BIT) == TOP_BIT) { | ||||||
|  |             walls.add(Direction.TOP); | ||||||
|  |         } | ||||||
|  |         if ((bitmask & RIGHT_BIT) == RIGHT_BIT) { | ||||||
|  |             walls.add(Direction.RIGHT); | ||||||
|  |         } | ||||||
|  |         if ((bitmask & BOTTOM_BIT) == BOTTOM_BIT) { | ||||||
|  |             walls.add(Direction.BOTTOM); | ||||||
|  |         } | ||||||
|  |         if ((bitmask & LEFT_BIT) == LEFT_BIT) { | ||||||
|  |             walls.add(Direction.LEFT); | ||||||
|  |         } | ||||||
|  |         final boolean solution = (bitmask & SOLUTION_BIT) == SOLUTION_BIT; | ||||||
|  |         return createTile(walls, solution); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @NotNull | ||||||
|  |     private Tile createTile(@NotNull final EnumSet<Direction> walls, boolean solution) { | ||||||
|  |         try { | ||||||
|  |             final Constructor<Tile> constructor = Tile.class.getDeclaredConstructor(EnumSet.class, Boolean.TYPE); | ||||||
|  |             constructor.setAccessible(true); | ||||||
|  |             return constructor.newInstance(walls, solution); | ||||||
|  |         } catch (@NotNull final NoSuchMethodException | InstantiationException | IllegalAccessException | | ||||||
|  |                                 InvocationTargetException e) { | ||||||
|  |             throw new RuntimeException("Can not deserialize Tile from maze data.", e); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -3,6 +3,7 @@ package ch.fritteli.maze.generator.serialization.v1; | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream; | import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream; | ||||||
|  | import ch.fritteli.maze.generator.serialization.CommonTileHandler; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| public class MazeInputStreamV1 extends AbstractMazeInputStream { | public class MazeInputStreamV1 extends AbstractMazeInputStream { | ||||||
|  | @ -13,6 +14,9 @@ public class MazeInputStreamV1 extends AbstractMazeInputStream { | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void checkHeader() { |     public void checkHeader() { | ||||||
|  |         // 00 0x1a magic | ||||||
|  |         // 01 0xb1 magic | ||||||
|  |         // 02 0x01 version | ||||||
|         final byte magic1 = this.readByte(); |         final byte magic1 = this.readByte(); | ||||||
|         if (magic1 != SerializerDeserializerV1.MAGIC_BYTE_1) { |         if (magic1 != SerializerDeserializerV1.MAGIC_BYTE_1) { | ||||||
|             throw new IllegalArgumentException("Invalid maze data."); |             throw new IllegalArgumentException("Invalid maze data."); | ||||||
|  | @ -30,6 +34,10 @@ public class MazeInputStreamV1 extends AbstractMazeInputStream { | ||||||
|     @NotNull |     @NotNull | ||||||
|     @Override |     @Override | ||||||
|     public Maze readMazeData() { |     public Maze readMazeData() { | ||||||
|  |         // 03..10  random seed number (long) | ||||||
|  |         // 11..14  width (int) | ||||||
|  |         // 15..18  height (int) | ||||||
|  |         // 19..    tiles | ||||||
|         final long randomSeed = this.readLong(); |         final long randomSeed = this.readLong(); | ||||||
|         final int width = this.readInt(); |         final int width = this.readInt(); | ||||||
|         final int height = this.readInt(); |         final int height = this.readInt(); | ||||||
|  | @ -42,7 +50,7 @@ public class MazeInputStreamV1 extends AbstractMazeInputStream { | ||||||
|         for (int y = 0; y < height; y++) { |         for (int y = 0; y < height; y++) { | ||||||
|             for (int x = 0; x < width; x++) { |             for (int x = 0; x < width; x++) { | ||||||
|                 final byte bitmask = this.readByte(); |                 final byte bitmask = this.readByte(); | ||||||
|                 tiles[x][y] = SerializerDeserializerV1.getTileForBitmask(bitmask); |                 tiles[x][y] = CommonTileHandler.getTileForBitmask(bitmask); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,12 +3,16 @@ package ch.fritteli.maze.generator.serialization.v1; | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream; | import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream; | ||||||
|  | import ch.fritteli.maze.generator.serialization.CommonTileHandler; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| public class MazeOutputStreamV1 extends AbstractMazeOutputStream { | public class MazeOutputStreamV1 extends AbstractMazeOutputStream { | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void writeHeader() { |     public void writeHeader() { | ||||||
|  |         // 00 0x1a magic | ||||||
|  |         // 01 0xb1 magic | ||||||
|  |         // 02 0x02 version | ||||||
|         this.writeByte(SerializerDeserializerV1.MAGIC_BYTE_1); |         this.writeByte(SerializerDeserializerV1.MAGIC_BYTE_1); | ||||||
|         this.writeByte(SerializerDeserializerV1.MAGIC_BYTE_2); |         this.writeByte(SerializerDeserializerV1.MAGIC_BYTE_2); | ||||||
|         this.writeByte(SerializerDeserializerV1.VERSION_BYTE); |         this.writeByte(SerializerDeserializerV1.VERSION_BYTE); | ||||||
|  | @ -16,6 +20,10 @@ public class MazeOutputStreamV1 extends AbstractMazeOutputStream { | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void writeMazeData(@NotNull final Maze maze) { |     public void writeMazeData(@NotNull final Maze maze) { | ||||||
|  |         // 03..10  random seed number (long) | ||||||
|  |         // 11..14  width (int) | ||||||
|  |         // 15..18  height (int) | ||||||
|  |         // 19..    tiles | ||||||
|         final long randomSeed = maze.getRandomSeed(); |         final long randomSeed = maze.getRandomSeed(); | ||||||
|         final int width = maze.getWidth(); |         final int width = maze.getWidth(); | ||||||
|         final int height = maze.getHeight(); |         final int height = maze.getHeight(); | ||||||
|  | @ -27,7 +35,7 @@ public class MazeOutputStreamV1 extends AbstractMazeOutputStream { | ||||||
|             for (int x = 0; x < width; x++) { |             for (int x = 0; x < width; x++) { | ||||||
|                 // We .get() it, because we want to crash hard if it is not available. |                 // We .get() it, because we want to crash hard if it is not available. | ||||||
|                 final Tile tile = maze.getTileAt(x, y).get(); |                 final Tile tile = maze.getTileAt(x, y).get(); | ||||||
|                 final byte bitmask = SerializerDeserializerV1.getBitmaskForTile(tile); |                 final byte bitmask = CommonTileHandler.getBitmaskForTile(tile); | ||||||
|                 this.writeByte(bitmask); |                 this.writeByte(bitmask); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| package ch.fritteli.maze.generator.serialization.v1; | package ch.fritteli.maze.generator.serialization.v1; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.maze.generator.model.Direction; |  | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import lombok.experimental.UtilityClass; | import lombok.experimental.UtilityClass; | ||||||
|  | @ -8,37 +7,17 @@ import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| import java.lang.reflect.Constructor; | import java.lang.reflect.Constructor; | ||||||
| import java.lang.reflect.InvocationTargetException; | import java.lang.reflect.InvocationTargetException; | ||||||
| import java.util.EnumSet; |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * <pre> |  * Header bytes are: | ||||||
|  * decimal hex bin  border |  | ||||||
|  *       0   0 0000 no border |  | ||||||
|  *       1   1 0001 top |  | ||||||
|  *       2   2 0010 right |  | ||||||
|  *       3   3 0011 top+right |  | ||||||
|  *       4   4 0100 bottom |  | ||||||
|  *       5   5 0101 top+bottom |  | ||||||
|  *       6   6 0110 right+bottom |  | ||||||
|  *       7   7 0111 top+right+bottom |  | ||||||
|  *       8   8 1000 left |  | ||||||
|  *       9   9 1001 top+left |  | ||||||
|  *      10   a 1010 right+left |  | ||||||
|  *      11   b 1011 top+right+left |  | ||||||
|  *      12   c 1100 bottom+left |  | ||||||
|  *      13   d 1101 top+bottom+left |  | ||||||
|  *      14   e 1110 right+bottom+left |  | ||||||
|  *      15   f 1111 top+right+bottom+left |  | ||||||
|  * </pre> |  | ||||||
|  * ==> bits 0..2: always 0; bit 3: 1=solution, 0=not solution; bits 4..7: encode walls ==> first bytes are: |  | ||||||
|  * <pre> |  * <pre> | ||||||
|  *   byte  hex meaning |  *   byte  hex meaning | ||||||
|  *     00 0x1a magic |  *     00 0x1a magic | ||||||
|  *     01 0xb1 magic |  *     01 0xb1 magic | ||||||
|  *     02 0x01 version (0x00 -> dev, 0x01 -> stable) |  *     02 0x01 version (0x00 -> dev, 0x01 -> stable) | ||||||
|  * 03..06      width (int) |  * 03..10      random seed number (long) | ||||||
|  * 07..10      height (int) |  * 11..14      width (int) | ||||||
|  * 11..18      random seed number (long) |  * 15..18      height (int) | ||||||
|  * 19..        tiles |  * 19..        tiles | ||||||
|  * </pre> |  * </pre> | ||||||
|  * Extraneous space (poss. last nibble) is ignored. |  * Extraneous space (poss. last nibble) is ignored. | ||||||
|  | @ -49,12 +28,6 @@ public class SerializerDeserializerV1 { | ||||||
|     final byte MAGIC_BYTE_2 = (byte) 0xb1; |     final byte MAGIC_BYTE_2 = (byte) 0xb1; | ||||||
|     final byte VERSION_BYTE = 0x01; |     final byte VERSION_BYTE = 0x01; | ||||||
| 
 | 
 | ||||||
|     private final byte TOP_BIT = 0b0000_0001; |  | ||||||
|     private final byte RIGHT_BIT = 0b0000_0010; |  | ||||||
|     private final byte BOTTOM_BIT = 0b0000_0100; |  | ||||||
|     private final byte LEFT_BIT = 0b0000_1000; |  | ||||||
|     private final byte SOLUTION_BIT = 0b0001_0000; |  | ||||||
| 
 |  | ||||||
|     /** |     /** | ||||||
|      * Serializes the {@code maze} into a byte array. |      * Serializes the {@code maze} into a byte array. | ||||||
|      * |      * | ||||||
|  | @ -93,55 +66,4 @@ public class SerializerDeserializerV1 { | ||||||
|             throw new RuntimeException("Can not deserialize Maze from maze data.", e); |             throw new RuntimeException("Can not deserialize Maze from maze data.", e); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     @NotNull |  | ||||||
|     private Tile createTile(@NotNull final EnumSet<Direction> walls, boolean solution) { |  | ||||||
|         try { |  | ||||||
|             final Constructor<Tile> constructor = Tile.class.getDeclaredConstructor(EnumSet.class, Boolean.TYPE); |  | ||||||
|             constructor.setAccessible(true); |  | ||||||
|             return constructor.newInstance(walls, solution); |  | ||||||
|         } catch (@NotNull final NoSuchMethodException | InstantiationException | IllegalAccessException | |  | ||||||
|                                 InvocationTargetException e) { |  | ||||||
|             throw new RuntimeException("Can not deserialize Tile from maze data.", e); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     byte getBitmaskForTile(@NotNull final Tile tile) { |  | ||||||
|         byte bitmask = 0; |  | ||||||
|         if (tile.hasWallAt(Direction.TOP)) { |  | ||||||
|             bitmask |= TOP_BIT; |  | ||||||
|         } |  | ||||||
|         if (tile.hasWallAt(Direction.RIGHT)) { |  | ||||||
|             bitmask |= RIGHT_BIT; |  | ||||||
|         } |  | ||||||
|         if (tile.hasWallAt(Direction.BOTTOM)) { |  | ||||||
|             bitmask |= BOTTOM_BIT; |  | ||||||
|         } |  | ||||||
|         if (tile.hasWallAt((Direction.LEFT))) { |  | ||||||
|             bitmask |= LEFT_BIT; |  | ||||||
|         } |  | ||||||
|         if (tile.isSolution()) { |  | ||||||
|             bitmask |= SOLUTION_BIT; |  | ||||||
|         } |  | ||||||
|         return bitmask; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @NotNull |  | ||||||
|     Tile getTileForBitmask(final byte bitmask) { |  | ||||||
|         final EnumSet<Direction> walls = EnumSet.noneOf(Direction.class); |  | ||||||
|         if ((bitmask & TOP_BIT) == TOP_BIT) { |  | ||||||
|             walls.add(Direction.TOP); |  | ||||||
|         } |  | ||||||
|         if ((bitmask & RIGHT_BIT) == RIGHT_BIT) { |  | ||||||
|             walls.add(Direction.RIGHT); |  | ||||||
|         } |  | ||||||
|         if ((bitmask & BOTTOM_BIT) == BOTTOM_BIT) { |  | ||||||
|             walls.add(Direction.BOTTOM); |  | ||||||
|         } |  | ||||||
|         if ((bitmask & LEFT_BIT) == LEFT_BIT) { |  | ||||||
|             walls.add(Direction.LEFT); |  | ||||||
|         } |  | ||||||
|         final boolean solution = (bitmask & SOLUTION_BIT) == SOLUTION_BIT; |  | ||||||
|         return createTile(walls, solution); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Position; | import ch.fritteli.maze.generator.model.Position; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream; | import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream; | ||||||
|  | import ch.fritteli.maze.generator.serialization.CommonTileHandler; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| public class MazeInputStreamV2 extends AbstractMazeInputStream { | public class MazeInputStreamV2 extends AbstractMazeInputStream { | ||||||
|  | @ -58,7 +59,7 @@ public class MazeInputStreamV2 extends AbstractMazeInputStream { | ||||||
|         for (int y = 0; y < height; y++) { |         for (int y = 0; y < height; y++) { | ||||||
|             for (int x = 0; x < width; x++) { |             for (int x = 0; x < width; x++) { | ||||||
|                 final byte bitmask = this.readByte(); |                 final byte bitmask = this.readByte(); | ||||||
|                 tiles[x][y] = SerializerDeserializerV2.getTileForBitmask(bitmask); |                 tiles[x][y] = CommonTileHandler.getTileForBitmask(bitmask); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Position; | import ch.fritteli.maze.generator.model.Position; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream; | import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream; | ||||||
|  | import ch.fritteli.maze.generator.serialization.CommonTileHandler; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| public class MazeOutputStreamV2 extends AbstractMazeOutputStream { | public class MazeOutputStreamV2 extends AbstractMazeOutputStream { | ||||||
|  | @ -45,7 +46,7 @@ public class MazeOutputStreamV2 extends AbstractMazeOutputStream { | ||||||
|             for (int x = 0; x < width; x++) { |             for (int x = 0; x < width; x++) { | ||||||
|                 // We .get() it, because we want to crash hard if it is not available. |                 // We .get() it, because we want to crash hard if it is not available. | ||||||
|                 final Tile tile = maze.getTileAt(x, y).get(); |                 final Tile tile = maze.getTileAt(x, y).get(); | ||||||
|                 final byte bitmask = SerializerDeserializerV2.getBitmaskForTile(tile); |                 final byte bitmask = CommonTileHandler.getBitmaskForTile(tile); | ||||||
|                 this.writeByte(bitmask); |                 this.writeByte(bitmask); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| package ch.fritteli.maze.generator.serialization.v2; | package ch.fritteli.maze.generator.serialization.v2; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.maze.generator.model.Direction; |  | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Position; | import ch.fritteli.maze.generator.model.Position; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
|  | @ -9,29 +8,9 @@ import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| import java.lang.reflect.Constructor; | import java.lang.reflect.Constructor; | ||||||
| import java.lang.reflect.InvocationTargetException; | import java.lang.reflect.InvocationTargetException; | ||||||
| import java.util.EnumSet; |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * <pre> |  * Header bytes are: | ||||||
|  * decimal hex bin  border |  | ||||||
|  *       0   0 0000 no border |  | ||||||
|  *       1   1 0001 top |  | ||||||
|  *       2   2 0010 right |  | ||||||
|  *       3   3 0011 top+right |  | ||||||
|  *       4   4 0100 bottom |  | ||||||
|  *       5   5 0101 top+bottom |  | ||||||
|  *       6   6 0110 right+bottom |  | ||||||
|  *       7   7 0111 top+right+bottom |  | ||||||
|  *       8   8 1000 left |  | ||||||
|  *       9   9 1001 top+left |  | ||||||
|  *      10   a 1010 right+left |  | ||||||
|  *      11   b 1011 top+right+left |  | ||||||
|  *      12   c 1100 bottom+left |  | ||||||
|  *      13   d 1101 top+bottom+left |  | ||||||
|  *      14   e 1110 right+bottom+left |  | ||||||
|  *      15   f 1111 top+right+bottom+left |  | ||||||
|  * </pre> |  | ||||||
|  * ==> bits 0..2: always 0; bit 3: 1=solution, 0=not solution; bits 4..7: encode walls ==> first bytes are: |  | ||||||
|  * <pre> |  * <pre> | ||||||
|  *   byte  hex meaning |  *   byte  hex meaning | ||||||
|  *     00 0x1a magic |  *     00 0x1a magic | ||||||
|  | @ -55,12 +34,6 @@ public class SerializerDeserializerV2 { | ||||||
|     final byte MAGIC_BYTE_2 = (byte) 0xb1; |     final byte MAGIC_BYTE_2 = (byte) 0xb1; | ||||||
|     final byte VERSION_BYTE = 0x02; |     final byte VERSION_BYTE = 0x02; | ||||||
| 
 | 
 | ||||||
|     private final byte TOP_BIT = 0b0000_0001; |  | ||||||
|     private final byte RIGHT_BIT = 0b0000_0010; |  | ||||||
|     private final byte BOTTOM_BIT = 0b0000_0100; |  | ||||||
|     private final byte LEFT_BIT = 0b0000_1000; |  | ||||||
|     private final byte SOLUTION_BIT = 0b0001_0000; |  | ||||||
| 
 |  | ||||||
|     /** |     /** | ||||||
|      * Serializes the {@code maze} into a byte array. |      * Serializes the {@code maze} into a byte array. | ||||||
|      * |      * | ||||||
|  | @ -99,55 +72,4 @@ public class SerializerDeserializerV2 { | ||||||
|             throw new RuntimeException("Can not deserialize Maze from maze data.", e); |             throw new RuntimeException("Can not deserialize Maze from maze data.", e); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     @NotNull |  | ||||||
|     private Tile createTile(@NotNull final EnumSet<Direction> walls, boolean solution) { |  | ||||||
|         try { |  | ||||||
|             final Constructor<Tile> constructor = Tile.class.getDeclaredConstructor(EnumSet.class, Boolean.TYPE); |  | ||||||
|             constructor.setAccessible(true); |  | ||||||
|             return constructor.newInstance(walls, solution); |  | ||||||
|         } catch (@NotNull final NoSuchMethodException | InstantiationException | IllegalAccessException | |  | ||||||
|                                 InvocationTargetException e) { |  | ||||||
|             throw new RuntimeException("Can not deserialize Tile from maze data.", e); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     byte getBitmaskForTile(@NotNull final Tile tile) { |  | ||||||
|         byte bitmask = 0; |  | ||||||
|         if (tile.hasWallAt(Direction.TOP)) { |  | ||||||
|             bitmask |= TOP_BIT; |  | ||||||
|         } |  | ||||||
|         if (tile.hasWallAt(Direction.RIGHT)) { |  | ||||||
|             bitmask |= RIGHT_BIT; |  | ||||||
|         } |  | ||||||
|         if (tile.hasWallAt(Direction.BOTTOM)) { |  | ||||||
|             bitmask |= BOTTOM_BIT; |  | ||||||
|         } |  | ||||||
|         if (tile.hasWallAt((Direction.LEFT))) { |  | ||||||
|             bitmask |= LEFT_BIT; |  | ||||||
|         } |  | ||||||
|         if (tile.isSolution()) { |  | ||||||
|             bitmask |= SOLUTION_BIT; |  | ||||||
|         } |  | ||||||
|         return bitmask; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @NotNull |  | ||||||
|     Tile getTileForBitmask(final byte bitmask) { |  | ||||||
|         final EnumSet<Direction> walls = EnumSet.noneOf(Direction.class); |  | ||||||
|         if ((bitmask & TOP_BIT) == TOP_BIT) { |  | ||||||
|             walls.add(Direction.TOP); |  | ||||||
|         } |  | ||||||
|         if ((bitmask & RIGHT_BIT) == RIGHT_BIT) { |  | ||||||
|             walls.add(Direction.RIGHT); |  | ||||||
|         } |  | ||||||
|         if ((bitmask & BOTTOM_BIT) == BOTTOM_BIT) { |  | ||||||
|             walls.add(Direction.BOTTOM); |  | ||||||
|         } |  | ||||||
|         if ((bitmask & LEFT_BIT) == LEFT_BIT) { |  | ||||||
|             walls.add(Direction.LEFT); |  | ||||||
|         } |  | ||||||
|         final boolean solution = (bitmask & SOLUTION_BIT) == SOLUTION_BIT; |  | ||||||
|         return createTile(walls, solution); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Position; | import ch.fritteli.maze.generator.model.Position; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream; | import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream; | ||||||
|  | import ch.fritteli.maze.generator.serialization.CommonTileHandler; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
|  | @ -66,7 +67,7 @@ public class MazeInputStreamV3 extends AbstractMazeInputStream { | ||||||
|         for (int y = 0; y < height; y++) { |         for (int y = 0; y < height; y++) { | ||||||
|             for (int x = 0; x < width; x++) { |             for (int x = 0; x < width; x++) { | ||||||
|                 final byte bitmask = this.readByte(); |                 final byte bitmask = this.readByte(); | ||||||
|                 tiles[x][y] = SerializerDeserializerV3.getTileForBitmask(bitmask); |                 tiles[x][y] = CommonTileHandler.getTileForBitmask(bitmask); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Position; | import ch.fritteli.maze.generator.model.Position; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream; | import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream; | ||||||
|  | import ch.fritteli.maze.generator.serialization.CommonTileHandler; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||||
|  | @ -52,7 +53,7 @@ public class MazeOutputStreamV3 extends AbstractMazeOutputStream { | ||||||
|             for (int x = 0; x < width; x++) { |             for (int x = 0; x < width; x++) { | ||||||
|                 // We .get() it, because we want to crash hard if it is not available. |                 // We .get() it, because we want to crash hard if it is not available. | ||||||
|                 final Tile tile = maze.getTileAt(x, y).get(); |                 final Tile tile = maze.getTileAt(x, y).get(); | ||||||
|                 final byte bitmask = SerializerDeserializerV3.getBitmaskForTile(tile); |                 final byte bitmask = CommonTileHandler.getBitmaskForTile(tile); | ||||||
|                 this.writeByte(bitmask); |                 this.writeByte(bitmask); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| package ch.fritteli.maze.generator.serialization.v3; | package ch.fritteli.maze.generator.serialization.v3; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.maze.generator.model.Direction; |  | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Position; | import ch.fritteli.maze.generator.model.Position; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
|  | @ -10,29 +9,9 @@ import org.jetbrains.annotations.NotNull; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.lang.reflect.Constructor; | import java.lang.reflect.Constructor; | ||||||
| import java.lang.reflect.InvocationTargetException; | import java.lang.reflect.InvocationTargetException; | ||||||
| import java.util.EnumSet; |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * <pre> |  * Header bytes are: | ||||||
|  * decimal hex bin  border |  | ||||||
|  *       0   0 0000 no border |  | ||||||
|  *       1   1 0001 top |  | ||||||
|  *       2   2 0010 right |  | ||||||
|  *       3   3 0011 top+right |  | ||||||
|  *       4   4 0100 bottom |  | ||||||
|  *       5   5 0101 top+bottom |  | ||||||
|  *       6   6 0110 right+bottom |  | ||||||
|  *       7   7 0111 top+right+bottom |  | ||||||
|  *       8   8 1000 left |  | ||||||
|  *       9   9 1001 top+left |  | ||||||
|  *      10   a 1010 right+left |  | ||||||
|  *      11   b 1011 top+right+left |  | ||||||
|  *      12   c 1100 bottom+left |  | ||||||
|  *      13   d 1101 top+bottom+left |  | ||||||
|  *      14   e 1110 right+bottom+left |  | ||||||
|  *      15   f 1111 top+right+bottom+left |  | ||||||
|  * </pre> |  | ||||||
|  * ==> bits 0..2: always 0; bit 3: 1=solution, 0=not solution; bits 4..7: encode walls ==> first bytes are: |  | ||||||
|  * <pre> |  * <pre> | ||||||
|  *   byte     hex    meaning |  *   byte     hex    meaning | ||||||
|  *     00     0x1a   magic |  *     00     0x1a   magic | ||||||
|  | @ -58,12 +37,6 @@ public class SerializerDeserializerV3 { | ||||||
|     final byte MAGIC_BYTE_2 = (byte) 0xb1; |     final byte MAGIC_BYTE_2 = (byte) 0xb1; | ||||||
|     final byte VERSION_BYTE = 0x03; |     final byte VERSION_BYTE = 0x03; | ||||||
| 
 | 
 | ||||||
|     private final byte TOP_BIT = 0b0000_0001; |  | ||||||
|     private final byte RIGHT_BIT = 0b0000_0010; |  | ||||||
|     private final byte BOTTOM_BIT = 0b0000_0100; |  | ||||||
|     private final byte LEFT_BIT = 0b0000_1000; |  | ||||||
|     private final byte SOLUTION_BIT = 0b0001_0000; |  | ||||||
| 
 |  | ||||||
|     /** |     /** | ||||||
|      * Serializes the {@code maze} into a byte array. |      * Serializes the {@code maze} into a byte array. | ||||||
|      * |      * | ||||||
|  | @ -116,55 +89,4 @@ public class SerializerDeserializerV3 { | ||||||
|             throw new RuntimeException("Can not deserialize Maze from maze data.", e); |             throw new RuntimeException("Can not deserialize Maze from maze data.", e); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     @NotNull |  | ||||||
|     private Tile createTile(@NotNull final EnumSet<Direction> walls, boolean solution) { |  | ||||||
|         try { |  | ||||||
|             final Constructor<Tile> constructor = Tile.class.getDeclaredConstructor(EnumSet.class, Boolean.TYPE); |  | ||||||
|             constructor.setAccessible(true); |  | ||||||
|             return constructor.newInstance(walls, solution); |  | ||||||
|         } catch (@NotNull final NoSuchMethodException | InstantiationException | IllegalAccessException | |  | ||||||
|                                 InvocationTargetException e) { |  | ||||||
|             throw new RuntimeException("Can not deserialize Tile from maze data.", e); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     byte getBitmaskForTile(@NotNull final Tile tile) { |  | ||||||
|         byte bitmask = 0; |  | ||||||
|         if (tile.hasWallAt(Direction.TOP)) { |  | ||||||
|             bitmask |= TOP_BIT; |  | ||||||
|         } |  | ||||||
|         if (tile.hasWallAt(Direction.RIGHT)) { |  | ||||||
|             bitmask |= RIGHT_BIT; |  | ||||||
|         } |  | ||||||
|         if (tile.hasWallAt(Direction.BOTTOM)) { |  | ||||||
|             bitmask |= BOTTOM_BIT; |  | ||||||
|         } |  | ||||||
|         if (tile.hasWallAt((Direction.LEFT))) { |  | ||||||
|             bitmask |= LEFT_BIT; |  | ||||||
|         } |  | ||||||
|         if (tile.isSolution()) { |  | ||||||
|             bitmask |= SOLUTION_BIT; |  | ||||||
|         } |  | ||||||
|         return bitmask; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @NotNull |  | ||||||
|     Tile getTileForBitmask(final byte bitmask) { |  | ||||||
|         final EnumSet<Direction> walls = EnumSet.noneOf(Direction.class); |  | ||||||
|         if ((bitmask & TOP_BIT) == TOP_BIT) { |  | ||||||
|             walls.add(Direction.TOP); |  | ||||||
|         } |  | ||||||
|         if ((bitmask & RIGHT_BIT) == RIGHT_BIT) { |  | ||||||
|             walls.add(Direction.RIGHT); |  | ||||||
|         } |  | ||||||
|         if ((bitmask & BOTTOM_BIT) == BOTTOM_BIT) { |  | ||||||
|             walls.add(Direction.BOTTOM); |  | ||||||
|         } |  | ||||||
|         if ((bitmask & LEFT_BIT) == LEFT_BIT) { |  | ||||||
|             walls.add(Direction.LEFT); |  | ||||||
|         } |  | ||||||
|         final boolean solution = (bitmask & SOLUTION_BIT) == SOLUTION_BIT; |  | ||||||
|         return createTile(walls, solution); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue