diff --git a/src/main/java/controller/MainPaneController.java b/src/main/java/controller/MainPaneController.java index e59c215b8c8729c4cf4fd290c94de0b34e3b6374..6653ae48637f84f6e4915aeeef1c773d670202e0 100644 --- a/src/main/java/controller/MainPaneController.java +++ b/src/main/java/controller/MainPaneController.java @@ -10,11 +10,6 @@ public class MainPaneController { private MainApp mainApp; - /** - * Is called by the main application to give a reference back to itself. - * - * @param mainApp the main app - */ public void initializeGrid() { gridTileCanvas.initializeGrid(); } diff --git a/src/main/java/main/MainApp.java b/src/main/java/main/MainApp.java index 4a725ba2a47bbfa6121965e21acd933c710fc21c..bc106af65c0aacb0cffd24d60c170006644a69aa 100644 --- a/src/main/java/main/MainApp.java +++ b/src/main/java/main/MainApp.java @@ -7,8 +7,6 @@ import javafx.scene.Scene; import javafx.scene.layout.AnchorPane; import javafx.stage.Stage; -import model.TileGame; -import view.GridTileCanvas; import java.io.IOException; @@ -16,7 +14,6 @@ public class MainApp extends Application { private Stage primaryStage; private AnchorPane rootLayout; - private TileGame tileGame = new TileGame(); public MainApp() { } diff --git a/src/main/java/view/PointType.java b/src/main/java/model/PointType.java similarity index 74% rename from src/main/java/view/PointType.java rename to src/main/java/model/PointType.java index 1cefc71734fbe739711239e9047111d2e072a1ca..6cdd79f7211293259fb3f0f078b28d02a9d8f47b 100644 --- a/src/main/java/view/PointType.java +++ b/src/main/java/model/PointType.java @@ -1,6 +1,4 @@ -package view; - -import model.CardinalDirection; +package model; import java.util.List; @@ -18,12 +16,12 @@ public enum PointType { this.yPosition = yPosition; } - static public List<PointType> getIncidentCornerTypes(CardinalDirection side){ + static public List<PointType> trianglePointTypes(CardinalDirection side){ return switch (side){ - case NORTH -> List.of(PointType.NORTH_WEST_CORNER, PointType.NORTH_EAST_CORNER); - case EAST -> List.of(PointType.NORTH_EAST_CORNER, PointType.SOUTH_EAST_CORNER); - case SOUTH -> List.of(PointType.SOUTH_EAST_CORNER, PointType.SOUTH_WEST_CORNER); - case WEST -> List.of(PointType.NORTH_WEST_CORNER, PointType.SOUTH_WEST_CORNER); + case NORTH -> List.of(PointType.NORTH_WEST_CORNER, PointType.NORTH_EAST_CORNER, PointType.CENTER); + case EAST -> List.of(PointType.NORTH_EAST_CORNER, PointType.SOUTH_EAST_CORNER, PointType.CENTER); + case SOUTH -> List.of(PointType.SOUTH_EAST_CORNER, PointType.SOUTH_WEST_CORNER, PointType.CENTER); + case WEST -> List.of(PointType.NORTH_WEST_CORNER, PointType.SOUTH_WEST_CORNER, PointType.CENTER); }; } diff --git a/src/main/java/model/RandomTileGenerator.java b/src/main/java/model/RandomTileGenerator.java deleted file mode 100644 index 7f21231790e7571e13cd33038ddfaf7e64ebcc76..0000000000000000000000000000000000000000 --- a/src/main/java/model/RandomTileGenerator.java +++ /dev/null @@ -1,44 +0,0 @@ -package model; - -import javafx.scene.paint.Color; - -import java.util.List; -import java.util.Random; - -public class RandomTileGenerator { - private final List<Color> colors; - private final Random randomGenerator; - - public RandomTileGenerator(List<Color> colors, Random randomGenerator) { - this.colors = colors; - this.randomGenerator = randomGenerator; - } - - private Color randomColor(){ - return colors.get(randomGenerator.nextInt(colors.size())); - } - - public Tile nextTile(){ - Color[] colorsOfTile = new Color[4]; - for(int index = 0; index < 4; index++) - colorsOfTile[index] = randomColor(); - return new Tile(colorsOfTile); - } - - public Tile nextUniformTile(){ - Color[] colorsOfTile = new Color[4]; - Color randomColor = randomColor(); - for(int index = 0; index < 4; index++) - colorsOfTile[index] = randomColor; - return new Tile(colorsOfTile); - } - - public Tile nextTileWithColorConstraint(Square square){ - Color[] colorsOfTile = new Color[4]; - for(CardinalDirection side : CardinalDirection.values()){ - colorsOfTile[side.ordinal()] = square.getColorConstraint(side).orElse(randomColor()); - } - return new Tile(colorsOfTile); - } - -} diff --git a/src/main/java/model/RandomWangTileGenerator.java b/src/main/java/model/RandomWangTileGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..e47a62bd2efb62332bd4c94415921e32ee8d38c3 --- /dev/null +++ b/src/main/java/model/RandomWangTileGenerator.java @@ -0,0 +1,53 @@ +package model; + +import javafx.scene.paint.Color; + +import java.util.List; +import java.util.Optional; +import java.util.Random; + +public class RandomWangTileGenerator implements SquareTileGenerator{ + + private final List<Color> colors; + private final Random randomGenerator; + + public RandomWangTileGenerator(List<Color> colors, Random randomGenerator) { + this.colors = colors; + this.randomGenerator = randomGenerator; + } + + private Color randomColor(){ + return colors.get(randomGenerator.nextInt(colors.size())); + } + + public WangTile nextTile(){ + Color[] colorsOfTile = new Color[4]; + for(int index = 0; index < 4; index++) + colorsOfTile[index] = randomColor(); + return new WangTile(colorsOfTile); + } + + public WangTile nextUniformTile(){ + Color[] colorsOfTile = new Color[4]; + Color randomColor = randomColor(); + for(int index = 0; index < 4; index++) + colorsOfTile[index] = randomColor; + return new WangTile(colorsOfTile); + } + @Override + public SquareTile nextTileWithNeighborhoodConstraint(Square square) { + Color[] colorsOfTile = new Color[4]; + for(CardinalDirection side : CardinalDirection.values()){ + Optional<SquareTile> optionalSquareTile = square.getNeighboringSquare(side); + if(optionalSquareTile.isPresent()){ + SquareTile neighboringSquareTile = optionalSquareTile.get(); + colorsOfTile[side.ordinal()] = neighboringSquareTile.getSideColor(side.oppositeDirection()); + } + else { + colorsOfTile[side.ordinal()] = randomColor(); + } + } + return new WangTile(colorsOfTile); + } + +} diff --git a/src/main/java/model/RotationType.java b/src/main/java/model/RotationType.java new file mode 100644 index 0000000000000000000000000000000000000000..bb496329f41b79c57e6c8a70162c4650ed3231ce --- /dev/null +++ b/src/main/java/model/RotationType.java @@ -0,0 +1,5 @@ +package model; + +public enum RotationType { + NO_TURN, QUARTER_TURN, HALF_TURN, THREE_QUARTER_TURN +} diff --git a/src/main/java/model/Square.java b/src/main/java/model/Square.java index 060679133086fb1e37326ea7eddd2680e667018a..b22b0547b42508c9af001a627ef0aa2189a4ddd8 100644 --- a/src/main/java/model/Square.java +++ b/src/main/java/model/Square.java @@ -1,48 +1,39 @@ package model; -import javafx.scene.paint.Color; - -import java.util.NoSuchElementException; import java.util.Optional; public class Square { - private Tile tile; + private SquareTile squareTile; private Square[] neighboringSquares; - private Square(Tile tile, Square[] neighboringSquares) { - this.tile = tile; + private Square(SquareTile squareTile, Square[] neighboringSquares) { + this.squareTile = squareTile; this.neighboringSquares = neighboringSquares; } - public Square(Square[] neighboringSquares) { - this(null, neighboringSquares); - } public Square(){ this(null, null); } - public Tile getTile(){ - if(tile == null) - throw new NoSuchElementException(); - return tile; + public Optional<SquareTile> getSquareTile(){ + if(!hasTile()) + return Optional.empty(); + return Optional.of(squareTile); } - public void add(Tile tile) { - this.tile = tile; + public void add(SquareTile tile) { + this.squareTile = tile; } public boolean hasTile() { - return tile != null; + return squareTile != null; } - public Optional<Color> getColorConstraint(CardinalDirection side) { - if (neighboringSquares == null) - throw new NoSuchElementException(); - Square neighboringSquare = neighboringSquares[side.ordinal()]; - if(!neighboringSquare.hasTile()) + public Optional<SquareTile> getNeighboringSquare(CardinalDirection side) { + if (neighboringSquares == null || neighboringSquares[side.ordinal()] == null) return Optional.empty(); - return Optional.of(neighboringSquare.getTile().getColor(side.oppositeDirection())); + return neighboringSquares[side.ordinal()].getSquareTile(); } public void setNeighboringSquares(Square[] neighboringSquares) { diff --git a/src/main/java/model/SquareGrid.java b/src/main/java/model/SquareGrid.java index 8175c5db1e430ba68f6a557a0902b9094aa20551..32fa4d9980e3a2ff4a39cc54b8c6036247c7f9f7 100644 --- a/src/main/java/model/SquareGrid.java +++ b/src/main/java/model/SquareGrid.java @@ -4,6 +4,7 @@ import javafx.scene.paint.Color; import java.util.Iterator; import java.util.List; +import java.util.Optional; import java.util.Random; public class SquareGrid implements Iterable<Square> { @@ -60,8 +61,8 @@ public class SquareGrid implements Iterable<Square> { return new BorderSquareIterator(this); } - public Tile getTile(int rowIndex, int columnIndex) { - return getSquare(rowIndex, columnIndex).getTile(); + public Optional<SquareTile> getTile(int rowIndex, int columnIndex) { + return getSquare(rowIndex, columnIndex).getSquareTile(); } public Square getSquare(int rowIndex, int columnIndex) { @@ -76,10 +77,10 @@ public class SquareGrid implements Iterable<Square> { } public void fillWithRandomTiles(List<Color> colors, Random randomGenerator){ - RandomTileGenerator randomTileGenerator = new RandomTileGenerator(colors, randomGenerator); + RandomWangTileGenerator randomTileGenerator = new RandomWangTileGenerator(colors, randomGenerator); borderSquareIterator().forEachRemaining(square -> square.add(randomTileGenerator.nextUniformTile())); - internalSquareIterator().forEachRemaining(square -> square.add(randomTileGenerator.nextTileWithColorConstraint(square))); + internalSquareIterator().forEachRemaining(square -> square.add(randomTileGenerator.nextTileWithNeighborhoodConstraint(square))); } public boolean hasTile(int row, int column) { diff --git a/src/main/java/model/SquareTile.java b/src/main/java/model/SquareTile.java new file mode 100644 index 0000000000000000000000000000000000000000..1165fcd417fd3245a927795c87aa897bc1e007dc --- /dev/null +++ b/src/main/java/model/SquareTile.java @@ -0,0 +1,11 @@ +package model; + +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; + +public interface SquareTile { + void draw(GraphicsContext graphicsContext, double x, double y, double width, double height); + boolean isCompatibleWith(SquareTile neighbor, CardinalDirection side); + SquareTile rotation(RotationType rotation); + Color getSideColor(CardinalDirection side); +} diff --git a/src/main/java/model/SquareTileGenerator.java b/src/main/java/model/SquareTileGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..2baf21871352b93021e6a9258997f27904dd3444 --- /dev/null +++ b/src/main/java/model/SquareTileGenerator.java @@ -0,0 +1,7 @@ +package model; + +public interface SquareTileGenerator { + SquareTile nextTile(); + SquareTile nextTileWithNeighborhoodConstraint(Square square); + SquareTile nextUniformTile(); +} diff --git a/src/main/java/model/Tile.java b/src/main/java/model/Tile.java deleted file mode 100644 index 5880b936ca8a83b34a47d71736e9b6f4cf9f77fa..0000000000000000000000000000000000000000 --- a/src/main/java/model/Tile.java +++ /dev/null @@ -1,36 +0,0 @@ -package model; - -import javafx.scene.paint.Color; - -import java.util.Arrays; -import java.util.HashMap; - -public class Tile { - private static final int NUMBER_OF_SIDES = 4; - private final Color colors[] = new Color[NUMBER_OF_SIDES]; - - public Tile(Color[] colors) { - if(colors.length != NUMBER_OF_SIDES) - throw new IllegalArgumentException("A tile is defined by " + NUMBER_OF_SIDES - + "and not" + colors.length + "sides."); - for(int index = 0; index < NUMBER_OF_SIDES; index++) - this.colors[index] = colors[index]; - } - - public Color getColor(CardinalDirection direction){ - return colors[direction.ordinal()]; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Tile tile = (Tile) o; - return Arrays.equals(colors, tile.colors); - } - - @Override - public int hashCode() { - return Arrays.hashCode(colors); - } -} diff --git a/src/main/java/model/TileGame.java b/src/main/java/model/TileGame.java deleted file mode 100644 index b893dc20b57ec25021ea269a4dc53956a75bd01e..0000000000000000000000000000000000000000 --- a/src/main/java/model/TileGame.java +++ /dev/null @@ -1,22 +0,0 @@ -package model; - -import javafx.scene.paint.Color; - -import java.util.List; -import java.util.Random; - -public class TileGame { - private final SquareGrid tileGrid; - - public TileGame(SquareGrid tileGrid) { - this.tileGrid = tileGrid; - tileGrid.fillWithRandomTiles(List.of(Color.BLUE, Color.WHITE, Color.BLACK, Color.RED), new Random()); - } - public TileGame() { - this(new SquareGrid(10, 10)); - } - - public SquareGrid getTileGrid() { - return tileGrid; - } -} diff --git a/src/main/java/model/WangTile.java b/src/main/java/model/WangTile.java new file mode 100644 index 0000000000000000000000000000000000000000..552feb2713d6d588ff4c703761b2779d52b9f6e3 --- /dev/null +++ b/src/main/java/model/WangTile.java @@ -0,0 +1,66 @@ +package model; + +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.paint.Color; + +import java.util.Arrays; +import java.util.List; + +public class WangTile implements SquareTile { + private static final int NUMBER_OF_SIDES = 4; + private final Color[] colors = new Color[NUMBER_OF_SIDES]; + + public WangTile(Color[] colors) { + if(colors.length != NUMBER_OF_SIDES) + throw new IllegalArgumentException("A tile is defined by " + NUMBER_OF_SIDES + + "and not" + colors.length + "sides."); + System.arraycopy(colors, 0, this.colors, 0, NUMBER_OF_SIDES); + } + + public Color getSideColor(CardinalDirection direction){ + return colors[direction.ordinal()]; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + WangTile tile = (WangTile) o; + return Arrays.equals(colors, tile.colors); + } + + @Override + public int hashCode() { + return Arrays.hashCode(colors); + } + + @Override + public void draw(GraphicsContext graphicsContext, double x, double y, double width, double height) { + for(CardinalDirection side: CardinalDirection.values()){ + drawSideTriangle(graphicsContext, x, y, width, height, side); + } + } + + @Override + public boolean isCompatibleWith(SquareTile neighbor, CardinalDirection side) { + return false; + } + + @Override + public SquareTile rotation(RotationType rotation) { + return null; + } + + private void drawSideTriangle(GraphicsContext graphicsContext, double x, double y, double width, double height, + CardinalDirection side){ + List<PointType> cornerTypes = PointType.trianglePointTypes(side); + double[] xPoints = new double[3]; + double[] yPoints = new double[3]; + for(int index = 0; index < 3; index++){ + xPoints[index] = x + (cornerTypes.get(index).getXPosition() * width); + yPoints[index] = y + (cornerTypes.get(index).getYPosition() * height); + } + graphicsContext.setFill(getSideColor(side)); + graphicsContext.fillPolygon(xPoints, yPoints, 3); + } +} diff --git a/src/main/java/view/GridTileCanvas.java b/src/main/java/view/GridTileCanvas.java index 36a1995d43e135fcfba8f3e3d18946637cb66057..58679194e110fe39635a341a0c1fe8d1cf226752 100644 --- a/src/main/java/view/GridTileCanvas.java +++ b/src/main/java/view/GridTileCanvas.java @@ -4,17 +4,18 @@ import javafx.beans.NamedArg; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.paint.Color; -import model.CardinalDirection; -import model.SquareGrid; -import model.Tile; +import model.*; import java.util.List; +import java.util.Optional; import java.util.Random; public class GridTileCanvas extends Canvas { public final double tileWidth; private final double tileHeight; + private final Integer numberOfColumns; + private final Integer numberOfRows; private final SquareGrid tileGrid; public GridTileCanvas(@NamedArg("tileWidth") Double tileWidth, @@ -23,6 +24,8 @@ public class GridTileCanvas extends Canvas { @NamedArg("numberOfRows") Integer numberOfRows) { this.tileWidth = tileWidth; this.tileHeight = tileHeight; + this.numberOfColumns = numberOfColumns; + this.numberOfRows = numberOfRows; this.setWidth(tileWidth * numberOfColumns); this.setHeight(tileHeight * numberOfRows); tileGrid = new SquareGrid(numberOfRows, numberOfColumns); @@ -34,39 +37,13 @@ public class GridTileCanvas extends Canvas { } public void drawGridTile(SquareGrid tileGrid){ - for(int row = 0; row < tileGrid.getNumberOfRows(); row++) - for(int column = 0; column < tileGrid.getNumberOfColumns(); column++){ - if(tileGrid.hasTile(row, column)) - drawTile(tileGrid.getTile(row, column), column, row); - } - } - - public void drawTile(Tile tile, int row, int column){ - for(CardinalDirection cardinalDirection: CardinalDirection.values()){ - drawTriangle(column, row, cardinalDirection, tile.getColor(cardinalDirection)); - } - } - - private double getXPosition(int column, PointType pointType){ - return (column + pointType.getXPosition()) * tileWidth; - } - private double getYPosition(int row, PointType pointType){ - return (row + pointType.getYPosition()) * tileHeight; - } - - private void drawTriangle(int row, int column, CardinalDirection side, Color color){ - List<PointType> cornerTypes = PointType.getIncidentCornerTypes(side); - double[] xPoints = new double[3]; - double[] yPoints = new double[3]; - for(int index = 0; index < 2; index++){ - xPoints[index] = getXPosition(column, cornerTypes.get(index)); - yPoints[index] = getYPosition(row, cornerTypes.get(index)); - } - xPoints[2] = getXPosition(column, PointType.CENTER); - yPoints[2] = getYPosition(row, PointType.CENTER); GraphicsContext graphicsContext = getGraphicsContext2D(); - graphicsContext.setFill(color); - graphicsContext.fillPolygon(xPoints, yPoints, 3); + for(int row = 0; row < numberOfRows; row++) + for(int column = 0; column < numberOfColumns; column++){ + Optional<SquareTile> tile = tileGrid.getTile(row, column); + if(tile.isPresent()) + tile.get().draw(graphicsContext, column * tileWidth, + row * tileHeight, tileWidth, tileHeight); + } } - } diff --git a/src/test/java/model/TileTest.java b/src/test/java/model/TileTest.java index fab7b94044b452f2af77c60237c8e67254b1525c..074d8ea61694e818b59db02e37ebb50db40876b4 100644 --- a/src/test/java/model/TileTest.java +++ b/src/test/java/model/TileTest.java @@ -7,20 +7,20 @@ import static org.assertj.core.api.Assertions.assertThat; public class TileTest { @Test void testGetColor(){ - Tile tile = new Tile(new Color[]{Color.BLACK, Color.BLUE, Color.WHITE, Color.BLUE}); - assertThat(tile.getColor(CardinalDirection.NORTH)).isEqualTo(Color.BLACK); - assertThat(tile.getColor(CardinalDirection.EAST)).isEqualTo(Color.BLUE); - assertThat(tile.getColor(CardinalDirection.SOUTH)).isEqualTo(Color.WHITE); - assertThat(tile.getColor(CardinalDirection.WEST)).isEqualTo(Color.BLUE); + WangTile tile = new WangTile(new Color[]{Color.BLACK, Color.BLUE, Color.WHITE, Color.BLUE}); + assertThat(tile.getSideColor(CardinalDirection.NORTH)).isEqualTo(Color.BLACK); + assertThat(tile.getSideColor(CardinalDirection.EAST)).isEqualTo(Color.BLUE); + assertThat(tile.getSideColor(CardinalDirection.SOUTH)).isEqualTo(Color.WHITE); + assertThat(tile.getSideColor(CardinalDirection.WEST)).isEqualTo(Color.BLUE); } @Test void testEquals(){ Color[] colors1 = new Color[]{Color.BLACK, Color.BLUE, Color.WHITE, Color.BLUE}; Color[] colors2 = new Color[]{Color.BLACK, Color.BLUE, Color.WHITE, Color.WHITE}; - Tile tile1 = new Tile(colors1); - Tile tile2 = new Tile(colors1); - Tile tile3 = new Tile(colors2); + WangTile tile1 = new WangTile(colors1); + WangTile tile2 = new WangTile(colors1); + WangTile tile3 = new WangTile(colors2); assertThat(tile1) .isEqualTo(tile1) .isEqualTo(tile2)