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

Version quasi-définitive

parent 544ea43d
No related branches found
No related tags found
No related merge requests found
Showing
with 338 additions and 148 deletions
...@@ -13,9 +13,9 @@ repositories { ...@@ -13,9 +13,9 @@ repositories {
} }
dependencies { dependencies {
testImplementation('org.junit.jupiter:junit-jupiter-api:5.8.0', testImplementation('org.junit.jupiter:junit-jupiter-api:5.8.1',
'org.assertj:assertj-core:3.20.2') 'org.assertj:assertj-core:3.21.0')
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
} }
test { test {
......
...@@ -2,7 +2,10 @@ package controller; ...@@ -2,7 +2,10 @@ package controller;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import model.RandomWangConstrainedTileGenerator; import model.ConstrainedRotatedTruchetTileGenerator;
import model.RandomConstrainedWangTileGenerator;
import model.RandomRotatedTruchetTileGenerator;
import model.RandomWangTileGenerator;
import view.GridTileCanvas; import view.GridTileCanvas;
import java.util.List; import java.util.List;
...@@ -13,8 +16,10 @@ public class GridController { ...@@ -13,8 +16,10 @@ public class GridController {
public GridTileCanvas gridTileCanvas; public GridTileCanvas gridTileCanvas;
public void initialize() { public void initialize() {
gridTileCanvas.initializeGrid(new RandomWangConstrainedTileGenerator(List.of(Color.BLUE, Color.RED, Color.BLACK, Color.GREEN), //gridTileCanvas.initializeGrid(new RandomConstrainedWangTileGenerator(List.of(Color.BLUE, Color.RED, Color.BLACK, Color.GREEN),new Random(0)));
new Random(0))); //gridTileCanvas.initializeGrid(new RandomWangTileGenerator(List.of(Color.BLUE, Color.RED, Color.BLACK, Color.GREEN),new Random(0)));
//gridTileCanvas.initializeGrid(new RandomRotatedTruchetTileGenerator(Color.BLUE, Color.RED, new Random(0)));
gridTileCanvas.initializeGrid(new ConstrainedRotatedTruchetTileGenerator(Color.BLUE, Color.RED));
} }
public void draw() { public void draw() {
gridTileCanvas.drawGrid(); gridTileCanvas.drawGrid();
......
package model;
import java.util.List;
public class ArraySquare implements Square {
private static final Tile EMPTY_TILE = new UniformTile(EmptySide.EMPTY_SIDE);
private static final Square EMPTY_SQUARE = new ArraySquare();
private Tile tile = EMPTY_TILE;
private final Square[] neighborhood = new Square[CardinalDirection.NUMBER_OF_DIRECTIONS];
public ArraySquare() {
setEmptyNeighborhood();
}
private void setEmptyNeighborhood(){
for(CardinalDirection direction : CardinalDirection.values())
setNeighbor(EMPTY_SQUARE, direction);
}
public Tile getTile(){
return tile;
}
public void put(Tile tile) {
this.tile = tile;
}
public void setNeighbor(Square neighbor, CardinalDirection direction) {
this.neighborhood[direction.ordinal()] = neighbor;
}
public Square getNeighbor(CardinalDirection direction) {
return this.neighborhood[direction.ordinal()];
}
@Override
public boolean accept(Tile tile) {
for(CardinalDirection direction : CardinalDirection.values()){
if(!accept(tile, direction))
return false;
}
return true;
}
public boolean accept(Tile tile, CardinalDirection direction) {
return getIncidentNeighboringSide(direction).accept(tile.side(direction));
}
private Side getIncidentNeighboringSide(CardinalDirection direction) {
return getNeighbor(direction).getTile().side(direction.oppositeDirection());
}
@Override
public List<Side> compatibleSides(List<Side> sides, CardinalDirection direction) {
return getIncidentNeighboringSide(direction).compatibleSides(sides);
}
}
package model;
import javafx.scene.paint.Color;
public class ConstrainedRotatedTruchetTileGenerator implements TileGenerator{
private final Tile truchetTile;
public ConstrainedRotatedTruchetTileGenerator(Color color1, Color color2) {
this.truchetTile = new TruchetTile(new InternalSide(color1), new InternalSide(color2));
}
@Override
public Tile nextTile(Square square) {
for(Rotation rotation : Rotation.values()) {
Tile rotatedTile = new RotatedTile(truchetTile, rotation);
if(square.accept(rotatedTile)){
return rotatedTile;
}
}
return new UniformTile(EmptySide.EMPTY_SIDE);
}
}
package model;
import javafx.scene.paint.Color;
import java.util.List;
public class EmptySide implements Side {
public static final Side EMPTY_SIDE = new EmptySide();
private EmptySide(){}
@Override
public boolean accept(Side side) {
return true;
}
@Override
public List<Side> compatibleSides(List<Side> sides) {
return sides;
}
@Override
public Color color() {
return Color.WHITE;
}
}
package model; package model;
import java.util.Iterator; import java.util.Iterator;
import java.util.Optional;
public class Grid implements Iterable<Square> { public class Grid implements Iterable<Square> {
private final int numberOfRows; private final int numberOfRows;
private final int numberOfColumns; private final int numberOfColumns;
private final Square[][] squares; private final Square[][] squares;
private final Square outOfGridSquare = new ArraySquare();
/** /**
* Creates a new {@code Grid} instance given the number of rows and columns. * Creates a new {@code Grid} instance given the number of rows and columns.
* *
...@@ -22,7 +21,7 @@ public class Grid implements Iterable<Square> { ...@@ -22,7 +21,7 @@ public class Grid implements Iterable<Square> {
throw new IllegalArgumentException("The number of columns must be positive and not equal to " + numberOfColumns); throw new IllegalArgumentException("The number of columns must be positive and not equal to " + numberOfColumns);
this.numberOfRows = numberOfRows; this.numberOfRows = numberOfRows;
this.numberOfColumns = numberOfColumns; this.numberOfColumns = numberOfColumns;
squares = new Square[getNumberOfRows()][getNumberOfColumns()]; squares = new ArraySquare[getNumberOfRows()][getNumberOfColumns()];
initializeGrid(); initializeGrid();
} }
...@@ -34,7 +33,7 @@ public class Grid implements Iterable<Square> { ...@@ -34,7 +33,7 @@ public class Grid implements Iterable<Square> {
private void initializeSquares() { private void initializeSquares() {
for(int row = 0; row < getNumberOfRows(); row++) for(int row = 0; row < getNumberOfRows(); row++)
for(int column = 0; column < getNumberOfColumns(); column++) for(int column = 0; column < getNumberOfColumns(); column++)
squares[row][column] = new Square(); squares[row][column] = new ArraySquare();
} }
private void initializeNeighborhood() { private void initializeNeighborhood() {
...@@ -43,8 +42,9 @@ public class Grid implements Iterable<Square> { ...@@ -43,8 +42,9 @@ public class Grid implements Iterable<Square> {
for (CardinalDirection direction : CardinalDirection.values()){ for (CardinalDirection direction : CardinalDirection.values()){
int rowNeighbor = row + direction.deltaRow; int rowNeighbor = row + direction.deltaRow;
int columnNeighbor = column + direction.deltaColumn; int columnNeighbor = column + direction.deltaColumn;
if(containsCoordinates(rowNeighbor, columnNeighbor)) Square neighboringSquare =
squares[row][column].setNeighboringSquare(squares[rowNeighbor][columnNeighbor], direction); containsCoordinates(rowNeighbor, columnNeighbor) ? getSquare(rowNeighbor, columnNeighbor) : outOfGridSquare;
getSquare(row, column).setNeighbor(neighboringSquare, direction);
} }
} }
} }
...@@ -63,10 +63,6 @@ public class Grid implements Iterable<Square> { ...@@ -63,10 +63,6 @@ public class Grid implements Iterable<Square> {
return new SquareIterator(this); return new SquareIterator(this);
} }
public Optional<Tile> getTile(int rowIndex, int columnIndex) {
return getSquare(rowIndex, columnIndex).getSquareTile();
}
public Square getSquare(int rowIndex, int columnIndex) { public Square getSquare(int rowIndex, int columnIndex) {
return squares[rowIndex][columnIndex]; return squares[rowIndex][columnIndex];
} }
...@@ -81,10 +77,6 @@ public class Grid implements Iterable<Square> { ...@@ -81,10 +77,6 @@ public class Grid implements Iterable<Square> {
public void fill(TileGenerator tileGenerator){ public void fill(TileGenerator tileGenerator){
for(Square square : this) for(Square square : this)
square.add(tileGenerator.nextTile(square)); square.put(tileGenerator.nextTile(square));
}
public boolean hasTile(int row, int column) {
return getSquare(row, column).hasTile();
} }
} }
package model;
import javafx.scene.paint.Color;
import java.util.ArrayList;
import java.util.List;
public class InternalSide implements Side {
private final Color color;
public InternalSide(Color color) {
this.color = color;
}
@Override
public boolean accept(Side side) {
return color.equals(side.color());
}
@Override
public List<Side> compatibleSides(List<Side> sides) {
List<Side> filteredSides = new ArrayList<>();
for(Side side : sides){
if(this.accept(side)){
filteredSides.add(side);
}
}
return filteredSides;
}
@Override
public Color color() {
return color;
}
}
package model;
import javafx.scene.paint.Color;
import util.RandomUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class RandomConstrainedWangTileGenerator implements TileGenerator {
private final List<Side> availableSides = new ArrayList<>();
private final Random randomGenerator;
public RandomConstrainedWangTileGenerator(List<Color> colors, Random randomGenerator) {
for(Color color : colors)
this.availableSides.add(new InternalSide(color));
this.randomGenerator = randomGenerator;
}
@Override
public Tile nextTile(Square square) {
Side[] sidesOfTile = new Side[CardinalDirection.NUMBER_OF_DIRECTIONS];
for(CardinalDirection direction : CardinalDirection.values()){
List<Side> compatibleSides = square.compatibleSides(availableSides, direction);
sidesOfTile[direction.ordinal()] = RandomUtil.randomElement(compatibleSides, randomGenerator);
}
return new WangTile(sidesOfTile);
}
}
package model;
import javafx.scene.paint.Color;
import util.RandomUtil;
import java.util.Random;
public class RandomRotatedTruchetTileGenerator implements TileGenerator{
private final Random randomGenerator;
private final Tile truchetTile;
public RandomRotatedTruchetTileGenerator(Color color1, Color color2, Random randomGenerator) {
this.randomGenerator = randomGenerator;
this.truchetTile = new TruchetTile(new InternalSide(color1), new InternalSide(color2));
}
@Override
public Tile nextTile(Square square) {
Rotation randomRotation = RandomUtil.randomElement(Rotation.values(), randomGenerator);
return new RotatedTile(truchetTile, randomRotation);
}
}
package model;
import javafx.scene.paint.Color;
import util.RandomUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class RandomUniformTileGenerator implements TileGenerator{
private final List<Side> colors = new ArrayList<>();
private final Random randomGenerator;
public RandomUniformTileGenerator(List<Color> colors, Random randomGenerator) {
for(Color color : colors)
this.colors.add(new InternalSide(color));
this.randomGenerator = randomGenerator;
}
@Override
public Tile nextTile(Square square) {
return new UniformTile(RandomUtil.randomElement(colors, randomGenerator));
}
}
package model;
import javafx.scene.paint.Color;
import java.util.List;
import java.util.Optional;
import java.util.Random;
public class RandomWangConstrainedTileGenerator implements TileGenerator {
private final List<Color> colors;
private final Random randomGenerator;
public RandomWangConstrainedTileGenerator(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 Tile nextTile(Square square) {
Color[] colorsOfTile = new Color[4];
for(CardinalDirection side : CardinalDirection.values()){
Optional<Tile> optionalSquareTile = square.getNeighboringSquare(side);
if(optionalSquareTile.isPresent()){
Tile neighboringTile = optionalSquareTile.get();
colorsOfTile[side.ordinal()] = neighboringTile.getSideColor(side.oppositeDirection());
}
else {
colorsOfTile[side.ordinal()] = randomColor();
}
}
return new WangTile(colorsOfTile);
}
}
package model;
import javafx.scene.paint.Color;
import util.RandomUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class RandomWangTileGenerator implements TileGenerator{
private final List<Side> availableSides = new ArrayList<>();
private final Random randomGenerator;
public RandomWangTileGenerator(List<Color> colors, Random randomGenerator) {
for(Color color : colors)
this.availableSides.add(new InternalSide(color));
this.randomGenerator = randomGenerator;
}
@Override
public Tile nextTile(Square square) {
Side[] sidesOfTile = new Side[CardinalDirection.NUMBER_OF_DIRECTIONS];
for(CardinalDirection direction : CardinalDirection.values()){
sidesOfTile[direction.ordinal()] = RandomUtil.randomElement(availableSides, randomGenerator);
}
return new WangTile(sidesOfTile);
}
}
package model; package model;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
public class RotatedTile implements Tile { public class RotatedTile implements Tile {
private final Tile tile;
private final Rotation rotationType;
public RotatedTile(Tile tile, Rotation rotationType) {
@Override this.tile = tile;
public boolean isCompatibleWith(Tile neighbor, CardinalDirection side) { this.rotationType = rotationType;
return false;
}
@Override
public Tile rotation(RotationType rotation) {
return null;
} }
@Override @Override
public Color getSideColor(CardinalDirection side) { public Side side(CardinalDirection direction) {
return null; return tile.side(rotationType.rotatedDirection(direction));
} }
} }
package model;
public enum Rotation {
NO_TURN(0),
QUARTER_TURN(1),
HALF_TURN(2),
THREE_QUARTER_TURN(3);
private final int NumberOfQuarterTurns;
Rotation(int numberOfQuarterTurns) {
NumberOfQuarterTurns = numberOfQuarterTurns;
}
public CardinalDirection rotatedDirection(CardinalDirection side) {
return CardinalDirection.values()[(side.ordinal() + this.NumberOfQuarterTurns) % CardinalDirection.NUMBER_OF_DIRECTIONS];
}
}
package model;
public enum RotationType {
NO_TURN, QUARTER_TURN, HALF_TURN, THREE_QUARTER_TURN
}
package model;
import javafx.scene.paint.Color;
import java.util.List;
public interface Side {
List<Side> compatibleSides(List<Side> sides);
Color color();
boolean accept(Side side);
}
package model; package model;
import java.util.Optional; import java.util.List;
public class Square { public interface Square {
boolean accept(Tile tile);
private Tile tile; void put(Tile tile);
private Square[] neighboringSquares; Tile getTile();
List<Side> compatibleSides(List<Side> sides, CardinalDirection direction);
private Square(Tile tile, Square[] neighboringSquares) { Square getNeighbor(CardinalDirection direction);
this.tile = tile; void setNeighbor(Square neighbor, CardinalDirection direction);
this.neighboringSquares = neighboringSquares;
}
public Square(){
this(null, new Square[CardinalDirection.NUMBER_OF_DIRECTIONS]);
}
public Optional<Tile> getSquareTile(){
if(!hasTile())
return Optional.empty();
return Optional.of(tile);
}
public void add(Tile tile) {
this.tile = tile;
}
public boolean hasTile() {
return tile != null;
}
public Optional<Tile> getNeighboringSquare(CardinalDirection side) {
if (neighboringSquares[side.ordinal()] == null)
return Optional.empty();
return neighboringSquares[side.ordinal()].getSquareTile();
}
public void setNeighboringSquare(Square neighboringSquare, CardinalDirection direction) {
this.neighboringSquares[direction.ordinal()] = neighboringSquare;
}
} }
...@@ -3,28 +3,28 @@ package model; ...@@ -3,28 +3,28 @@ package model;
import java.util.Iterator; import java.util.Iterator;
public class SquareIterator implements Iterator<Square> { public class SquareIterator implements Iterator<Square> {
private int rowIndex; private int rowNext;
private int columnIndex; private int columnNext;
private final Grid grid; private final Grid grid;
SquareIterator(Grid grid) { SquareIterator(Grid grid) {
this.rowIndex = 0; this.rowNext = 0;
this.columnIndex = 0; this.columnNext = 0;
this.grid = grid; this.grid = grid;
} }
@Override @Override
public boolean hasNext() { public boolean hasNext() {
return rowIndex < grid.getNumberOfRows(); return rowNext < grid.getNumberOfRows();
} }
@Override @Override
public Square next() { public Square next() {
final Square result = grid.getSquare(rowIndex, columnIndex); final Square next = grid.getSquare(rowNext, columnNext);
columnIndex = (columnIndex +1) % grid.getNumberOfColumns(); columnNext = (columnNext +1) % grid.getNumberOfColumns();
if(columnIndex == 0){ if(columnNext == 0){
rowIndex++; rowNext++;
} }
return result; return next;
} }
} }
package model; package model;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
public interface Tile { public interface Tile {
boolean isCompatibleWith(Tile neighbor, CardinalDirection side); Side side(CardinalDirection direction);
Tile rotation(RotationType rotation);
Color getSideColor(CardinalDirection side);
} }
package model;
public class TruchetTile implements Tile{
private final Side northWestColor;
private final Side southEastColor;
public TruchetTile(Side northWestColor, Side southEastColor) {
this.northWestColor = northWestColor;
this.southEastColor = southEastColor;
}
@Override
public Side side(CardinalDirection direction) {
return switch (direction){
case SOUTH, EAST -> southEastColor;
case NORTH, WEST -> northWestColor;
};
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment