diff --git a/build.gradle b/build.gradle
index 8231943f07c69e5caf5559abfc3fb0f37ecdba5b..b98a21c215d453616a22fb262d64318e40fbccd3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -13,9 +13,9 @@ repositories {
 }
 
 dependencies {
-    testImplementation('org.junit.jupiter:junit-jupiter-api:5.8.0',
-            'org.assertj:assertj-core:3.20.2')
-    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.0'
+    testImplementation('org.junit.jupiter:junit-jupiter-api:5.8.1',
+            'org.assertj:assertj-core:3.21.0')
+    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
 }
 
 test {
diff --git a/src/main/java/controller/GridController.java b/src/main/java/controller/GridController.java
index a0995b565676a708ce6615de7f64fdc246f59c2a..b4f9864481e525762bf8bfb34974ec5afe6ad232 100644
--- a/src/main/java/controller/GridController.java
+++ b/src/main/java/controller/GridController.java
@@ -2,7 +2,10 @@ package controller;
 
 import javafx.fxml.FXML;
 import javafx.scene.paint.Color;
-import model.RandomWangConstrainedTileGenerator;
+import model.ConstrainedRotatedTruchetTileGenerator;
+import model.RandomConstrainedWangTileGenerator;
+import model.RandomRotatedTruchetTileGenerator;
+import model.RandomWangTileGenerator;
 import view.GridTileCanvas;
 
 import java.util.List;
@@ -13,8 +16,10 @@ public class GridController {
   public GridTileCanvas gridTileCanvas;
 
   public void initialize() {
-    gridTileCanvas.initializeGrid(new RandomWangConstrainedTileGenerator(List.of(Color.BLUE, Color.RED, Color.BLACK, Color.GREEN),
-            new Random(0)));
+    //gridTileCanvas.initializeGrid(new RandomConstrainedWangTileGenerator(List.of(Color.BLUE, Color.RED, Color.BLACK, Color.GREEN),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() {
     gridTileCanvas.drawGrid();
diff --git a/src/main/java/model/ArraySquare.java b/src/main/java/model/ArraySquare.java
new file mode 100644
index 0000000000000000000000000000000000000000..3298e582bca2a6a4a4d6751f1bc488ac1f8c71ad
--- /dev/null
+++ b/src/main/java/model/ArraySquare.java
@@ -0,0 +1,59 @@
+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);
+  }
+}
diff --git a/src/main/java/model/ConstrainedRotatedTruchetTileGenerator.java b/src/main/java/model/ConstrainedRotatedTruchetTileGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f69e7fa071a5657b7bc8dd8cab43b53a956b215
--- /dev/null
+++ b/src/main/java/model/ConstrainedRotatedTruchetTileGenerator.java
@@ -0,0 +1,23 @@
+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);
+  }
+
+}
diff --git a/src/main/java/model/EmptySide.java b/src/main/java/model/EmptySide.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec97721ca558e7cbcd97be1496fab836a2cdeb2c
--- /dev/null
+++ b/src/main/java/model/EmptySide.java
@@ -0,0 +1,26 @@
+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;
+  }
+}
diff --git a/src/main/java/model/Grid.java b/src/main/java/model/Grid.java
index 91444e3c74e1139801bcf3c4f1a56edc2e4427ac..becc8e57945d08e42f112fd1a88a0657948f5875 100644
--- a/src/main/java/model/Grid.java
+++ b/src/main/java/model/Grid.java
@@ -1,12 +1,11 @@
 package model;
 import java.util.Iterator;
