Skip to content
Snippets Groups Projects
Commit 65c97d6e authored by LABOUREL Arnaud's avatar LABOUREL Arnaud
Browse files

Prepare the code to define different types of tiles.

parent 92ed70fa
No related branches found
No related tags found
No related merge requests found
Showing with 187 additions and 108 deletions
......@@ -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();
}
......
......@@ -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() {
}
......
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);
};
}
......
......@@ -3,13 +3,15 @@ package model;
import javafx.scene.paint.Color;
import java.util.List;
import java.util.Optional;
import java.util.Random;
public class RandomTileGenerator {
public class RandomWangTileGenerator implements SquareTileGenerator{
private final List<Color> colors;
private final Random randomGenerator;
public RandomTileGenerator(List<Color> colors, Random randomGenerator) {
public RandomWangTileGenerator(List<Color> colors, Random randomGenerator) {
this.colors = colors;
this.randomGenerator = randomGenerator;
}
......@@ -18,27 +20,34 @@ public class RandomTileGenerator {
return colors.get(randomGenerator.nextInt(colors.size()));
}
public Tile nextTile(){
public WangTile nextTile(){
Color[] colorsOfTile = new Color[4];
for(int index = 0; index < 4; index++)
colorsOfTile[index] = randomColor();
return new Tile(colorsOfTile);
return new WangTile(colorsOfTile);
}
public Tile nextUniformTile(){
public WangTile nextUniformTile(){
Color[] colorsOfTile = new Color[4];
Color randomColor = randomColor();
for(int index = 0; index < 4; index++)
colorsOfTile[index] = randomColor;
return new Tile(colorsOfTile);
return new WangTile(colorsOfTile);
}
public Tile nextTileWithColorConstraint(Square square){
@Override
public SquareTile nextTileWithNeighborhoodConstraint(Square square) {
Color[] colorsOfTile = new Color[4];
for(CardinalDirection side : CardinalDirection.values()){
colorsOfTile[side.ordinal()] = square.getColorConstraint(side).orElse(randomColor());
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 Tile(colorsOfTile);
return new WangTile(colorsOfTile);
}
}
package model;
public enum RotationType {
NO_TURN, QUARTER_TURN, HALF_TURN, THREE_QUARTER_TURN
}
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) {
......
......@@ -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) {
......
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);
}
package model;
public interface SquareTileGenerator {
SquareTile nextTile();
SquareTile nextTileWithNeighborhoodConstraint(Square square);
SquareTile nextUniformTile();
}
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;
}
}
package model;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public class Tile {
public class WangTile implements SquareTile {
private static final int NUMBER_OF_SIDES = 4;
private final Color colors[] = new Color[NUMBER_OF_SIDES];
private final Color[] colors = new Color[NUMBER_OF_SIDES];
public Tile(Color[] colors) {
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.");
for(int index = 0; index < NUMBER_OF_SIDES; index++)
this.colors[index] = colors[index];
System.arraycopy(colors, 0, this.colors, 0, NUMBER_OF_SIDES);
}
public Color getColor(CardinalDirection direction){
public Color getSideColor(CardinalDirection direction){
return colors[direction.ordinal()];
}
......@@ -25,7 +25,7 @@ public class Tile {
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Tile tile = (Tile) o;
WangTile tile = (WangTile) o;
return Arrays.equals(colors, tile.colors);
}
......@@ -33,4 +33,34 @@ public class Tile {
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);
}
}
......@@ -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);
}
}
}
......@@ -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)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment