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)