-import java.util.Optional;
 
 public class Grid implements Iterable<Square> {
   private final int numberOfRows;
   private final int numberOfColumns;
   private final Square[][] squares;
-
+  private final Square outOfGridSquare = new ArraySquare();
   /**
    * Creates a new {@code Grid} instance given the number of rows and columns.
    *
@@ -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);
     this.numberOfRows = numberOfRows;
     this.numberOfColumns = numberOfColumns;
-    squares = new Square[getNumberOfRows()][getNumberOfColumns()];
+    squares = new ArraySquare[getNumberOfRows()][getNumberOfColumns()];
     initializeGrid();
   }
 
@@ -34,7 +33,7 @@ public class Grid implements Iterable<Square> {
   private void initializeSquares() {
     for(int row = 0; row < getNumberOfRows(); row++)
       for(int column = 0; column < getNumberOfColumns(); column++)
-        squares[row][column] = new Square();
+        squares[row][column] = new ArraySquare();
   }
 
   private void initializeNeighborhood() {
@@ -43,8 +42,9 @@ public class Grid implements Iterable<Square> {
           for (CardinalDirection direction : CardinalDirection.values()){
             int rowNeighbor = row + direction.deltaRow;
             int columnNeighbor = column + direction.deltaColumn;
-            if(containsCoordinates(rowNeighbor, columnNeighbor))
-              squares[row][column].setNeighboringSquare(squares[rowNeighbor][columnNeighbor], direction);
+            Square neighboringSquare =
+                    containsCoordinates(rowNeighbor, columnNeighbor) ? getSquare(rowNeighbor, columnNeighbor) : outOfGridSquare;
+            getSquare(row, column).setNeighbor(neighboringSquare, direction);
           }
         }
   }
@@ -63,10 +63,6 @@ public class Grid implements Iterable<Square> {
     return new SquareIterator(this);
   }
 
-  public Optional<Tile> getTile(int rowIndex, int columnIndex) {
-    return getSquare(rowIndex, columnIndex).getSquareTile();
-  }
-
   public Square getSquare(int rowIndex, int columnIndex) {
     return squares[rowIndex][columnIndex];
   }
@@ -81,10 +77,6 @@ public class Grid implements Iterable<Square> {
 
   public void fill(TileGenerator tileGenerator){
     for(Square square : this)
-      square.add(tileGenerator.nextTile(square));
-  }
-
-  public boolean hasTile(int row, int column) {
-    return getSquare(row, column).hasTile();
+      square.put(tileGenerator.nextTile(square));
   }
 }
diff --git a/src/main/java/model/InternalSide.java b/src/main/java/model/InternalSide.java
new file mode 100644
index 0000000000000000000000000000000000000000..11b1b7a318b060c6fcc3b42500a018b620353e48
--- /dev/null
+++ b/src/main/java/model/InternalSide.java
@@ -0,0 +1,35 @@
+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;
+  }
+}
diff --git a/src/main/java/model/RandomConstrainedWangTileGenerator.java b/src/main/java/model/RandomConstrainedWangTileGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..72dce8fe20cdbc8743f97a3e07ec828a6d1397b6
--- /dev/null
+++ b/src/main/java/model/RandomConstrainedWangTileGenerator.java
@@ -0,0 +1,29 @@
+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);
+  }
+}
diff --git a/src/main/java/model/RandomRotatedTruchetTileGenerator.java b/src/main/java/model/RandomRotatedTruchetTileGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..69b8a533fa6cfc5163fc5a7e6295003f39da0423
--- /dev/null
+++ b/src/main/java/model/RandomRotatedTruchetTileGenerator.java
@@ -0,0 +1,22 @@
+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);
+  }
+}
diff --git a/src/main/java/model/RandomUniformTileGenerator.java b/src/main/java/model/RandomUniformTileGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..636116aaf30fda616076cbf2daf853a290076342
--- /dev/null
+++ b/src/main/java/model/RandomUniformTileGenerator.java
@@ -0,0 +1,24 @@
+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));
+  }
+}
diff --git a/src/main/java/model/RandomWangConstrainedTileGenerator.java b/src/main/java/model/RandomWangConstrainedTileGenerator.java
deleted file mode 100644
index d50ab021afe67aa0786c399bef861f633e73b2be..0000000000000000000000000000000000000000
--- a/src/main/java/model/RandomWangConstrainedTileGenerator.java
+++ /dev/null
@@ -1,53 +0,0 @@
-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);
-  }
-
-}
diff --git a/src/main/java/model/RandomWangTileGenerator.java b/src/main/java/model/RandomWangTileGenerator.java
new file mode 100644
index 0000000000000000000000000000000000000000..55927e9d956992f610fefc447d0dd2d956757352
--- /dev/null
+++ b/src/main/java/model/RandomWangTileGenerator.java
@@ -0,0 +1,27 @@
+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);
+  }
+}
diff --git a/src/main/java/model/RotatedTile.java b/src/main/java/model/RotatedTile.java
index 290dcaaf8e61f15791a2e2c97467b3ddf3bcd769..e00ee52b36fe01c11f1533ca0c16f5e43c8789cc 100644
--- a/src/main/java/model/RotatedTile.java
+++ b/src/main/java/model/RotatedTile.java
@@ -1,23 +1,16 @@
 package model;
 
-import javafx.scene.canvas.GraphicsContext;
-import javafx.scene.paint.Color;
-
 public class RotatedTile implements Tile {
+  private final Tile tile;
+  private final Rotation rotationType;
 
-
-  @Override
-  public boolean isCompatibleWith(Tile neighbor, CardinalDirection side) {
-    return false;
-  }
-
-  @Override
-  public Tile rotation(RotationType rotation) {
-    return null;
+  public RotatedTile(Tile tile, Rotation rotationType) {
+    this.tile = tile;
+    this.rotationType = rotationType;
   }
 
   @Override
-  public Color getSideColor(CardinalDirection side) {
-    return null;
+  public Side side(CardinalDirection direction) {
+    return tile.side(rotationType.rotatedDirection(direction));
   }
 }
diff --git a/src/main/java/model/Rotation.java b/src/main/java/model/Rotation.java
new file mode 100644
index 0000000000000000000000000000000000000000..ffd340798d057542f2b7c61c405df71efc886bcd
--- /dev/null
+++ b/src/main/java/model/Rotation.java
@@ -0,0 +1,18 @@
+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];
+  }
+}
diff --git a/src/main/java/model/RotationType.java b/src/main/java/model/RotationType.java
deleted file mode 100644
index bb496329f41b79c57e6c8a70162c4650ed3231ce..0000000000000000000000000000000000000000
--- a/src/main/java/model/RotationType.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package model;
-
-public enum RotationType {
-  NO_TURN, QUARTER_TURN, HALF_TURN, THREE_QUARTER_TURN
-}
diff --git a/src/main/java/model/Side.java b/src/main/java/model/Side.java
new file mode 100644
index 0000000000000000000000000000000000000000..4c66de4fde84e24f7bc0b6fc968716a294c29fe9
--- /dev/null
+++ b/src/main/java/model/Side.java
@@ -0,0 +1,11 @@
+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);
+}
diff --git a/src/main/java/model/Square.java b/src/main/java/model/Square.java
index 667552301e2718cac4cb6115a85f4c7c28b9c33d..2849e044ac7a3572784d5fb6512de1255735667b 100644
--- a/src/main/java/model/Square.java
+++ b/src/main/java/model/Square.java
@@ -1,42 +1,12 @@
 package model;
 
-import java.util.Optional;
-
-public class Square {
-
-  private Tile tile;
-  private Square[] neighboringSquares;
-
-  private Square(Tile tile, Square[] neighboringSquares) {
-    this.tile = tile;
-    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;
-  }
+import java.util.List;
+
+public interface Square {
+  boolean accept(Tile tile);
+  void put(Tile tile);
+  Tile getTile();
+  List<Side> compatibleSides(List<Side> sides, CardinalDirection direction);
+  Square getNeighbor(CardinalDirection direction);
+  void setNeighbor(Square neighbor, CardinalDirection direction);
 }
diff --git a/src/main/java/model/SquareIterator.java b/src/main/java/model/SquareIterator.java
index 52960a25c7cbe013758b67ffce24d49350801dac..c970bf266e283f42a1a22c8bef8b85eb83d4e897 100644
--- a/src/main/java/model/SquareIterator.java
+++ b/src/main/java/model/SquareIterator.java
@@ -3,28 +3,28 @@ package model;
 import java.util.Iterator;
 
 public class SquareIterator implements Iterator<Square> {
-  private int rowIndex;
-  private int columnIndex;
+  private int rowNext;
+  private int columnNext;
   private final Grid grid;
 
   SquareIterator(Grid grid) {
-    this.rowIndex = 0;
-    this.columnIndex = 0;
+    this.rowNext = 0;
+    this.columnNext = 0;
     this.grid = grid;
   }
 
   @Override
   public boolean hasNext() {
-    return rowIndex < grid.getNumberOfRows();
+    return rowNext < grid.getNumberOfRows();
   }
 
   @Override
   public Square next() {
-    final Square result = grid.getSquare(rowIndex, columnIndex);
-    columnIndex = (columnIndex +1) % grid.getNumberOfColumns();
-    if(columnIndex == 0){
-      rowIndex++;
+    final Square next = grid.getSquare(rowNext, columnNext);
+    columnNext = (columnNext +1) % grid.getNumberOfColumns();
+    if(columnNext == 0){
+      rowNext++;
     }
-    return result;
+    return next;
   }
 }
diff --git a/src/main/java/model/Tile.java b/src/main/java/model/Tile.java
index c75dcb79c4f435e8f7fc453f04cf79a2ee311837..ef290d27885599e94722a74a42fe98cfc4dec137 100644
--- a/src/main/java/model/Tile.java
+++ b/src/main/java/model/Tile.java
@@ -1,10 +1,5 @@
 package model;
 
-import javafx.scene.canvas.GraphicsContext;
-import javafx.scene.paint.Color;
-
 public interface Tile {
-  boolean isCompatibleWith(Tile neighbor, CardinalDirection side);
-  Tile rotation(RotationType rotation);
-  Color getSideColor(CardinalDirection side);
+  Side side(CardinalDirection direction);
 }
diff --git a/src/main/java/model/TruchetTile.java b/src/main/java/model/TruchetTile.java
new file mode 100644
index 0000000000000000000000000000000000000000..46bfb2e6a4341f3da6f3cf28ef1ec4518391d943
--- /dev/null
+++ b/src/main/java/model/TruchetTile.java
@@ -0,0 +1,19 @@
+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;
+    };
+  }
+}
diff --git a/src/main/java/model/UniformTile.java b/src/main/java/model/UniformTile.java
new file mode 100644
index 0000000000000000000000000000000000000000..89ea2dbe032f89934bf5e7477fe1482262967b96
--- /dev/null
+++ b/src/main/java/model/UniformTile.java
@@ -0,0 +1,14 @@
+package model;
+
+public class UniformTile implements Tile{
+  private final Side side;
+
+  public UniformTile(Side side) {
+    this.side = side;
+  }
+
+  @Override
+  public Side side(CardinalDirection direction) {
+    return side;
+  }
+}
diff --git a/src/main/java/model/WangTile.java b/src/main/java/model/WangTile.java
index ecfa87b86ae5bfb1531a5662b1ad1d637275b561..4d02bf7417f1733270a529efe9c5ba5dde7eb1f9 100644
--- a/src/main/java/model/WangTile.java
+++ b/src/main/java/model/WangTile.java
@@ -1,50 +1,17 @@
 package model;
 
-import javafx.scene.canvas.GraphicsContext;
-import javafx.scene.paint.Color;
-
-import java.util.Arrays;
-import java.util.List;
-
 public class WangTile implements Tile {
-  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);
-  }
+  private final Side[] sides = new Side[CardinalDirection.NUMBER_OF_DIRECTIONS];
 
-  public Color getSideColor(CardinalDirection direction){
-    return colors[direction.ordinal()];
+  public WangTile(Side[] sides) {
+    if(sides.length != CardinalDirection.NUMBER_OF_DIRECTIONS)
+      throw new IllegalArgumentException("A tile is defined by " + CardinalDirection.NUMBER_OF_DIRECTIONS
+                                            + "and not" + sides.length + "sides.");
+    System.arraycopy(sides, 0, this.sides, 0, CardinalDirection.NUMBER_OF_DIRECTIONS);
   }
 
-  @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);
+  public Side side(CardinalDirection direction){
+    return sides[direction.ordinal()];
   }
-
-  @Override
-  public int hashCode() {
-    return Arrays.hashCode(colors);
-  }
-
-
-
-  @Override
-  public boolean isCompatibleWith(Tile neighbor, CardinalDirection side) {
-    return false;
-  }
-
-  @Override
-  public Tile rotation(RotationType rotation) {
-    return null;
-  }
-
-
 }
diff --git a/src/main/java/util/RandomUtil.java b/src/main/java/util/RandomUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..8ccb36f64f0d627e22f1d8c20798451b465c877d
--- /dev/null
+++ b/src/main/java/util/RandomUtil.java
@@ -0,0 +1,16 @@
+package util;
+
+import java.util.List;
+import java.util.Random;
+
+public final class RandomUtil {
+  private RandomUtil(){}
+
+  public static <T> T randomElement(List<T> elements, Random random){
+    return elements.get(random.nextInt(elements.size()));
+  }
+
+  public static <T> T randomElement(T[] elements, Random random){
+    return elements[random.nextInt(elements.length)];
+  }
+}
diff --git a/src/main/java/view/GridTileCanvas.java b/src/main/java/view/GridTileCanvas.java
index 5dede2f1ea226877b640bf39a7eca16ba4d8aae7..5eb17226e56c64dd070ec0b390e2922bfde506a9 100644
--- a/src/main/java/view/GridTileCanvas.java
+++ b/src/main/java/view/GridTileCanvas.java
@@ -4,9 +4,7 @@ import javafx.beans.NamedArg;
 import javafx.scene.canvas.Canvas;
 import javafx.scene.canvas.GraphicsContext;
 import model.*;
-
 import java.util.List;
-import java.util.Optional;
 
 public class GridTileCanvas extends Canvas {
 
@@ -44,12 +42,10 @@ public class GridTileCanvas extends Canvas {
   }
 
   public void drawGridTile(Grid tileGrid){
-    GraphicsContext graphicsContext = getGraphicsContext2D();
     for(int row = 0; row < numberOfRows; row++)
       for(int column = 0; column < numberOfColumns; column++){
-        Optional<Tile> tile = tileGrid.getTile(row, column);
-        if(tile.isPresent())
-          drawTile(tile.get(), column * tileWidth, row * tileHeight);
+        Tile tile = tileGrid.getSquare(row, column).getTile();
+        drawTile(tile, column * tileWidth, row * tileHeight);
       }
   }
 
@@ -67,7 +63,7 @@ public class GridTileCanvas extends Canvas {
       xPoints[index] =  x + (cornerTypes.get(index).getXPosition() * tileWidth);
       yPoints[index] =  y + (cornerTypes.get(index).getYPosition() * tileHeight);
     }
-    graphicsContext.setFill(tile.getSideColor(side));
+    graphicsContext.setFill(tile.side(side).color());
     graphicsContext.fillPolygon(xPoints, yPoints, 3);
   }
 }
diff --git a/src/test/java/model/TileTest.java b/src/test/java/model/TileTest.java
deleted file mode 100644
index 074d8ea61694e818b59db02e37ebb50db40876b4..0000000000000000000000000000000000000000
--- a/src/test/java/model/TileTest.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package model;
-
-import javafx.scene.paint.Color;
-import org.junit.jupiter.api.Test;
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class TileTest {
-  @Test
-  void testGetColor(){
-    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};
-    WangTile tile1 = new WangTile(colors1);
-    WangTile tile2 = new WangTile(colors1);
-    WangTile tile3 = new WangTile(colors2);
-    assertThat(tile1)
-            .isEqualTo(tile1)
-            .isEqualTo(tile2)
-            .isNotEqualTo(tile3);
-  }
-}
diff --git a/src/test/java/model/WangTileTest.java b/src/test/java/model/WangTileTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..422b9288c5412971b095bc7bf03f570c552f0c54
--- /dev/null
+++ b/src/test/java/model/WangTileTest.java
@@ -0,0 +1,19 @@
+package model;
+
+import javafx.scene.paint.Color;
+import org.junit.jupiter.api.Test;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class WangTileTest {
+
+  @Test
+  void testGetColor(){
+    WangTile tile = new WangTile(new Side[]{new InternalSide(Color.BLACK), new InternalSide(Color.BLUE),
+            new InternalSide(Color.WHITE), new InternalSide(Color.BLUE)});
+    assertThat(tile.side(CardinalDirection.NORTH).color()).isEqualTo(Color.BLACK);
+    assertThat(tile.side(CardinalDirection.EAST).color()).isEqualTo(Color.BLUE);
+    assertThat(tile.side(CardinalDirection.SOUTH).color()).isEqualTo(Color.WHITE);
+    assertThat(tile.side(CardinalDirection.WEST).color()).isEqualTo(Color.BLUE);
+  }
+
+}