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