From 207adb5bcda18464e7a950a321e09d9ac970f706 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Magnus=20Schj=C3=B8lberg?= <magnus.schjolberg@ntnu.no>
Date: Wed, 5 Jan 2022 15:17:40 +0100
Subject: [PATCH] Add test code for JUnit5 and JavaFX

---
 foreksempel/src/main/java/of13/kode/Game.fxml |  41 +++
 foreksempel/src/main/java/of13/kode/Game.java | 188 ++++++++++++++
 .../src/main/java/of13/kode/GameApp.java      |  23 ++
 .../main/java/of13/kode/GameController.java   | 164 ++++++++++++
 .../src/main/java/of13/kode/SaveHandler.java  |  79 ++++++
 foreksempel/src/main/java/of13/kode/Tile.java |  94 +++++++
 foreksempel/src/main/java/of13/lf/Game.fxml   |  41 +++
 foreksempel/src/main/java/of13/lf/Game.java   | 188 ++++++++++++++
 .../src/main/java/of13/lf/GameApp.java        |  23 ++
 .../src/main/java/of13/lf/GameController.java | 164 ++++++++++++
 .../src/main/java/of13/lf/SaveHandler.java    |  78 ++++++
 foreksempel/src/main/java/of13/lf/Tile.java   |  94 +++++++
 .../src/main/java/of13/saves/test-save.txt    |   8 +
 .../main/java/of13/v2020/kode/Assistant.java  |  26 ++
 .../src/main/java/of13/v2020/kode/Boss.java   |  50 ++++
 .../main/java/of13/v2020/kode/Employee.java   |  31 +++
 .../of13/v2020/kode/TemporaryEmployee.java    |  45 ++++
 .../main/java/of13/v2020/lf/Assistant.java    |  25 ++
 .../java/of13/v2020/lf/AssistantTest.java     |  53 ++++
 .../src/main/java/of13/v2020/lf/Boss.java     |  50 ++++
 .../src/main/java/of13/v2020/lf/BossTest.java |  56 +++++
 .../src/main/java/of13/v2020/lf/Employee.java |  31 +++
 .../java/of13/v2020/lf/TemporaryEmployee.java |  45 ++++
 .../of13/v2020/lf/TemporaryEmployeeTest.java  |  53 ++++
 foreksempel/src/main/java/of6/kode/Game.java  | 221 ++++++++++++++++
 .../src/main/java/of6/kode/Oppgave3.txt       |  21 ++
 .../src/main/java/of6/kode/Oppgave4.txt       |   1 +
 .../main/java/of6/kode/Oppgave5-farger.txt    |   5 +
 .../src/main/java/of6/kode/Oppgave5-test.txt  |   5 +
 foreksempel/src/main/java/of6/kode/Tile.java  |  70 ++++++
 foreksempel/src/main/java/of6/lf/Game.fxml    |  34 +++
 foreksempel/src/main/java/of6/lf/Game.java    | 237 ++++++++++++++++++
 foreksempel/src/main/java/of6/lf/GameApp.java |  25 ++
 .../src/main/java/of6/lf/GameController.java  | 151 +++++++++++
 foreksempel/src/main/java/of6/lf/Tile.java    |  70 ++++++
 foreksempel/src/main/java/uke2/Random100.java |   4 +-
 .../src/test/java/of13/kode/.gitinclude       |   0
 .../src/test/java/of13/lf/GameTest.java       | 103 ++++++++
 .../test/java/of13/lf/SaveHandlerTest.java    | 115 +++++++++
 .../src/test/java/of13/lf/TileTest.java       |  37 +++
 40 files changed, 2747 insertions(+), 2 deletions(-)
 create mode 100644 foreksempel/src/main/java/of13/kode/Game.fxml
 create mode 100644 foreksempel/src/main/java/of13/kode/Game.java
 create mode 100644 foreksempel/src/main/java/of13/kode/GameApp.java
 create mode 100644 foreksempel/src/main/java/of13/kode/GameController.java
 create mode 100644 foreksempel/src/main/java/of13/kode/SaveHandler.java
 create mode 100644 foreksempel/src/main/java/of13/kode/Tile.java
 create mode 100644 foreksempel/src/main/java/of13/lf/Game.fxml
 create mode 100644 foreksempel/src/main/java/of13/lf/Game.java
 create mode 100644 foreksempel/src/main/java/of13/lf/GameApp.java
 create mode 100644 foreksempel/src/main/java/of13/lf/GameController.java
 create mode 100644 foreksempel/src/main/java/of13/lf/SaveHandler.java
 create mode 100644 foreksempel/src/main/java/of13/lf/Tile.java
 create mode 100644 foreksempel/src/main/java/of13/saves/test-save.txt
 create mode 100644 foreksempel/src/main/java/of13/v2020/kode/Assistant.java
 create mode 100644 foreksempel/src/main/java/of13/v2020/kode/Boss.java
 create mode 100644 foreksempel/src/main/java/of13/v2020/kode/Employee.java
 create mode 100644 foreksempel/src/main/java/of13/v2020/kode/TemporaryEmployee.java
 create mode 100644 foreksempel/src/main/java/of13/v2020/lf/Assistant.java
 create mode 100644 foreksempel/src/main/java/of13/v2020/lf/AssistantTest.java
 create mode 100644 foreksempel/src/main/java/of13/v2020/lf/Boss.java
 create mode 100644 foreksempel/src/main/java/of13/v2020/lf/BossTest.java
 create mode 100644 foreksempel/src/main/java/of13/v2020/lf/Employee.java
 create mode 100644 foreksempel/src/main/java/of13/v2020/lf/TemporaryEmployee.java
 create mode 100644 foreksempel/src/main/java/of13/v2020/lf/TemporaryEmployeeTest.java
 create mode 100644 foreksempel/src/main/java/of6/kode/Game.java
 create mode 100644 foreksempel/src/main/java/of6/kode/Oppgave3.txt
 create mode 100644 foreksempel/src/main/java/of6/kode/Oppgave4.txt
 create mode 100644 foreksempel/src/main/java/of6/kode/Oppgave5-farger.txt
 create mode 100644 foreksempel/src/main/java/of6/kode/Oppgave5-test.txt
 create mode 100644 foreksempel/src/main/java/of6/kode/Tile.java
 create mode 100644 foreksempel/src/main/java/of6/lf/Game.fxml
 create mode 100644 foreksempel/src/main/java/of6/lf/Game.java
 create mode 100644 foreksempel/src/main/java/of6/lf/GameApp.java
 create mode 100644 foreksempel/src/main/java/of6/lf/GameController.java
 create mode 100644 foreksempel/src/main/java/of6/lf/Tile.java
 create mode 100644 foreksempel/src/test/java/of13/kode/.gitinclude
 create mode 100644 foreksempel/src/test/java/of13/lf/GameTest.java
 create mode 100644 foreksempel/src/test/java/of13/lf/SaveHandlerTest.java
 create mode 100644 foreksempel/src/test/java/of13/lf/TileTest.java

diff --git a/foreksempel/src/main/java/of13/kode/Game.fxml b/foreksempel/src/main/java/of13/kode/Game.fxml
new file mode 100644
index 0000000..f82fbf2
--- /dev/null
+++ b/foreksempel/src/main/java/of13/kode/Game.fxml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.Button?>
+<?import javafx.scene.control.TextField?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.ColumnConstraints?>
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.layout.Pane?>
+<?import javafx.scene.layout.RowConstraints?>
+<?import javafx.scene.text.Text?>
+
+<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="of10.lf.GameController">
+   <children>
+      <GridPane prefHeight="400.0" prefWidth="400.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+        <columnConstraints>
+          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="600.0" />
+        </columnConstraints>
+        <rowConstraints>
+          <RowConstraints minHeight="10.0" prefHeight="330.0" vgrow="ALWAYS" />
+          <RowConstraints maxHeight="70.0" minHeight="70.0" prefHeight="70.0" vgrow="SOMETIMES" />
+        </rowConstraints>
+         <children>
+            <Pane fx:id="board" prefHeight="200.0" prefWidth="600.0" GridPane.rowIndex="0">
+            </Pane>
+            <Pane maxHeight="75.0" minHeight="75.0" prefHeight="75.0" prefWidth="600.0" GridPane.rowIndex="1">
+               <children>
+                  <Button layoutX="100.0" layoutY="5.0" mnemonicParsing="false" onMouseClicked="#handleUp" prefWidth="60.0" text="Up" />
+                  <Button layoutX="100.0" layoutY="40.0" mnemonicParsing="false" onMouseClicked="#handleDown" prefWidth="60.0" text="Down" />
+                  <Button layoutX="30.0" layoutY="40.0" mnemonicParsing="false" onMouseClicked="#handleLeft" prefWidth="60.0" text="Left" />
+                  <Button layoutX="170.0" layoutY="40.0" mnemonicParsing="false" onMouseClicked="#handleRight" prefWidth="60.0" text="Right" />
+                  <Button layoutX="507.0" layoutY="5.0" mnemonicParsing="false" onMouseClicked="#handleLoad" text="Load" />
+                  <Button layoutX="507.0" layoutY="40.0" mnemonicParsing="false" onMouseClicked="#handleSave" text="Save" />
+                  <TextField fx:id="filename" layoutX="334.0" layoutY="27.0" prefHeight="27.0" prefWidth="160.0" promptText="save_file" text="save_file" />
+                  <Text layoutX="334.0" layoutY="23.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Filename:" />
+                  <Text fill="RED" layoutX="334.0" layoutY="66.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Filen finnes ikke" visible="false" fx:id="fileNotFoundMessage"/>
+               </children>
+            </Pane>
+         </children>
+      </GridPane>
+   </children>
+</AnchorPane>
diff --git a/foreksempel/src/main/java/of13/kode/Game.java b/foreksempel/src/main/java/of13/kode/Game.java
new file mode 100644
index 0000000..4ab2789
--- /dev/null
+++ b/foreksempel/src/main/java/of13/kode/Game.java
@@ -0,0 +1,188 @@
+package of13.kode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Game {
+
+    private Tile[][] board;
+    private ArrayList<Tile> snake;
+    private boolean isGameOver = false;
+    private boolean isGameWon = false;
+
+    public Game(int width, int height) {
+        board = new Tile[height][width];
+        for (int y = 0; y < height; y++) {
+            for (int x = 0; x < width; x++) {
+                board[y][x] = new Tile(x, y);
+            }
+        }
+    }
+
+    public void createSnake(List<Tile> tiles) {
+        if (snake != null) {
+            throw new IllegalStateException("Snake already created");
+        }
+
+        for (Tile tile : tiles) {
+            tile.setSnake();
+        }
+        snake = new ArrayList<>(tiles);
+    }
+
+    public boolean isTile(int x, int y) {
+        return 0 <= x && x < getWidth() && 0 <= y && y < getHeight();
+    }
+
+    public Tile getTile(int x, int y) {
+        if (!isTile(x, y)) {
+            throw new IllegalArgumentException("Not a valid tile");
+        }
+
+        return board[y][x];
+    }
+
+    public int getHeight() {
+        return board.length;
+    }
+
+    public int getWidth() {
+        return board[0].length;
+    }
+
+    public boolean isGameOver() {
+        return isGameOver;
+    }
+
+    public boolean isGameWon() {
+        return isGameWon;
+    }
+    
+    public void setGameOver() {
+    	isGameOver = true;
+    }
+    
+    public void setGameWon() {
+    	isGameWon = true;
+    }
+
+    private boolean canMove(int dx, int dy) {
+        if (snake == null || Math.abs(dx) + Math.abs(dy) > 1 || isGameOver() || isGameWon()) {
+            return false;
+        }
+
+        int x = snake.get(0).getX() + dx;
+        int y = snake.get(0).getY() + dy;
+
+        return isTile(x, y) && (!getTile(x, y).hasCollision() || getTile(x, y) == snake.get(snake.size() - 1));
+    }
+
+    private void move(int dx, int dy) {
+    	if (!canMove(dx, dy)) {
+    		throw new IllegalStateException("Not a valid move");
+    	}
+    	
+        Tile targetTile = getTile(snake.get(0).getX() + dx, snake.get(0).getY() + dy);
+
+        if (targetTile.isGoal()) {
+            isGameWon = true;
+        }
+
+        if (!targetTile.isFruit()) {
+            snake.get(snake.size() - 1).setAir();
+            snake.remove(snake.size() - 1);
+        }
+        snake.add(0, targetTile);
+        snake.get(0).setSnake();
+
+        if (isGameWon) {
+            return;
+        }
+
+        while (snakeInAir()) {
+            isGameOver = false;
+            for (Tile tile : snake) {
+                if (!isTile(tile.getX(), tile.getY() + 1)) {
+                    isGameOver = true;
+                }
+            }
+            if (isGameOver) {
+                break;
+            }
+
+            for (Tile tile : snake) {
+                tile.setAir();
+            }
+
+            ArrayList<Tile> newSnake = new ArrayList<>();
+            for (Tile tile : snake) {
+                Tile newTile = getTile(tile.getX(), tile.getY() + 1);
+                newTile.setSnake();
+                newSnake.add(newTile);
+            }
+            snake = newSnake;
+        }
+    }
+
+    private boolean snakeInAir() {
+        for (Tile tile : snake) {
+            if (isTile(tile.getX(), tile.getY() + 1) && getTile(tile.getX(), tile.getY() + 1).isGround()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public boolean isSnakeHead(Tile tile) {
+        return snake != null && tile == snake.get(0);
+    }
+
+    
+    public void moveUp() {
+        move(0, -1);
+	    System.out.println(this);
+    }
+
+    public void moveDown() {
+        move(0, 1);
+	    System.out.println(this);
+    }
+
+    public void moveLeft() {
+        move(-1, 0);
+	    System.out.println(this);
+    }
+
+    public void moveRight() {
+        move(1, 0);
+	    System.out.println(this);
+    }
+    
+    public List<Tile> getSnake() {
+    	return new ArrayList<>(snake);
+    }
+
+    @Override
+    public String toString() {
+        String representation = "";
+        if (isGameWon()) {
+            representation = "You Won!";
+        } else if (isGameOver()) {
+            representation = "You Lost!";
+        }
+
+
+        for (int y = 0; y < getHeight(); y++) {
+            for (int x = 0; x < getWidth(); x++) {
+                if (snake != null && snake.get(0) == getTile(x, y)) {
+                    representation = representation + "8";
+                } else {
+                    representation = representation + getTile(x, y).toString();
+                }
+            }
+            representation = representation + "\n";
+        }
+        return representation;
+    }
+
+}
diff --git a/foreksempel/src/main/java/of13/kode/GameApp.java b/foreksempel/src/main/java/of13/kode/GameApp.java
new file mode 100644
index 0000000..194a2d5
--- /dev/null
+++ b/foreksempel/src/main/java/of13/kode/GameApp.java
@@ -0,0 +1,23 @@
+package of13.kode;
+
+import javafx.application.Application;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+
+import java.io.IOException;
+
+public class GameApp extends Application {
+
+    public static void main(String[] args) {
+        Application.launch(args);
+    }
+
+    @Override
+    public void start(Stage primaryStage) throws IOException {
+        primaryStage.setTitle("Snakebird");
+        primaryStage.setScene(new Scene(FXMLLoader.load(getClass().getResource("Game.fxml"))));
+        primaryStage.show();
+    }
+
+}
diff --git a/foreksempel/src/main/java/of13/kode/GameController.java b/foreksempel/src/main/java/of13/kode/GameController.java
new file mode 100644
index 0000000..ee18d0e
--- /dev/null
+++ b/foreksempel/src/main/java/of13/kode/GameController.java
@@ -0,0 +1,164 @@
+package of13.kode;
+
+import javafx.fxml.FXML;
+import javafx.scene.text.Text;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.Pane;
+import javafx.scene.paint.Color;
+
+import java.io.FileNotFoundException;
+import java.util.Arrays;
+
+public class GameController {
+
+    private Game game;
+    private SaveHandler saveHandler = new SaveHandler();
+
+    @FXML
+    Pane board;
+    
+    @FXML
+    TextField filename;
+    
+    @FXML
+    Text fileNotFoundMessage;
+
+    @FXML
+    public void initialize() {
+        game = new Game(16, 12);
+        game.getTile(6, 11).setGround();
+        game.getTile(7, 11).setGround();
+        game.getTile(8, 11).setGround();
+        game.getTile(6, 10).setGround();
+        game.getTile(7, 10).setGround();
+        game.getTile(8, 10).setGround();
+        game.getTile(9, 10).setGround();
+        game.getTile(6, 9).setGround();
+        game.getTile(7, 9).setGround();
+        game.getTile(8, 9).setGround();
+        game.getTile(9, 9).setGround();
+        game.getTile(6, 8).setGround();
+        game.getTile(8, 6).setGround();
+        game.getTile(10, 6).setGround();
+        game.getTile(5, 5).setGround();
+        game.getTile(5, 6).setFruit();
+        game.getTile(9, 6).setFruit();
+        game.getTile(8, 3).setGoal();
+
+        game.createSnake(Arrays.asList(game.getTile(9, 8), game.getTile(8, 8)));
+             
+
+        createBoard();
+        drawBoard();
+    }
+
+    private void createBoard() {
+        board.getChildren().clear();
+        for (int y = 0; y < game.getHeight(); y++) {
+            for (int x = 0; x < game.getWidth(); x++) {
+                Pane tile = new Pane();
+                tile.setTranslateX(x * 20);
+                tile.setTranslateY(y * 20);
+                tile.setPrefWidth(20);
+                tile.setPrefHeight(20);
+                board.getChildren().add(tile);
+            }
+        }
+    }
+
+    private String getTileColor(Tile tile) {
+        if (game.isSnakeHead(tile)) {
+            return "#1db121";
+        } else if (tile.isSnake()) {
+            return "#24d628";
+        } else if (tile.isGround()) {
+            return "#a26f42";
+        } else if (tile.isFruit()) {
+            return "#e5303a";
+        } else if (tile.isGoal()) {
+            return "#f6ec5a";
+        }
+        return "#7bcaf2";
+    }
+
+    @FXML
+    void handleUp() {
+        game.moveUp();
+        drawBoard();
+    }
+
+    @FXML
+    void handleDown() {
+        game.moveDown();
+        drawBoard();
+    }
+
+    @FXML
+    void handleLeft() {
+        game.moveLeft();
+        drawBoard();
+    }
+
+    @FXML
+    void handleRight() {
+        game.moveRight();
+        drawBoard();
+    }
+    
+    private String getFilename() {
+    	String filename = this.filename.getText();
+    	if (filename.isEmpty()) {
+    		filename = "save_file";
+    	}
+    	return filename;
+    }
+    
+    @FXML
+    void handleSave() {
+    	try {
+    		saveHandler.save(getFilename(), game);
+    		fileNotFoundMessage.setVisible(false);
+    	} catch (FileNotFoundException e) {
+    		fileNotFoundMessage.setVisible(true);
+    	}
+    }
+    
+    @FXML
+    void handleLoad() {
+    	try {
+			game = saveHandler.load(getFilename());
+    		fileNotFoundMessage.setVisible(false);
+    	} catch (FileNotFoundException e) {
+    		fileNotFoundMessage.setVisible(true);
+		}
+    	createBoard();
+    	drawBoard();
+    }
+
+    private void drawBoard() {
+        for (int y = 0; y < game.getHeight(); y++) {
+            for (int x = 0; x < game.getWidth(); x++) {
+                board.getChildren().get(y * game.getWidth() + x).setStyle("-fx-background-color: " + getTileColor(game.getTile(x, y)));
+            }
+        }
+
+        if (game.isGameWon()) {
+            Text wonText = new Text();
+            wonText.setText("You Won!");
+            wonText.setFill(Color.GREEN);
+            wonText.setStyle("-fx-font-size: 40px;");
+            wonText.setTranslateX(((double) game.getWidth() * 20) / 2 - 80);
+            wonText.setTranslateY(((double) game.getHeight() * 20) / 2);
+            board.getChildren().add(wonText);
+        } else if (game.isGameOver()) {
+            Text lostText = new Text();
+            lostText.setText("You Lost!");
+            lostText.setStyle("-fx-font-size: 40px;");
+            lostText.setFill(Color.RED);
+            lostText.setTranslateX(((double) game.getWidth() * 20) / 2 - 80);
+            lostText.setTranslateY(((double) game.getHeight() * 20) / 2);
+            board.getChildren().add(lostText);
+        }
+    }
+
+}
diff --git a/foreksempel/src/main/java/of13/kode/SaveHandler.java b/foreksempel/src/main/java/of13/kode/SaveHandler.java
new file mode 100644
index 0000000..b1f6caf
--- /dev/null
+++ b/foreksempel/src/main/java/of13/kode/SaveHandler.java
@@ -0,0 +1,79 @@
+package of13.kode;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Scanner;
+
+public class SaveHandler {
+
+	public final static String SAVE_FOLDER = "src/main/java/of13/saves/";
+
+	public void save(String filename, Game game) throws FileNotFoundException {
+		try (PrintWriter writer = new PrintWriter(getFilePath(filename))) {
+			writer.println(game.getWidth());
+			writer.println(game.getHeight());
+			writer.println(game.isGameOver());
+			writer.println(game.isGameWon());
+			for (int y = 0; y < game.getHeight(); y++) {
+				for (int x = 0; x < game.getWidth(); x++) {
+					writer.print(game.getTile(x, y).getType());
+				}
+			}
+
+			writer.println();
+			writer.println(game.getSnake().size());
+			for (Tile tile : game.getSnake()) {
+				writer.print(tile.getX());
+				writer.print(" ");
+				writer.println(tile.getY());
+				// Eventuelt
+				//writer.printf("%d %d\n", tile.getX(), tile.getY());
+			}
+		} 
+	}
+
+	public Game load(String filename) throws FileNotFoundException {
+		try (Scanner scanner = new Scanner(new File(getFilePath(filename)))) {
+			int width = scanner.nextInt();
+			int height = scanner.nextInt();
+			Game game = new Game(width, height);
+
+			if (scanner.nextBoolean()) {
+				game.setGameOver();
+			}
+
+			if (scanner.nextBoolean()) {
+				game.setGameWon();
+			}
+
+			scanner.nextLine();
+
+			String board = scanner.next();
+			for (int y = 0; y < height; y++) {
+				for (int x = 0; x < width; x++) {
+					char symbol = board.charAt(y * width + x);
+					game.getTile(x, y).setType(symbol);
+				}
+			}
+
+			int snakeLength = scanner.nextInt();
+			List<Tile> snake = new ArrayList<>();
+			for (int i = 0; i < snakeLength; i++) {
+				snake.add(game.getTile(scanner.nextInt(), scanner.nextInt()));
+			}
+			game.createSnake(snake);
+
+			return game;
+		}
+	}
+
+	public static String getFilePath(String filename) {
+		return SAVE_FOLDER + filename + ".txt";
+	}
+	
+
+}
diff --git a/foreksempel/src/main/java/of13/kode/Tile.java b/foreksempel/src/main/java/of13/kode/Tile.java
new file mode 100644
index 0000000..5b1b1ee
--- /dev/null
+++ b/foreksempel/src/main/java/of13/kode/Tile.java
@@ -0,0 +1,94 @@
+package of13.kode;
+
+public class Tile {
+
+    private char type = 'a';
+    private int x;
+    private int y;
+
+    public Tile(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+    
+    public void setType(char symbol) {
+    	if ("asgf@s".indexOf(symbol) == -1) {
+    		throw new IllegalArgumentException("Not a valid state");
+    	}
+    	
+    	type = symbol;
+    }
+    
+    public char getType() {
+    	return type;
+    }
+
+    public void setAir() {
+        type = 'a';
+    }
+
+    public void setSnake() {
+        type = 's';
+    }
+
+    public void setGround() {
+        type = 'g';
+    }
+
+    public void setFruit() {
+        type = 'f';
+    }
+
+    public void setGoal() {
+        type = '@';
+    }
+
+    public boolean isAir() {
+        return type == 'a';
+    }
+
+    public boolean isSnake() {
+        return type == 's';
+    }
+
+    public boolean isGround() {
+        return type == 'g';
+    }
+
+    public boolean isFruit() {
+        return type == 'f';
+    }
+
+    public boolean isGoal() {
+        return type == '@';
+    }
+
+    public int getX() {
+        return x;
+    }
+
+    public int getY() {
+        return y;
+    }
+
+    public boolean hasCollision() {
+        return isGround() || isSnake();
+    }
+
+    @Override
+    public String toString() {
+        switch (type) {
+            case 'g':
+                return "#";
+            case '@':
+                return "@";
+            case 's':
+                return "O";
+            case 'f':
+                return "*";
+            case 'a':
+            default:
+                return " ";
+        }
+    }
+}
diff --git a/foreksempel/src/main/java/of13/lf/Game.fxml b/foreksempel/src/main/java/of13/lf/Game.fxml
new file mode 100644
index 0000000..f82fbf2
--- /dev/null
+++ b/foreksempel/src/main/java/of13/lf/Game.fxml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.Button?>
+<?import javafx.scene.control.TextField?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.ColumnConstraints?>
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.layout.Pane?>
+<?import javafx.scene.layout.RowConstraints?>
+<?import javafx.scene.text.Text?>
+
+<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="of10.lf.GameController">
+   <children>
+      <GridPane prefHeight="400.0" prefWidth="400.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+        <columnConstraints>
+          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="600.0" />
+        </columnConstraints>
+        <rowConstraints>
+          <RowConstraints minHeight="10.0" prefHeight="330.0" vgrow="ALWAYS" />
+          <RowConstraints maxHeight="70.0" minHeight="70.0" prefHeight="70.0" vgrow="SOMETIMES" />
+        </rowConstraints>
+         <children>
+            <Pane fx:id="board" prefHeight="200.0" prefWidth="600.0" GridPane.rowIndex="0">
+            </Pane>
+            <Pane maxHeight="75.0" minHeight="75.0" prefHeight="75.0" prefWidth="600.0" GridPane.rowIndex="1">
+               <children>
+                  <Button layoutX="100.0" layoutY="5.0" mnemonicParsing="false" onMouseClicked="#handleUp" prefWidth="60.0" text="Up" />
+                  <Button layoutX="100.0" layoutY="40.0" mnemonicParsing="false" onMouseClicked="#handleDown" prefWidth="60.0" text="Down" />
+                  <Button layoutX="30.0" layoutY="40.0" mnemonicParsing="false" onMouseClicked="#handleLeft" prefWidth="60.0" text="Left" />
+                  <Button layoutX="170.0" layoutY="40.0" mnemonicParsing="false" onMouseClicked="#handleRight" prefWidth="60.0" text="Right" />
+                  <Button layoutX="507.0" layoutY="5.0" mnemonicParsing="false" onMouseClicked="#handleLoad" text="Load" />
+                  <Button layoutX="507.0" layoutY="40.0" mnemonicParsing="false" onMouseClicked="#handleSave" text="Save" />
+                  <TextField fx:id="filename" layoutX="334.0" layoutY="27.0" prefHeight="27.0" prefWidth="160.0" promptText="save_file" text="save_file" />
+                  <Text layoutX="334.0" layoutY="23.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Filename:" />
+                  <Text fill="RED" layoutX="334.0" layoutY="66.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Filen finnes ikke" visible="false" fx:id="fileNotFoundMessage"/>
+               </children>
+            </Pane>
+         </children>
+      </GridPane>
+   </children>
+</AnchorPane>
diff --git a/foreksempel/src/main/java/of13/lf/Game.java b/foreksempel/src/main/java/of13/lf/Game.java
new file mode 100644
index 0000000..4192c56
--- /dev/null
+++ b/foreksempel/src/main/java/of13/lf/Game.java
@@ -0,0 +1,188 @@
+package of13.lf;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Game {
+
+    private Tile[][] board;
+    private ArrayList<Tile> snake;
+    private boolean isGameOver = false;
+    private boolean isGameWon = false;
+
+    public Game(int width, int height) {
+        board = new Tile[height][width];
+        for (int y = 0; y < height; y++) {
+            for (int x = 0; x < width; x++) {
+                board[y][x] = new Tile(x, y);
+            }
+        }
+    }
+
+    public void createSnake(List<Tile> tiles) {
+        if (snake != null) {
+            throw new IllegalStateException("Snake already created");
+        }
+
+        for (Tile tile : tiles) {
+            tile.setSnake();
+        }
+        snake = new ArrayList<>(tiles);
+    }
+
+    public boolean isTile(int x, int y) {
+        return 0 <= x && x < getWidth() && 0 <= y && y < getHeight();
+    }
+
+    public Tile getTile(int x, int y) {
+        if (!isTile(x, y)) {
+            throw new IllegalArgumentException("Not a valid tile");
+        }
+
+        return board[y][x];
+    }
+
+    public int getHeight() {
+        return board.length;
+    }
+
+    public int getWidth() {
+        return board[0].length;
+    }
+
+    public boolean isGameOver() {
+        return isGameOver;
+    }
+
+    public boolean isGameWon() {
+        return isGameWon;
+    }
+    
+    public void setGameOver() {
+    	isGameOver = true;
+    }
+    
+    public void setGameWon() {
+    	isGameWon = true;
+    }
+
+    private boolean canMove(int dx, int dy) {
+        if (snake == null || Math.abs(dx) + Math.abs(dy) > 1 || isGameOver() || isGameWon()) {
+            return false;
+        }
+
+        int x = snake.get(0).getX() + dx;
+        int y = snake.get(0).getY() + dy;
+
+        return isTile(x, y) && (!getTile(x, y).hasCollision() || getTile(x, y) == snake.get(snake.size() - 1));
+    }
+
+    private void move(int dx, int dy) {
+    	if (!canMove(dx, dy)) {
+    		throw new IllegalStateException("Not a valid move");
+    	}
+    	
+        Tile targetTile = getTile(snake.get(0).getX() + dx, snake.get(0).getY() + dy);
+
+        if (targetTile.isGoal()) {
+            isGameWon = true;
+        }
+
+        if (!targetTile.isFruit()) {
+            snake.get(snake.size() - 1).setAir();
+            snake.remove(snake.size() - 1);
+        }
+        snake.add(0, targetTile);
+        snake.get(0).setSnake();
+
+        if (isGameWon) {
+            return;
+        }
+
+        while (snakeInAir()) {
+            isGameOver = false;
+            for (Tile tile : snake) {
+                if (!isTile(tile.getX(), tile.getY() + 1)) {
+                    isGameOver = true;
+                }
+            }
+            if (isGameOver) {
+                break;
+            }
+
+            for (Tile tile : snake) {
+                tile.setAir();
+            }
+
+            ArrayList<Tile> newSnake = new ArrayList<>();
+            for (Tile tile : snake) {
+                Tile newTile = getTile(tile.getX(), tile.getY() + 1);
+                newTile.setSnake();
+                newSnake.add(newTile);
+            }
+            snake = newSnake;
+        }
+    }
+
+    private boolean snakeInAir() {
+        for (Tile tile : snake) {
+            if (isTile(tile.getX(), tile.getY() + 1) && getTile(tile.getX(), tile.getY() + 1).isGround()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public boolean isSnakeHead(Tile tile) {
+        return snake != null && tile == snake.get(0);
+    }
+
+    
+    public void moveUp() {
+        move(0, -1);
+	    System.out.println(this);
+    }
+
+    public void moveDown() {
+        move(0, 1);
+	    System.out.println(this);
+    }
+
+    public void moveLeft() {
+        move(-1, 0);
+	    System.out.println(this);
+    }
+
+    public void moveRight() {
+        move(1, 0);
+	    System.out.println(this);
+    }
+    
+    public List<Tile> getSnake() {
+    	return new ArrayList<>(snake);
+    }
+
+    @Override
+    public String toString() {
+        String representation = "";
+        if (isGameWon()) {
+            representation = "You Won!";
+        } else if (isGameOver()) {
+            representation = "You Lost!";
+        }
+
+
+        for (int y = 0; y < getHeight(); y++) {
+            for (int x = 0; x < getWidth(); x++) {
+                if (snake != null && snake.get(0) == getTile(x, y)) {
+                    representation = representation + "8";
+                } else {
+                    representation = representation + getTile(x, y).toString();
+                }
+            }
+            representation = representation + "\n";
+        }
+        return representation;
+    }
+
+}
diff --git a/foreksempel/src/main/java/of13/lf/GameApp.java b/foreksempel/src/main/java/of13/lf/GameApp.java
new file mode 100644
index 0000000..9ea9b36
--- /dev/null
+++ b/foreksempel/src/main/java/of13/lf/GameApp.java
@@ -0,0 +1,23 @@
+package of13.lf;
+
+import javafx.application.Application;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+
+import java.io.IOException;
+
+public class GameApp extends Application {
+
+    public static void main(String[] args) {
+        Application.launch(args);
+    }
+
+    @Override
+    public void start(Stage primaryStage) throws IOException {
+        primaryStage.setTitle("Snakebird");
+        primaryStage.setScene(new Scene(FXMLLoader.load(getClass().getResource("Game.fxml"))));
+        primaryStage.show();
+    }
+
+}
diff --git a/foreksempel/src/main/java/of13/lf/GameController.java b/foreksempel/src/main/java/of13/lf/GameController.java
new file mode 100644
index 0000000..7aeb8f5
--- /dev/null
+++ b/foreksempel/src/main/java/of13/lf/GameController.java
@@ -0,0 +1,164 @@
+package of13.lf;
+
+import javafx.fxml.FXML;
+import javafx.scene.text.Text;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.Pane;
+import javafx.scene.paint.Color;
+
+import java.io.FileNotFoundException;
+import java.util.Arrays;
+
+public class GameController {
+
+    private Game game;
+    private SaveHandler saveHandler = new SaveHandler();
+
+    @FXML
+    Pane board;
+    
+    @FXML
+    TextField filename;
+    
+    @FXML
+    Text fileNotFoundMessage;
+
+    @FXML
+    public void initialize() {
+        game = new Game(16, 12);
+        game.getTile(6, 11).setGround();
+        game.getTile(7, 11).setGround();
+        game.getTile(8, 11).setGround();
+        game.getTile(6, 10).setGround();
+        game.getTile(7, 10).setGround();
+        game.getTile(8, 10).setGround();
+        game.getTile(9, 10).setGround();
+        game.getTile(6, 9).setGround();
+        game.getTile(7, 9).setGround();
+        game.getTile(8, 9).setGround();
+        game.getTile(9, 9).setGround();
+        game.getTile(6, 8).setGround();
+        game.getTile(8, 6).setGround();
+        game.getTile(10, 6).setGround();
+        game.getTile(5, 5).setGround();
+        game.getTile(5, 6).setFruit();
+        game.getTile(9, 6).setFruit();
+        game.getTile(8, 3).setGoal();
+
+        game.createSnake(Arrays.asList(game.getTile(9, 8), game.getTile(8, 8)));
+             
+
+        createBoard();
+        drawBoard();
+    }
+
+    private void createBoard() {
+        board.getChildren().clear();
+        for (int y = 0; y < game.getHeight(); y++) {
+            for (int x = 0; x < game.getWidth(); x++) {
+                Pane tile = new Pane();
+                tile.setTranslateX(x * 20);
+                tile.setTranslateY(y * 20);
+                tile.setPrefWidth(20);
+                tile.setPrefHeight(20);
+                board.getChildren().add(tile);
+            }
+        }
+    }
+
+    private String getTileColor(Tile tile) {
+        if (game.isSnakeHead(tile)) {
+            return "#1db121";
+        } else if (tile.isSnake()) {
+            return "#24d628";
+        } else if (tile.isGround()) {
+            return "#a26f42";
+        } else if (tile.isFruit()) {
+            return "#e5303a";
+        } else if (tile.isGoal()) {
+            return "#f6ec5a";
+        }
+        return "#7bcaf2";
+    }
+
+    @FXML
+    void handleUp() {
+        game.moveUp();
+        drawBoard();
+    }
+
+    @FXML
+    void handleDown() {
+        game.moveDown();
+        drawBoard();
+    }
+
+    @FXML
+    void handleLeft() {
+        game.moveLeft();
+        drawBoard();
+    }
+
+    @FXML
+    void handleRight() {
+        game.moveRight();
+        drawBoard();
+    }
+    
+    private String getFilename() {
+    	String filename = this.filename.getText();
+    	if (filename.isEmpty()) {
+    		filename = "save_file";
+    	}
+    	return filename;
+    }
+    
+    @FXML
+    void handleSave() {
+    	try {
+    		saveHandler.save(getFilename(), game);
+    		fileNotFoundMessage.setVisible(false);
+    	} catch (FileNotFoundException e) {
+    		fileNotFoundMessage.setVisible(true);
+    	}
+    }
+    
+    @FXML
+    void handleLoad() {
+    	try {
+			game = saveHandler.load(getFilename());
+    		fileNotFoundMessage.setVisible(false);
+    	} catch (FileNotFoundException e) {
+    		fileNotFoundMessage.setVisible(true);
+		}
+    	createBoard();
+    	drawBoard();
+    }
+
+    private void drawBoard() {
+        for (int y = 0; y < game.getHeight(); y++) {
+            for (int x = 0; x < game.getWidth(); x++) {
+                board.getChildren().get(y * game.getWidth() + x).setStyle("-fx-background-color: " + getTileColor(game.getTile(x, y)));
+            }
+        }
+
+        if (game.isGameWon()) {
+            Text wonText = new Text();
+            wonText.setText("You Won!");
+            wonText.setFill(Color.GREEN);
+            wonText.setStyle("-fx-font-size: 40px;");
+            wonText.setTranslateX(((double) game.getWidth() * 20) / 2 - 80);
+            wonText.setTranslateY(((double) game.getHeight() * 20) / 2);
+            board.getChildren().add(wonText);
+        } else if (game.isGameOver()) {
+            Text lostText = new Text();
+            lostText.setText("You Lost!");
+            lostText.setStyle("-fx-font-size: 40px;");
+            lostText.setFill(Color.RED);
+            lostText.setTranslateX(((double) game.getWidth() * 20) / 2 - 80);
+            lostText.setTranslateY(((double) game.getHeight() * 20) / 2);
+            board.getChildren().add(lostText);
+        }
+    }
+
+}
diff --git a/foreksempel/src/main/java/of13/lf/SaveHandler.java b/foreksempel/src/main/java/of13/lf/SaveHandler.java
new file mode 100644
index 0000000..14c10e6
--- /dev/null
+++ b/foreksempel/src/main/java/of13/lf/SaveHandler.java
@@ -0,0 +1,78 @@
+package of13.lf;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+public class SaveHandler {
+
+	public final static String SAVE_FOLDER = "src/main/java/of13/saves/";
+
+	public void save(String filename, Game game) throws FileNotFoundException {
+		try (PrintWriter writer = new PrintWriter(getFilePath(filename))) {
+			writer.println(game.getWidth());
+			writer.println(game.getHeight());
+			writer.println(game.isGameOver());
+			writer.println(game.isGameWon());
+			for (int y = 0; y < game.getHeight(); y++) {
+				for (int x = 0; x < game.getWidth(); x++) {
+					writer.print(game.getTile(x, y).getType());
+				}
+			}
+
+			writer.println();
+			writer.println(game.getSnake().size());
+			for (Tile tile : game.getSnake()) {
+				writer.print(tile.getX());
+				writer.print(" ");
+				writer.println(tile.getY());
+				// Eventuelt
+				//writer.printf("%d %d\n", tile.getX(), tile.getY());
+			}
+		} 
+	}
+
+	public Game load(String filename) throws FileNotFoundException {
+		try (Scanner scanner = new Scanner(new File(getFilePath(filename)))) {
+			int width = scanner.nextInt();
+			int height = scanner.nextInt();
+			Game game = new Game(width, height);
+
+			if (scanner.nextBoolean()) {
+				game.setGameOver();
+			}
+
+			if (scanner.nextBoolean()) {
+				game.setGameWon();
+			}
+
+			scanner.nextLine();
+
+			String board = scanner.next();
+			for (int y = 0; y < height; y++) {
+				for (int x = 0; x < width; x++) {
+					char symbol = board.charAt(y * width + x);
+					game.getTile(x, y).setType(symbol);
+				}
+			}
+
+			int snakeLength = scanner.nextInt();
+			List<Tile> snake = new ArrayList<>();
+			for (int i = 0; i < snakeLength; i++) {
+				snake.add(game.getTile(scanner.nextInt(), scanner.nextInt()));
+			}
+			game.createSnake(snake);
+
+			return game;
+		}
+	}
+
+	public static String getFilePath(String filename) {
+		return SAVE_FOLDER + filename + ".txt";
+	}
+	
+
+}
diff --git a/foreksempel/src/main/java/of13/lf/Tile.java b/foreksempel/src/main/java/of13/lf/Tile.java
new file mode 100644
index 0000000..dbad866
--- /dev/null
+++ b/foreksempel/src/main/java/of13/lf/Tile.java
@@ -0,0 +1,94 @@
+package of13.lf;
+
+public class Tile {
+
+    private char type = 'a';
+    private int x;
+    private int y;
+
+    public Tile(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+    
+    public void setType(char symbol) {
+    	if ("asgf@s".indexOf(symbol) == -1) {
+    		throw new IllegalArgumentException("Not a valid state");
+    	}
+    	
+    	type = symbol;
+    }
+    
+    public char getType() {
+    	return type;
+    }
+
+    public void setAir() {
+        type = 'a';
+    }
+
+    public void setSnake() {
+        type = 's';
+    }
+
+    public void setGround() {
+        type = 'g';
+    }
+
+    public void setFruit() {
+        type = 'f';
+    }
+
+    public void setGoal() {
+        type = '@';
+    }
+
+    public boolean isAir() {
+        return type == 'a';
+    }
+
+    public boolean isSnake() {
+        return type == 's';
+    }
+
+    public boolean isGround() {
+        return type == 'g';
+    }
+
+    public boolean isFruit() {
+        return type == 'f';
+    }
+
+    public boolean isGoal() {
+        return type == '@';
+    }
+
+    public int getX() {
+        return x;
+    }
+
+    public int getY() {
+        return y;
+    }
+
+    public boolean hasCollision() {
+        return isGround() || isSnake();
+    }
+
+    @Override
+    public String toString() {
+        switch (type) {
+            case 'g':
+                return "#";
+            case '@':
+                return "@";
+            case 's':
+                return "O";
+            case 'f':
+                return "*";
+            case 'a':
+            default:
+                return " ";
+        }
+    }
+}
diff --git a/foreksempel/src/main/java/of13/saves/test-save.txt b/foreksempel/src/main/java/of13/saves/test-save.txt
new file mode 100644
index 0000000..5d73b86
--- /dev/null
+++ b/foreksempel/src/main/java/of13/saves/test-save.txt
@@ -0,0 +1,8 @@
+16
+12
+false
+false
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@aaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaafaagfgaaaaaaaaaaaaaaaaaaaaaaaaaaagassaaaaaaaaaaaaggggaaaaaaaaaaaaggggaaaaaaaaaaaagggaaaaaaa
+2
+9 8
+8 8
diff --git a/foreksempel/src/main/java/of13/v2020/kode/Assistant.java b/foreksempel/src/main/java/of13/v2020/kode/Assistant.java
new file mode 100644
index 0000000..9d845b2
--- /dev/null
+++ b/foreksempel/src/main/java/of13/v2020/kode/Assistant.java
@@ -0,0 +1,26 @@
+package of13.v2020.kode;
+
+public class Assistant extends Employee {
+
+	public Assistant(String name) {
+		super(name, "Assistant");
+	}
+
+	@Override
+	public boolean canPerformTask(String task) {
+		return task.equals("Arrange meeting") || task.equals("Send email");
+	}
+
+	public static void main(String[] args) {
+		//Employee employee = new Employee("Magnus", "Vitass");
+		//employee.performTask("Test");
+		
+		
+		Employee assistant = new Assistant("Halvard");
+		
+		assistant.performTask("Arrange meeting");
+		
+		assistant.performTask("Test");
+	}
+
+}
diff --git a/foreksempel/src/main/java/of13/v2020/kode/Boss.java b/foreksempel/src/main/java/of13/v2020/kode/Boss.java
new file mode 100644
index 0000000..2788f81
--- /dev/null
+++ b/foreksempel/src/main/java/of13/v2020/kode/Boss.java
@@ -0,0 +1,50 @@
+package of13.v2020.kode;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class Boss extends Employee {
+
+	private List<Employee> subordinates;
+	
+	public Boss(String name, List<Employee> subordinates) {
+		super(name, "Boss");
+		
+		if (subordinates.isEmpty()) {
+			throw new IllegalArgumentException("A boss needs at least one subordinate");
+		}
+		
+		this.subordinates = new ArrayList<>(subordinates);
+	}
+	
+	public Boss(String name, Employee... employees) {
+		this(name, Arrays.asList(employees));
+	}
+	
+	@Override
+	public void performTask(String task) {
+		subordinates.stream()
+					.filter((subordinate) -> subordinate.canPerformTask(task))
+					.findAny()
+					.orElseThrow(() -> new IllegalArgumentException("No subordinates can perform task: " + task))
+					.performTask(task);
+	}
+	
+	@Override
+	public boolean canPerformTask(String task) {
+		return subordinates.stream().anyMatch((subordinate) -> subordinate.canPerformTask(task));
+	}
+	
+	public static void main(String[] args) {
+		Assistant assitant = new Assistant("assitant1");
+		TemporaryEmployee temp = new TemporaryEmployee("temp", "Assistant", 1);
+		
+		Boss boss = new Boss("Halvard", assitant, temp);
+		
+		boss.performTask("Arrange meeting");
+		boss.performTask("Make video");
+		boss.performTask("Make video");
+	}
+
+}
diff --git a/foreksempel/src/main/java/of13/v2020/kode/Employee.java b/foreksempel/src/main/java/of13/v2020/kode/Employee.java
new file mode 100644
index 0000000..f6337b3
--- /dev/null
+++ b/foreksempel/src/main/java/of13/v2020/kode/Employee.java
@@ -0,0 +1,31 @@
+package of13.v2020.kode;
+
+public abstract class Employee {
+
+	private String name;
+	protected String role;
+	
+	public Employee(String name, String role) {
+		this.name = name;
+		this.role = role;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+	public String getRole() {
+		return role;
+	}
+	
+	public void performTask(String task) {
+		if (!canPerformTask(task)) {
+			throw new IllegalArgumentException(name + " can not perform task: " + task);
+		}
+		
+		System.out.println(name + " [" + role + "] performed task " + task);
+	}
+	
+	public abstract boolean canPerformTask(String task);
+	
+}
diff --git a/foreksempel/src/main/java/of13/v2020/kode/TemporaryEmployee.java b/foreksempel/src/main/java/of13/v2020/kode/TemporaryEmployee.java
new file mode 100644
index 0000000..08e55f5
--- /dev/null
+++ b/foreksempel/src/main/java/of13/v2020/kode/TemporaryEmployee.java
@@ -0,0 +1,45 @@
+package of13.v2020.kode;
+
+public class TemporaryEmployee extends Employee {
+
+	private int numberOfRemainingTasks;
+	
+	public TemporaryEmployee(String name, String role, int numberOfTasks) {
+		super(name, role);
+		
+		numberOfRemainingTasks = numberOfTasks;
+	}
+	
+	@Override
+	public void performTask(String task) {
+		if (numberOfRemainingTasks <= 0) {
+			throw new IllegalStateException(getName() + " has performed all their tasks");
+		}
+		
+		super.performTask(task);
+		
+		numberOfRemainingTasks--;
+		// numberOfRemainingTasks -= 1;
+		// numberOfRemainingTasks = numberOfRemainingTasks - 1;
+		
+		if (numberOfRemainingTasks == 0) {
+			role = "Quit";
+		}
+	}
+
+	@Override
+	public boolean canPerformTask(String task) {
+		return numberOfRemainingTasks > 0;
+	}
+	
+	
+	public static void main(String[] args) {
+		TemporaryEmployee employee = new TemporaryEmployee("Halvard", "Vitass", 2);
+		employee.performTask("Svare på mail");
+		System.out.println(employee.getRole());
+		employee.performTask("Svare på mail");
+		System.out.println(employee.getRole());
+		employee.performTask("Svare på mail");
+	}
+
+}
diff --git a/foreksempel/src/main/java/of13/v2020/lf/Assistant.java b/foreksempel/src/main/java/of13/v2020/lf/Assistant.java
new file mode 100644
index 0000000..5171481
--- /dev/null
+++ b/foreksempel/src/main/java/of13/v2020/lf/Assistant.java
@@ -0,0 +1,25 @@
+package of13.v2020.lf;
+
+public class Assistant extends Employee {
+
+	public Assistant(String name) {
+		super(name, "Assistant");
+	}
+
+	@Override
+	public boolean canPerformTask(String task) {
+		return task.equals("Arrange meeting") || task.equals("Send email");
+	}
+
+	public static void main(String[] args) {
+		//Employee employee = new Employee("Magnus", "Vitass");
+		//employee.performTask("Test");
+		
+		Employee assistant = new Assistant("Halvard");
+		
+		assistant.performTask("Arrange meeting");
+		
+		assistant.performTask("Test");
+	}
+	
+}
diff --git a/foreksempel/src/main/java/of13/v2020/lf/AssistantTest.java b/foreksempel/src/main/java/of13/v2020/lf/AssistantTest.java
new file mode 100644
index 0000000..d98361c
--- /dev/null
+++ b/foreksempel/src/main/java/of13/v2020/lf/AssistantTest.java
@@ -0,0 +1,53 @@
+package of13.v2020.lf;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class AssistantTest {
+	
+	private Assistant assistant;
+	
+	@Before
+	public void setUp() {
+		assistant = new Assistant("Halvard");
+	}
+	
+	@Test
+	public void testRole() {
+		assertEquals("The role of an assistant should always be \"Assistant\"", assistant.getRole(), "Assistant");
+	}
+	
+	@Test
+	public void testCanPerformTask() {
+		assertTrue("An assistant should always be able to arrange meetings", assistant.canPerformTask("Arrange meeting"));
+		assertTrue("An assistant should always be able to send emails", assistant.canPerformTask("Send email"));
+		assertFalse("An assistant should not be able to fire an employee", assistant.canPerformTask("Fire employee"));
+	}
+	
+	@Test
+	public void testPerformValidTask() {
+		assistant.performTask("Arrange meeting");
+		assistant.performTask("Send email");
+	}
+	
+	@Test
+	public void testPerformInvalidTask() {
+		try {
+			assistant.performTask("Fire employee");
+			fail("An assistant should not be able to fire employees");
+		} catch (IllegalArgumentException e) {
+			
+		}
+	}
+	
+	@Test(expected = IllegalArgumentException.class)
+	public void testPerformInvalidTask2() {
+		assistant.performTask("Fire employee");
+	}
+
+}
diff --git a/foreksempel/src/main/java/of13/v2020/lf/Boss.java b/foreksempel/src/main/java/of13/v2020/lf/Boss.java
new file mode 100644
index 0000000..6ffa1ec
--- /dev/null
+++ b/foreksempel/src/main/java/of13/v2020/lf/Boss.java
@@ -0,0 +1,50 @@
+package of13.v2020.lf;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class Boss extends Employee {
+
+	private List<Employee> subordinates;
+	
+	public Boss(String name, List<Employee> subordinates) {
+		super(name, "Boss");
+		
+		if (subordinates.isEmpty()) {
+			throw new IllegalArgumentException("A boss needs at least one subordinate");
+		}
+		
+		this.subordinates = new ArrayList<>(subordinates);
+	}
+	
+	public Boss(String name, Employee... employees) {
+		this(name, Arrays.asList(employees));
+	}
+	
+	@Override
+	public void performTask(String task) {
+		subordinates.stream()
+					.filter((subordinate) -> subordinate.canPerformTask(task))
+					.findAny()
+					.orElseThrow(() -> new IllegalArgumentException("No subordinates can perform task: " + task))
+					.performTask(task);
+	}
+	
+	@Override
+	public boolean canPerformTask(String task) {
+		return subordinates.stream().anyMatch((subordinate) -> subordinate.canPerformTask(task));
+	}
+	
+	public static void main(String[] args) {
+		Assistant assitant = new Assistant("assitant1");
+		TemporaryEmployee temp = new TemporaryEmployee("temp", "Assistant", 1);
+		
+		Boss boss = new Boss("Halvard", assitant, temp);
+		
+		boss.performTask("Arrange meeting");
+		boss.performTask("Make video");
+		boss.performTask("Make video");
+	}
+
+}
diff --git a/foreksempel/src/main/java/of13/v2020/lf/BossTest.java b/foreksempel/src/main/java/of13/v2020/lf/BossTest.java
new file mode 100644
index 0000000..91e202b
--- /dev/null
+++ b/foreksempel/src/main/java/of13/v2020/lf/BossTest.java
@@ -0,0 +1,56 @@
+package of13.v2020.lf;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class BossTest {
+	
+	private Boss boss;
+
+	@Before
+	public void setUp() {
+		Assistant assistant = new Assistant("Halvard");
+		Assistant assistant1 = new Assistant("Magnus");
+		
+		boss = new Boss("Børge", assistant, assistant1);
+	}
+	
+	@Test(expected = IllegalArgumentException.class)
+	public void testConstructorWithoutSubordinates() {
+		new Boss("Børge");
+	}
+	
+	@Test
+	public void testRole() {
+		assertEquals("The role of a boss should always be \"Boss\"", boss.getRole(), "Boss");
+	}
+	
+	@Test
+	public void testCanPerformTask() {
+		assertTrue("A boss should able to perform tasks that its subordinates can perform", boss.canPerformTask("Arrange meeting"));
+		assertTrue("A boss should able to perform tasks that its subordinates can perform", boss.canPerformTask("Send email"));
+		assertFalse("A boss should not able to perform tasks that its subordinates can not perform", boss.canPerformTask("Fire employee"));
+	}
+	
+	@Test
+	public void testPerformTask() {
+		try {
+			boss.performTask("Arrange meeting");
+		} catch (IllegalArgumentException e) {
+			fail("A boss should able to perform tasks that its subordinates can perform");
+		}
+		
+		try {
+			boss.performTask("Fire employee");
+			fail("A boss should not able to perform tasks that its subordinates can not perform");
+		} catch (IllegalArgumentException e) {
+			
+		}
+	}
+	
+}
diff --git a/foreksempel/src/main/java/of13/v2020/lf/Employee.java b/foreksempel/src/main/java/of13/v2020/lf/Employee.java
new file mode 100644
index 0000000..2155377
--- /dev/null
+++ b/foreksempel/src/main/java/of13/v2020/lf/Employee.java
@@ -0,0 +1,31 @@
+package of13.v2020.lf;
+
+public abstract class Employee {
+
+	private String name;
+	protected String role;
+	
+	public Employee(String name, String role) {
+		this.name = name;
+		this.role = role;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+	public String getRole() {
+		return role;
+	}
+	
+	public void performTask(String task) {
+		if (!canPerformTask(task)) {
+			throw new IllegalArgumentException(name + " can not perform task: " + task);
+		}
+		
+		System.out.println(name + " [" + role + "] performed task " + task);
+	}
+	
+	public abstract boolean canPerformTask(String task);
+	
+}
diff --git a/foreksempel/src/main/java/of13/v2020/lf/TemporaryEmployee.java b/foreksempel/src/main/java/of13/v2020/lf/TemporaryEmployee.java
new file mode 100644
index 0000000..be52c64
--- /dev/null
+++ b/foreksempel/src/main/java/of13/v2020/lf/TemporaryEmployee.java
@@ -0,0 +1,45 @@
+package of13.v2020.lf;
+
+public class TemporaryEmployee extends Employee {
+
+	private int numberOfRemainingTasks;
+	
+	public TemporaryEmployee(String name, String role, int numberOfTasks) {
+		super(name, role);
+		
+		numberOfRemainingTasks = numberOfTasks;
+	}
+	
+	@Override
+	public void performTask(String task) {
+		if (numberOfRemainingTasks <= 0) {
+			throw new IllegalStateException(getName() + " has performed all their tasks");
+		}
+		
+		super.performTask(task);
+		
+		numberOfRemainingTasks--;
+		// numberOfRemainingTasks -= 1;
+		// numberOfRemainingTasks = numberOfRemainingTasks - 1;
+		
+		if (numberOfRemainingTasks == 0) {
+			role = "Quit";
+		}
+	}
+
+	@Override
+	public boolean canPerformTask(String task) {
+		return numberOfRemainingTasks > 0;
+	}
+	
+	
+	public static void main(String[] args) {
+		TemporaryEmployee employee = new TemporaryEmployee("Halvard", "Vitass", 2);
+		employee.performTask("Svare på mail");
+		System.out.println(employee.getRole());
+		employee.performTask("Svare på mail");
+		System.out.println(employee.getRole());
+		employee.performTask("Svare på mail");
+	}
+
+}
diff --git a/foreksempel/src/main/java/of13/v2020/lf/TemporaryEmployeeTest.java b/foreksempel/src/main/java/of13/v2020/lf/TemporaryEmployeeTest.java
new file mode 100644
index 0000000..15f2dc4
--- /dev/null
+++ b/foreksempel/src/main/java/of13/v2020/lf/TemporaryEmployeeTest.java
@@ -0,0 +1,53 @@
+package of13.v2020.lf;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class TemporaryEmployeeTest {
+
+	private TemporaryEmployee temp;
+	
+	@Before
+	public void setUp() {
+		temp = new TemporaryEmployee("Halvard", "Vitass", 1);
+	}
+	
+	@Test
+	public void testGetRole() {
+		assertEquals("A temporary employee should have the role given in the constructor", temp.getRole(), "Vitass");
+	}
+	
+	@Test
+	public void testCanPerformTask() {
+		assertTrue("A temporary employee with remaining tasks should be able to perform any task", temp.canPerformTask("Test task"));
+		
+		TemporaryEmployee temp2 = new TemporaryEmployee("Magnus", "Vitass", 0);
+		assertFalse("A temporary employee with no remaining tasks should not be able to perform a task", temp2.canPerformTask("Test task"));
+	}
+	
+	@Test
+	public void testPerformTask() {
+		try {
+			temp.performTask("Test task");
+		} catch (IllegalArgumentException | IllegalStateException e) {
+			fail("A temporary employee with remaining tasks should be able to perform any task");
+		}
+		
+		assertEquals("A temporary employee with no remaining tasks should have its role set to \"Quit\"", temp.getRole(), "Quit");
+		
+		try {
+			temp.performTask("Test task");
+			fail("A temporary employee with no remaining tasks should not be able to perform any task");
+		} catch (IllegalStateException e) {
+			
+		}
+	}
+	
+	
+	
+}
diff --git a/foreksempel/src/main/java/of6/kode/Game.java b/foreksempel/src/main/java/of6/kode/Game.java
new file mode 100644
index 0000000..7c0c5da
--- /dev/null
+++ b/foreksempel/src/main/java/of6/kode/Game.java
@@ -0,0 +1,221 @@
+package of6.kode;
+
+import java.util.ArrayList;
+
+public class Game {
+	
+	private int height;
+	private int width;
+	private Tile[][] board;
+    private ArrayList<Tile> snake;
+    private boolean isGameWon = false;
+    private boolean isGameOver = false;
+	
+    // Oppgave 1 a)
+	public Game(int width, int height) {
+		this.height = height;
+		this.width = width;
+		
+		this.board = new Tile[height][width];
+		
+		for (int y = 0; y < height; y++) {
+			for (int x = 0; x < width; x++) {
+				board[y][x] = new Tile(x, y);
+			}
+		}
+	}
+
+    // Oppgave 1 b)
+	public boolean isTile(int x, int y) {
+		return x >= 0 && y >= 0 && x < getWidth() && y < getHeight();
+	}
+
+    // Oppgave 1 c)
+	public Tile getTile(int x, int y) {
+		if (!isTile(x, y)) {
+			throw new IllegalArgumentException("Coordinates out of bounds");
+		}
+		return this.board[y][x];
+	}
+
+	public int getHeight() {
+		return height;
+	}
+
+
+	public int getWidth() {
+		return width;
+	}
+	
+	// Oppgave 3 a)
+	public void addSnakeToTiles(Tile snakeHead, Tile snakeBody) {
+		if (snake != null) {
+            throw new IllegalStateException("Snake already created");
+        }
+		
+		snake = new ArrayList<Tile>();
+		
+		snakeHead.setSnake();
+		snakeBody.setSnake();
+		snake.add(snakeHead);
+		snake.add(snakeBody);
+	}
+
+    public void moveUp() {
+        move(0, -1);
+	    System.out.println(this);
+    }
+
+    public void moveDown() {
+        move(0, 1);
+	    System.out.println(this);
+    }
+
+    public void moveLeft() {
+        move(-1, 0);
+	    System.out.println(this);
+    }
+
+    public void moveRight() {
+        move(1, 0);
+	    System.out.println(this);
+    }
+
+	
+	// Oppgave 4 a)
+	private boolean canMoveTo(int dx, int dy) {
+		
+		// Snake head coordinates
+		int targetX = snake.get(0).getX() + dx;
+		int targetY = snake.get(0).getY() + dy;
+		
+		if(!isTile(targetX, targetY)) {
+			return false;
+		}
+		
+		Tile targetTile = getTile(targetX, targetY);
+		boolean tileIsSnakeTail = (targetTile == snake.get(snake.size()-1));
+		
+		return !targetTile.hasCollision() || tileIsSnakeTail;
+	}
+
+	// Oppgave 4 b)
+	private void move(int dx, int dy) {
+		if(snake == null || isGameWon || isGameOver) {
+    		throw new IllegalStateException("Not a valid game state for move");
+		}
+		if(!canMoveTo(dx, dy)) {
+			throw new IllegalArgumentException("Not a valid move");
+		}
+
+		int targetX = snake.get(0).getX() + dx;
+		int targetY = snake.get(0).getY() + dy;
+		Tile targetTile = getTile(targetX, targetY);
+
+		
+		// Oppgave 5 b)
+        if (targetTile.isGoal()) {
+            isGameWon = true;
+        }
+		
+
+		// Oppgave 5 a)
+        if (!targetTile.isFruit()) {
+        	snake.get(snake.size()-1).setAir();
+        	snake.remove(snake.size()-1);
+        }
+		
+		snake.add(0, targetTile);
+		targetTile.setSnake();
+		
+
+        if (isGameWon) {
+            return;
+        }
+
+        while (snakeInAir()) {
+            isGameOver = false;
+            for (Tile tile : snake) {
+                if (!isTile(tile.getX(), tile.getY() + 1)) {
+                    isGameOver = true;
+                }
+            }
+            if (isGameOver) {
+                break;
+            }
+
+            for (Tile tile : snake) {
+                tile.setAir();
+            }
+
+            ArrayList<Tile> newSnake = new ArrayList<>();
+            for (Tile tile : snake) {
+                Tile newTile = getTile(tile.getX(), tile.getY() + 1);
+                newTile.setSnake();
+                newSnake.add(newTile);
+            }
+            snake = newSnake;
+        }
+	}
+	
+    private boolean snakeInAir() {
+        for (Tile tile : snake) {
+            if (isTile(tile.getX(), tile.getY() + 1) && getTile(tile.getX(), tile.getY() + 1).isGround()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    // Oppgave 2
+	@Override
+	public String toString() {
+		String boardString = "";
+		for (int y = 0; y < getHeight(); y++) {
+			for (int x = 0; x < getWidth(); x++) {
+				if (getTile(x, y) == snake.get(0)) {
+					boardString += "e";
+				} else {
+					boardString += getTile(x, y);
+				}
+			}
+			boardString += "\n";
+		}
+		// Oppgave 5b
+		if (isGameWon) {
+			boardString += "\n\nGame won!";
+		} else if (isGameOver) {
+			boardString = "\n\nYou Lost!";
+        }
+		return boardString;
+	}
+	
+	public static void main(String[] args) {
+	    Game game = new Game(16, 12);
+	    game.getTile(6, 11).setGround();
+	    game.getTile(7, 11).setGround();
+	    game.getTile(8, 11).setGround();
+	    game.getTile(6, 10).setGround();
+	    game.getTile(7, 10).setGround();
+	    game.getTile(8, 10).setGround();
+	    game.getTile(9, 10).setGround();
+	    game.getTile(6, 9).setGround();
+	    game.getTile(7, 9).setGround();
+	    game.getTile(8, 9).setGround();
+	    game.getTile(9, 9).setGround();
+	    game.getTile(6, 8).setGround();
+	    game.getTile(8, 6).setGround();
+	    game.getTile(10, 6).setGround();
+	    game.getTile(5, 5).setGround();
+	    game.getTile(5, 6).setFruit();
+	    game.getTile(9, 6).setFruit();
+	    game.getTile(8, 3).setGoal();
+
+	    game.addSnakeToTiles(game.getTile(8, 5), game.getTile(9, 5));
+	    System.out.println(game);
+	    game.moveLeft();
+	    game.moveLeft();
+	    
+	}
+
+}
diff --git a/foreksempel/src/main/java/of6/kode/Oppgave3.txt b/foreksempel/src/main/java/of6/kode/Oppgave3.txt
new file mode 100644
index 0000000..de0d583
--- /dev/null
+++ b/foreksempel/src/main/java/of6/kode/Oppgave3.txt
@@ -0,0 +1,21 @@
+game = new Game(16, 12);
+game.getTile(6, 11).setGround();
+game.getTile(7, 11).setGround();
+game.getTile(8, 11).setGround();
+game.getTile(6, 10).setGround();
+game.getTile(7, 10).setGround();
+game.getTile(8, 10).setGround();
+game.getTile(9, 10).setGround();
+game.getTile(6, 9).setGround();
+game.getTile(7, 9).setGround();
+game.getTile(8, 9).setGround();
+game.getTile(9, 9).setGround();
+game.getTile(6, 8).setGround();
+game.getTile(8, 6).setGround();
+game.getTile(10, 6).setGround();
+game.getTile(5, 5).setGround();
+game.getTile(5, 6).setFruit();
+game.getTile(9, 6).setFruit();
+game.getTile(8, 3).setGoal();
+
+game.addSnakeToTiles(game.getTile(9, 8), game.getTile(8, 8));
diff --git a/foreksempel/src/main/java/of6/kode/Oppgave4.txt b/foreksempel/src/main/java/of6/kode/Oppgave4.txt
new file mode 100644
index 0000000..e1d8b8b
--- /dev/null
+++ b/foreksempel/src/main/java/of6/kode/Oppgave4.txt
@@ -0,0 +1 @@
+tile.setStyle("-fx-border-color: black; -fx-border-width: 1px;");
\ No newline at end of file
diff --git a/foreksempel/src/main/java/of6/kode/Oppgave5-farger.txt b/foreksempel/src/main/java/of6/kode/Oppgave5-farger.txt
new file mode 100644
index 0000000..186dc10
--- /dev/null
+++ b/foreksempel/src/main/java/of6/kode/Oppgave5-farger.txt
@@ -0,0 +1,5 @@
+Slange: #24d628
+Bakke: #a26f42
+Frukt: #e5303a
+Mål: #f6ec5a
+Luft: #7bcaf2
\ No newline at end of file
diff --git a/foreksempel/src/main/java/of6/kode/Oppgave5-test.txt b/foreksempel/src/main/java/of6/kode/Oppgave5-test.txt
new file mode 100644
index 0000000..db929b0
--- /dev/null
+++ b/foreksempel/src/main/java/of6/kode/Oppgave5-test.txt
@@ -0,0 +1,5 @@
+System.out.println(getTileColor(game.getTile(8, 8)));
+System.out.println(getTileColor(game.getTile(8, 6)));
+System.out.println(getTileColor(game.getTile(5, 6)));
+System.out.println(getTileColor(game.getTile(8, 3)));
+System.out.println(getTileColor(game.getTile(1, 8)));
\ No newline at end of file
diff --git a/foreksempel/src/main/java/of6/kode/Tile.java b/foreksempel/src/main/java/of6/kode/Tile.java
new file mode 100644
index 0000000..e348212
--- /dev/null
+++ b/foreksempel/src/main/java/of6/kode/Tile.java
@@ -0,0 +1,70 @@
+package of6.kode;
+
+public class Tile {
+
+    private char type = ' ';
+    private int x;
+    private int y;
+
+    public Tile(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public void setAir() {
+        type = ' ';
+    }
+
+    public void setSnake() {
+        type = 'o';
+    }
+
+    public void setGround() {
+        type = '#';
+    }
+
+    public void setFruit() {
+        type = 'f';
+    }
+
+    public void setGoal() {
+        type = '@';
+    }
+
+    public boolean isAir() {
+        return type == ' ';
+    }
+
+    public boolean isSnake() {
+        return type == 'o';
+    }
+
+    public boolean isGround() {
+        return type == '#';
+    }
+
+    public boolean isFruit() {
+        return type == 'f';
+    }
+
+    public boolean isGoal() {
+        return type == '@';
+    }
+
+    public int getX() {
+        return x;
+    }
+
+    public int getY() {
+        return y;
+    }
+
+    public boolean hasCollision() {
+        return isGround() || isSnake();
+    }
+
+    @Override
+    public String toString() {
+        return Character.toString(type);
+    }
+}
diff --git a/foreksempel/src/main/java/of6/lf/Game.fxml b/foreksempel/src/main/java/of6/lf/Game.fxml
new file mode 100644
index 0000000..60a5797
--- /dev/null
+++ b/foreksempel/src/main/java/of6/lf/Game.fxml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.Button?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.ColumnConstraints?>
+<?import javafx.scene.layout.GridPane?>
+<?import javafx.scene.layout.Pane?>
+<?import javafx.scene.layout.RowConstraints?>
+
+<AnchorPane prefHeight="600.0" prefWidth="480.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="of6.lf.GameController">
+   <children>
+      <GridPane prefHeight="600.0" prefWidth="480.0">
+        <columnConstraints>
+          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
+        </columnConstraints>
+        <rowConstraints>
+          <RowConstraints maxHeight="400.0" minHeight="10.0" prefHeight="400.0" vgrow="SOMETIMES" />
+          <RowConstraints maxHeight="200.0" minHeight="10.0" prefHeight="200.0" vgrow="SOMETIMES" />
+        </rowConstraints>
+         <children>
+            <Pane GridPane.rowIndex="1">
+               <children>
+                  <Button layoutX="224.0" layoutY="61.0" mnemonicParsing="false" onAction="#handleUp" text="Opp" />
+                  <Button layoutX="224.0" layoutY="102.0" mnemonicParsing="false" onAction="#handleDown" text="Ned" />
+                  <Button layoutX="155.0" layoutY="102.0" mnemonicParsing="false" onAction="#handleLeft" text="Venstre" />
+                  <Button layoutX="274.0" layoutY="102.0" mnemonicParsing="false" onAction="#handleRight" text="Høyre" />
+                  <Button layoutX="409.0" layoutY="159.0" mnemonicParsing="false" onAction="#handleReset" text="Restart" />
+               </children>
+            </Pane>
+            <Pane fx:id="board" />
+         </children>
+      </GridPane>
+   </children>
+</AnchorPane>
diff --git a/foreksempel/src/main/java/of6/lf/Game.java b/foreksempel/src/main/java/of6/lf/Game.java
new file mode 100644
index 0000000..d32207c
--- /dev/null
+++ b/foreksempel/src/main/java/of6/lf/Game.java
@@ -0,0 +1,237 @@
+package of6.lf;
+
+import java.util.ArrayList;
+
+public class Game {
+	
+	private int height;
+	private int width;
+	private Tile[][] board;
+    private ArrayList<Tile> snake;
+    private boolean isGameWon = false;
+    private boolean isGameOver = false;
+	
+    // Oppgave 1 a)
+	public Game(int width, int height) {
+		this.height = height;
+		this.width = width;
+
+		this.board = new Tile[height][width];
+		
+		for (int y = 0; y < height; y++) {
+			for (int x = 0; x < width; x++) {
+				board[y][x] = new Tile(x, y);
+			}
+		}
+	}
+	
+    // Oppgave 1 b)
+	public boolean isTile(int x, int y) {
+		return x >= 0 && y >= 0 && x < getWidth() && y < getHeight();
+	}
+
+    // Oppgave 1 c)
+	public Tile getTile(int x, int y) {
+		if (!isTile(x, y)) {
+			throw new IllegalArgumentException("Coordinates out of bounds");
+		}
+		return this.board[y][x];
+	}
+
+	public int getHeight() {
+		return height;
+	}
+
+
+	public int getWidth() {
+		return width;
+	}
+	
+	// Oppgave 3 a)
+	public void addSnakeToTiles(Tile snakeHead, Tile snakeBody) {
+		if (snake != null) {
+            throw new IllegalStateException("Snake already created");
+        }
+		
+		snake = new ArrayList<Tile>();
+		
+		snakeHead.setSnake();
+		snakeBody.setSnake();
+		snake.add(snakeHead);
+		snake.add(snakeBody);
+	}
+
+    public void moveUp() {
+        move(0, -1);
+	    System.out.println(this);
+    }
+
+    public void moveDown() {
+        move(0, 1);
+	    System.out.println(this);
+    }
+
+    public void moveLeft() {
+        move(-1, 0);
+	    System.out.println(this);
+    }
+
+    public void moveRight() {
+        move(1, 0);
+	    System.out.println(this);
+    }
+
+	
+	// Oppgave 4 a)
+	private boolean canMoveTo(int dx, int dy) {
+		
+		// Snake head coordinates
+		int targetX = snake.get(0).getX() + dx;
+		int targetY = snake.get(0).getY() + dy;
+		
+		if(!isTile(targetX, targetY)) {
+			return false;
+		}
+		
+		Tile targetTile = getTile(targetX, targetY);
+		boolean tileIsSnakeTail = (targetTile == snake.get(snake.size()-1));
+		
+		return !targetTile.hasCollision() || tileIsSnakeTail;
+	}
+
+	// Oppgave 4 b)
+	private void move(int dx, int dy) {
+		if(snake == null || isGameWon || isGameOver) {
+    		throw new IllegalStateException("Not a valid game state for move");
+		}
+		if(!canMoveTo(dx, dy)) {
+			throw new IllegalArgumentException("Not a valid move");
+		}
+
+		int targetX = snake.get(0).getX() + dx;
+		int targetY = snake.get(0).getY() + dy;
+		Tile targetTile = getTile(targetX, targetY);
+
+		
+		// Oppgave 5 b)
+        if (targetTile.isGoal()) {
+            isGameWon = true;
+        }
+		
+
+		// Oppgave 5 a)
+        if (!targetTile.isFruit()) {
+        	snake.get(snake.size()-1).setAir();
+        	snake.remove(snake.size()-1);
+        }
+		
+		snake.add(0, targetTile);
+		targetTile.setSnake();
+		
+
+        if (isGameWon) {
+            return;
+        }
+
+        while (snakeInAir()) {
+            isGameOver = false;
+            for (Tile tile : snake) {
+                if (!isTile(tile.getX(), tile.getY() + 1)) {
+                    isGameOver = true;
+                }
+            }
+            if (isGameOver) {
+                break;
+            }
+
+            for (Tile tile : snake) {
+                tile.setAir();
+            }
+
+            ArrayList<Tile> newSnake = new ArrayList<>();
+            for (Tile tile : snake) {
+                Tile newTile = getTile(tile.getX(), tile.getY() + 1);
+                newTile.setSnake();
+                newSnake.add(newTile);
+            }
+            snake = newSnake;
+        }
+	}
+	
+    private boolean snakeInAir() {
+        for (Tile tile : snake) {
+            if (isTile(tile.getX(), tile.getY() + 1) && getTile(tile.getX(), tile.getY() + 1).isGround()) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    
+    
+    // Ekstra metoder lagt til i ØF 6 (i videoene som kom ut i etterkant):
+    public boolean isSnakeHead(Tile tile) {
+    	return tile == snake.get(0);
+    }
+    
+    public boolean isGameWon() {
+		return isGameWon;
+	}
+    
+    public boolean isGameOver() {
+		return isGameOver;
+    }
+	
+	
+    // Oppgave 2
+	@Override
+	public String toString() {
+		String boardString = "";
+		for (int y = 0; y < getHeight(); y++) {
+			for (int x = 0; x < getWidth(); x++) {
+				if (getTile(x, y) == snake.get(0)) {
+					boardString += "e";
+				} else {
+					boardString += getTile(x, y);
+				}
+			}
+			boardString += "\n";
+		}
+		// Oppgave 5b
+		if (isGameWon) {
+			boardString += "\n\nGame won!";
+		} else if (isGameOver) {
+			boardString = "\n\nYou Lost!";
+        }
+		return boardString;
+	}
+	
+	public static void main(String[] args) {
+	    Game game = new Game(16, 12);
+	    game.getTile(6, 11).setGround();
+	    game.getTile(7, 11).setGround();
+	    game.getTile(8, 11).setGround();
+	    game.getTile(6, 10).setGround();
+	    game.getTile(7, 10).setGround();
+	    game.getTile(8, 10).setGround();
+	    game.getTile(9, 10).setGround();
+	    game.getTile(6, 9).setGround();
+	    game.getTile(7, 9).setGround();
+	    game.getTile(8, 9).setGround();
+	    game.getTile(9, 9).setGround();
+	    game.getTile(6, 8).setGround();
+	    game.getTile(8, 6).setGround();
+	    game.getTile(10, 6).setGround();
+	    game.getTile(5, 5).setGround();
+	    game.getTile(5, 6).setFruit();
+	    game.getTile(9, 6).setFruit();
+	    game.getTile(8, 3).setGoal();
+
+	    game.addSnakeToTiles(game.getTile(8, 5), game.getTile(9, 5));
+	    System.out.println(game);
+	    game.moveLeft();
+	    game.moveLeft();
+	    
+	}
+
+}
diff --git a/foreksempel/src/main/java/of6/lf/GameApp.java b/foreksempel/src/main/java/of6/lf/GameApp.java
new file mode 100644
index 0000000..bb43e10
--- /dev/null
+++ b/foreksempel/src/main/java/of6/lf/GameApp.java
@@ -0,0 +1,25 @@
+package of6.lf;
+
+import javafx.application.Application;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Parent;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+
+// Oppgave 2
+public class GameApp extends Application {
+
+    @Override
+    public void start(Stage stage) throws Exception {
+        Parent parent = FXMLLoader.load(getClass().getResource("Game.fxml"));
+        stage.setTitle("Snakebird");
+        stage.setScene(new Scene(parent));
+        stage.show();
+    }
+
+    public static void main(String[] args) {
+        launch(GameApp.class, args);
+    }
+
+
+}
diff --git a/foreksempel/src/main/java/of6/lf/GameController.java b/foreksempel/src/main/java/of6/lf/GameController.java
new file mode 100644
index 0000000..a30388d
--- /dev/null
+++ b/foreksempel/src/main/java/of6/lf/GameController.java
@@ -0,0 +1,151 @@
+package of6.lf;
+
+import javafx.fxml.FXML;
+import javafx.scene.layout.Pane;
+import javafx.scene.paint.Color;
+import javafx.scene.text.Text;
+
+public class GameController {
+
+	// Oppgave 3
+	private Game game;
+	
+	@FXML
+	Pane board;
+
+	// Oppgave 11 (ekstra)
+	@FXML Text winText = new Text();
+	@FXML Text loseText = new Text();
+	
+	// Oppgave 3
+	@FXML
+	public void initialize() {
+		setInitialGameState();
+		createBoard();
+		drawBoard();
+	
+	}
+
+	// Oppgave 11 (ekstra)
+	private void setInitialGameState() {
+		game = new Game(16, 12);
+		game.getTile(6, 11).setGround();
+		game.getTile(7, 11).setGround();
+		game.getTile(8, 11).setGround();
+		game.getTile(6, 10).setGround();
+		game.getTile(7, 10).setGround();
+		game.getTile(8, 10).setGround();
+		game.getTile(9, 10).setGround();
+		game.getTile(6, 9).setGround();
+		game.getTile(7, 9).setGround();
+		game.getTile(8, 9).setGround();
+		game.getTile(9, 9).setGround();
+		game.getTile(6, 8).setGround();
+		game.getTile(8, 6).setGround();
+		game.getTile(10, 6).setGround();
+		game.getTile(5, 5).setGround();
+		game.getTile(5, 6).setFruit();
+		game.getTile(9, 6).setFruit();
+		game.getTile(8, 3).setGoal();
+
+		game.addSnakeToTiles(game.getTile(9, 8), game.getTile(8, 8));
+		
+	}
+	
+	// Oppgave 4
+	private void createBoard() {
+		board.getChildren().clear();
+		for (int y = 0; y < game.getHeight(); y++) {
+			for (int x = 0; x < game.getWidth(); x++) {
+				Pane tile = new Pane();
+				tile.setTranslateX(x*30);
+				tile.setTranslateY(y*30);
+				tile.setPrefWidth(30);
+				tile.setPrefHeight(30);
+				tile.setStyle("-fx-border-color: black; -fx-border-width: 1px;");
+				board.getChildren().add(tile);
+			}
+		}
+	}
+	
+	// Oppgave 6
+	private void drawBoard() {
+		for (int y = 0; y < game.getHeight(); y++) {
+			for (int x = 0; x < game.getWidth(); x++) {
+				board.getChildren().get(y*game.getWidth() + x).setStyle("-fx-background-color: " + getTilecolor(game.getTile(x, y)) + ";");
+			}
+		}
+		
+		// Oppgave 10
+		if(game.isGameWon()) {
+			winText.setText("Du vant!");
+			winText.setStyle("-fx-font-size: 40px");
+			winText.setFill(Color.GREEN);
+			winText.setTranslateX(160.0);
+			winText.setTranslateY(200.0);
+			board.getChildren().add(winText);
+		} else if(game.isGameOver()) {
+			loseText.setText("Game Over");
+			loseText.setStyle("-fx-font-size: 40px");
+			loseText.setFill(Color.RED);
+			loseText.setTranslateX(160.0);
+			loseText.setTranslateY(200.0);
+			board.getChildren().add(loseText);
+		}
+	}
+	
+	// Oppgave 8
+	@FXML
+	public void handleUp() {
+		game.moveUp();
+		drawBoard();
+	}
+
+	@FXML
+	public void handleDown() {
+		game.moveDown();
+		drawBoard();
+	}
+
+	@FXML
+	public void handleLeft() {
+		game.moveLeft();
+		drawBoard();
+	}
+	
+	@FXML
+	public void handleRight() {
+		game.moveRight();
+		drawBoard();
+	}
+
+	@FXML
+	public void handleReset() {
+		if (board.getChildren().contains(loseText)) {
+			board.getChildren().remove(loseText);
+		}
+		if (board.getChildren().contains(winText)) {
+			board.getChildren().remove(winText);
+		}
+		setInitialGameState();
+		drawBoard();
+	}
+	
+	// Oppgave 5
+    private String getTilecolor(Tile tile) {
+    	if (game.isSnakeHead(tile)) { 
+    		// Oppgave 7
+    		return "#1db121";
+    	} else if(tile.isSnake()) {
+    		return "#24d628";
+    	} else if(tile.isGround()) {
+    		return "#a26f42";
+    	} else if(tile.isFruit()) {
+    		return "#e5303a";
+    	} else if(tile.isGoal()) {
+    		return "#f6ec5a";
+    	} else {
+    		return "#7bcaf2";
+    	}
+    }
+}
diff --git a/foreksempel/src/main/java/of6/lf/Tile.java b/foreksempel/src/main/java/of6/lf/Tile.java
new file mode 100644
index 0000000..75700f4
--- /dev/null
+++ b/foreksempel/src/main/java/of6/lf/Tile.java
@@ -0,0 +1,70 @@
+package of6.lf;
+
+public class Tile {
+
+    private char type = ' ';
+    private int x;
+    private int y;
+
+    public Tile(int x, int y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public void setAir() {
+        type = ' ';
+    }
+
+    public void setSnake() {
+        type = 'o';
+    }
+
+    public void setGround() {
+        type = '#';
+    }
+
+    public void setFruit() {
+        type = 'f';
+    }
+
+    public void setGoal() {
+        type = '@';
+    }
+
+    public boolean isAir() {
+        return type == ' ';
+    }
+
+    public boolean isSnake() {
+        return type == 'o';
+    }
+
+    public boolean isGround() {
+        return type == '#';
+    }
+
+    public boolean isFruit() {
+        return type == 'f';
+    }
+
+    public boolean isGoal() {
+        return type == '@';
+    }
+
+    public int getX() {
+        return x;
+    }
+
+    public int getY() {
+        return y;
+    }
+
+    public boolean hasCollision() {
+        return isGround() || isSnake();
+    }
+
+    @Override
+    public String toString() {
+        return Character.toString(type);
+    }
+}
diff --git a/foreksempel/src/main/java/uke2/Random100.java b/foreksempel/src/main/java/uke2/Random100.java
index 51ab199..3845248 100644
--- a/foreksempel/src/main/java/uke2/Random100.java
+++ b/foreksempel/src/main/java/uke2/Random100.java
@@ -8,12 +8,12 @@ public int nextInt() {
     Random random = new Random();
     return random.nextInt(100);
 }
+    int test;
 
     public static void main(String[] args) {
         Random100 ra = new Random100();
         System.out.println(ra.nextInt());
-        
-
+    
     }
 
 }
\ No newline at end of file
diff --git a/foreksempel/src/test/java/of13/kode/.gitinclude b/foreksempel/src/test/java/of13/kode/.gitinclude
new file mode 100644
index 0000000..e69de29
diff --git a/foreksempel/src/test/java/of13/lf/GameTest.java b/foreksempel/src/test/java/of13/lf/GameTest.java
new file mode 100644
index 0000000..1dc793c
--- /dev/null
+++ b/foreksempel/src/test/java/of13/lf/GameTest.java
@@ -0,0 +1,103 @@
+package of13.lf;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+public class GameTest {
+	
+    private Game game;
+    
+	private void createBoard() {
+        game = new Game(16, 12);
+        game.getTile(6, 11).setGround();
+        game.getTile(7, 11).setGround();
+        game.getTile(8, 11).setGround();
+        game.getTile(6, 10).setGround();
+        game.getTile(7, 10).setGround();
+        game.getTile(8, 10).setGround();
+        game.getTile(9, 10).setGround();
+        game.getTile(6, 9).setGround();
+        game.getTile(7, 9).setGround();
+        game.getTile(8, 9).setGround();
+        game.getTile(9, 9).setGround();
+        game.getTile(6, 8).setGround();
+        game.getTile(8, 6).setGround();
+        game.getTile(10, 6).setGround();
+        game.getTile(5, 5).setGround();
+        game.getTile(5, 6).setFruit();
+        game.getTile(9, 6).setFruit();
+        game.getTile(8, 3).setGoal();
+		List<Tile> snake = Arrays.asList(game.getTile(9, 8), game.getTile(8, 8));
+		game.createSnake(snake);
+	}
+	
+	
+	@BeforeEach
+	public void setup() {
+		createBoard();
+	}
+
+	@Test
+	public void testConstructor() {
+		game = new Game(16, 12);
+		
+		// Test board dimensions
+		assertEquals(game.getHeight(), 12);
+		assertEquals(game.getWidth(), 16);
+		
+		// Test that all tiles are air initially
+		for (int y = 0; y < game.getHeight(); y++) {
+			for (int x = 0; x < game.getWidth(); x++) {
+				assertEquals(game.getTile(x, y).getType(), 'a');
+			}
+		}
+	}
+	
+	@Test
+	public void testCreateSnake() {
+		game = new Game(16, 12);
+		List<Tile> snake = Arrays.asList(game.getTile(9, 8), game.getTile(8, 8));
+        game.createSnake(snake);
+        assertEquals(game.getSnake().get(0), game.getTile(9, 8));
+        assertEquals(game.getSnake().get(1), game.getTile(8, 8));
+        assertEquals(game.getSnake().get(0).getType(), 's');
+        assertEquals(game.getSnake().get(1).getType(), 's');
+        assertTrue(game.isSnakeHead(game.getTile(9, 8)));
+	}
+	
+	@Test
+	public void testMoveIntoWall() {
+		game.moveLeft();
+		game.moveLeft();
+		assertThrows(
+			IllegalStateException.class, 
+			() -> game.moveLeft(), 
+			"IllegalState skal kastes når man prøver å gå inn i veggen!"
+		);
+	}
+	
+	@Test
+	public void testGameOver() {
+		game.moveRight();
+		game.moveRight();
+		assertThrows(
+			IllegalStateException.class, 
+			() -> game.moveRight(), 
+			"IllegalState skal kastes når man prøver å gå inn i veggen!"
+		);
+		assertTrue(game.isGameOver());
+	}
+
+	@Test
+	@DisplayName("Test at slange blir 3 blokker lang når den spiser frukt")
+	public void testEatFruit() {
+	    game.moveUp();
+	    game.moveUp();
+		assertEquals(game.getSnake().size(), 3);
+	}
+}
diff --git a/foreksempel/src/test/java/of13/lf/SaveHandlerTest.java b/foreksempel/src/test/java/of13/lf/SaveHandlerTest.java
new file mode 100644
index 0000000..b1927b7
--- /dev/null
+++ b/foreksempel/src/test/java/of13/lf/SaveHandlerTest.java
@@ -0,0 +1,115 @@
+package of13.lf;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+
+public class SaveHandlerTest {
+	
+    private Game game;
+    private SaveHandler saveHandler = new SaveHandler();
+    
+	private void createBoard() {
+        game = new Game(16, 12);
+        game.getTile(6, 11).setGround();
+        game.getTile(7, 11).setGround();
+        game.getTile(8, 11).setGround();
+        game.getTile(6, 10).setGround();
+        game.getTile(7, 10).setGround();
+        game.getTile(8, 10).setGround();
+        game.getTile(9, 10).setGround();
+        game.getTile(6, 9).setGround();
+        game.getTile(7, 9).setGround();
+        game.getTile(8, 9).setGround();
+        game.getTile(9, 9).setGround();
+        game.getTile(6, 8).setGround();
+        game.getTile(8, 6).setGround();
+        game.getTile(10, 6).setGround();
+        game.getTile(5, 5).setGround();
+        game.getTile(5, 6).setFruit();
+        game.getTile(9, 6).setFruit();
+        game.getTile(8, 3).setGoal();
+		List<Tile> snake = Arrays.asList(game.getTile(9, 8), game.getTile(8, 8));
+		game.createSnake(snake);
+	}
+
+	@BeforeEach
+	public void setup() {
+		createBoard();
+	}
+
+	@Test
+	public void testLoad() {
+		Game savedNewGame; // Required to ignore Eclipse warning
+		try {
+			savedNewGame = saveHandler.load("test-save");
+		} catch (FileNotFoundException e) {
+			fail("Could not load saved file");
+			return;
+		}
+		assertEquals(game.toString(), savedNewGame.toString());
+		assertFalse(game.isGameOver());
+	}
+
+	@Test
+	public void testLoadNonExistingFile() {
+		assertThrows(
+			FileNotFoundException.class, 
+			() -> game = saveHandler.load("foo"), 
+			"FileNotFoundException should be thrown when file does not exist!"
+		);
+	}
+
+	@Test
+	public void testLoadInvalidFile() {
+		assertThrows(
+			Exception.class, 
+			() -> game = saveHandler.load("invalid-save"), 
+			"An exception should be thrown if loaded file is invalid!"
+		);
+	}
+	
+	@Test
+	public void testSave() {
+		try {
+			saveHandler.save("test-save-new", game);
+		} catch (FileNotFoundException e) {
+			fail("Could not save file");
+		}
+		
+		byte[] testFile = null, newFile = null;
+		
+		try {
+			testFile = Files.readAllBytes(Path.of(SaveHandler.getFilePath("test-save")));
+		} catch (IOException e) {
+			fail("Could not load test file");
+		}
+
+		try {
+			newFile = Files.readAllBytes(Path.of(SaveHandler.getFilePath("test-save-new")));
+		} catch (IOException e) {
+			fail("Could not load saved file");
+		}
+		assertNotNull(testFile);
+		assertNotNull(newFile);
+		assertTrue(Arrays.equals(testFile, newFile));
+
+	}
+	
+	@AfterAll
+	static void teardown() {
+		File newTestSaveFile = new File(SaveHandler.getFilePath("test-save-new"));
+		newTestSaveFile.delete();
+	}
+
+}
diff --git a/foreksempel/src/test/java/of13/lf/TileTest.java b/foreksempel/src/test/java/of13/lf/TileTest.java
new file mode 100644
index 0000000..febf62c
--- /dev/null
+++ b/foreksempel/src/test/java/of13/lf/TileTest.java
@@ -0,0 +1,37 @@
+package of13.lf;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class TileTest {
+	
+	private Tile tile;
+
+	@BeforeEach
+	public void setup() {
+		tile = new Tile(0, 0);
+	}
+	
+	@Test
+	public void testSetValidType() {
+		tile.setType('a');
+		assertTrue(tile.isAir());
+		tile.setType('s');
+		assertTrue(tile.isSnake());
+		assertThrows(
+			IllegalArgumentException.class, 
+			() -> tile.setType('?'), 
+			"IllegalArgument skal kastes når man setter Tile til ugyldig verdi!"
+		);
+	}
+
+	@Test
+	public void testSetInvalidType() {
+		assertThrows(IllegalArgumentException.class, () -> {
+			tile.setType('?');
+		}, "IllegalArgument skal kastes når man setter Tile til ugyldig verdi!");
+	}
+	
+}
-- 
GitLab