From a217a988149b2dcac4e6db910d659c2ed992b4da Mon Sep 17 00:00:00 2001 From: 3013016 Date: Tue, 7 Jan 2025 12:31:52 +0100 Subject: [PATCH] comments --- src/main/java/domain/GameSolver.java | 8 +- src/main/java/domain/HitoriBoardLoader.java | 35 ++++---- src/main/java/domain/HitoriGameMain.java | 28 +++--- src/main/java/domain/HitoriGameMoves.java | 96 --------------------- src/main/java/domain/HitoriGameScores.java | 16 +++- src/main/java/domain/HitoriGameTimer.java | 32 ++++--- src/test/java/HitoriBoardPanelTest.java | 9 +- src/test/java/HitoriControlPanelTest.java | 13 +++ src/test/java/HitoriGameSolverTest.java | 39 +++++---- src/test/java/HitoriGameTest.java | 51 +++++++---- src/test/java/HitoriGameTimerTest.java | 17 ++-- 11 files changed, 160 insertions(+), 184 deletions(-) delete mode 100644 src/main/java/domain/HitoriGameMoves.java diff --git a/src/main/java/domain/GameSolver.java b/src/main/java/domain/GameSolver.java index f2b8347..f345ae5 100644 --- a/src/main/java/domain/GameSolver.java +++ b/src/main/java/domain/GameSolver.java @@ -8,6 +8,7 @@ public class GameSolver extends HitoriGameMoves { super(initialBoard); } + // Überprüft, ob das Spiel gelöst wurde public boolean isSolved() { // First check if all cells are marked (either black or white) for (int i = 0; i < board.length; i++) { @@ -55,6 +56,7 @@ public class GameSolver extends HitoriGameMoves { return isOrthogonallyConnected(); } + // Überprüft, ob die schwarze Markierung gültig ist private boolean isValidBlackMark(int row, int col) { if (row > 0 && blackCells[row-1][col] || row < board.length-1 && blackCells[row+1][col] || @@ -65,6 +67,7 @@ public class GameSolver extends HitoriGameMoves { return true; } + // Überprüft, ob weiße Zellen orthogonal verbunden sind private boolean isOrthogonallyConnected() { if (board.length == 0) return true; @@ -84,6 +87,7 @@ public class GameSolver extends HitoriGameMoves { return true; } + // Findet die erste weiße Zelle private int[] findFirstWhiteCell() { for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { @@ -95,6 +99,7 @@ public class GameSolver extends HitoriGameMoves { return null; } + // Tiefensuche, um verbundene weiße Zellen zu finden private void dfs(int row, int col, boolean[][] visited) { if (row < 0 || row >= board.length || col < 0 || col >= board[0].length || visited[row][col] || blackCells[row][col]) { @@ -109,6 +114,7 @@ public class GameSolver extends HitoriGameMoves { dfs(row, col + 1, visited); } + // Findet fehlerhafte schwarze Markierungen public List findIncorrectBlackMarks() { List incorrectMarks = new ArrayList<>(); for (int i = 0; i < board.length; i++) { @@ -120,4 +126,4 @@ public class GameSolver extends HitoriGameMoves { } return incorrectMarks; } -} \ No newline at end of file +} diff --git a/src/main/java/domain/HitoriBoardLoader.java b/src/main/java/domain/HitoriBoardLoader.java index b9d89d6..9533d31 100644 --- a/src/main/java/domain/HitoriBoardLoader.java +++ b/src/main/java/domain/HitoriBoardLoader.java @@ -11,12 +11,12 @@ public class HitoriBoardLoader { public HitoriBoardLoader() { availableBoards = new HashMap<>(); solutions = new HashMap<>(); - loadAllBoards(); + loadAllBoards(); // Lädt alle verfügbaren Boards } private void loadAllBoards() { try { - // Define all board file names + // Definiere die Board-Dateinamen String[] boardFiles = { "Hitori4x4_leicht.csv", "Hitori5x5leicht.csv", @@ -26,16 +26,12 @@ public class HitoriBoardLoader { "Hitori15x15_medium.csv" }; - // Try to load each board + // Versuche, jedes Board zu laden for (String fileName : boardFiles) { try { InputStream is = getClass().getResourceAsStream("/" + fileName); - if (is == null) { - is = getClass().getResourceAsStream("/" + fileName); - } - if (is != null) { - loadBoard(fileName, is); + loadBoard(fileName, is); // Lade das Board } } catch (Exception e) { System.out.println("Failed to load board: " + fileName); @@ -43,6 +39,7 @@ public class HitoriBoardLoader { } } + // Überprüfe, ob Boards geladen wurden if (availableBoards.isEmpty()) { System.out.println("No board files found. Please ensure .csv files are in the resources folder."); } else { @@ -53,15 +50,16 @@ public class HitoriBoardLoader { } } + // Lädt ein einzelnes Board und seine Lösung private void loadBoard(String fileName, InputStream inputStream) throws IOException { try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { List lines = new ArrayList<>(); String line; while ((line = reader.readLine()) != null) { - lines.add(line); + lines.add(line); // Liest jede Zeile der Datei } - // Find where the solution starts + // Finde den Startpunkt der Lösung int solutionIndex = -1; for (int i = 0; i < lines.size(); i++) { if (lines.get(i).contains("//")) { @@ -70,12 +68,12 @@ public class HitoriBoardLoader { } } - // Parse the board + // Parsen des Boards List boardRows = new ArrayList<>(); for (int i = 0; i < (solutionIndex == -1 ? lines.size() : solutionIndex); i++) { line = lines.get(i).trim(); if (!line.isEmpty()) { - boardRows.add(line.split(",")); + boardRows.add(line.split(",")); // Trenne die Zeilen in Spalten } } @@ -86,12 +84,12 @@ public class HitoriBoardLoader { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { - board[i][j] = Integer.parseInt(boardRows.get(i)[j].trim()); + board[i][j] = Integer.parseInt(boardRows.get(i)[j].trim()); // Konvertiere die Strings in Integers } } - availableBoards.put(fileName, board); + availableBoards.put(fileName, board); // Speichere das Board - // Parse the solution if available + // Wenn eine Lösung vorhanden ist, speichere sie List solutionCoordinates = new ArrayList<>(); if (solutionIndex != -1) { for (int i = solutionIndex + 1; i < lines.size(); i++) { @@ -104,21 +102,24 @@ public class HitoriBoardLoader { }); } } - solutions.put(fileName, solutionCoordinates); + solutions.put(fileName, solutionCoordinates); // Speichere die Lösung } } } } + // Gibt die Namen der verfügbaren Boards zurück public Set getAvailableBoardNames() { return availableBoards.keySet(); } + // Gibt ein Board anhand des Namens zurück public int[][] getBoard(String boardName) { return availableBoards.get(boardName); } + // Gibt die Lösung für ein Board zurück public List getSolution(String boardName) { return solutions.get(boardName); } -} \ No newline at end of file +} diff --git a/src/main/java/domain/HitoriGameMain.java b/src/main/java/domain/HitoriGameMain.java index f9cfb04..93fec62 100644 --- a/src/main/java/domain/HitoriGameMain.java +++ b/src/main/java/domain/HitoriGameMain.java @@ -5,9 +5,9 @@ import java.io.*; public class HitoriGameMain extends GameSolver { private static final long serialVersionUID = 1L; - private final HitoriGameTimer timer; - private final HitoriGameScores scores; - private long savedTime; + private final HitoriGameTimer timer; // Timer für das Spiel + private final HitoriGameScores scores; // Highscore-Verwaltung + private long savedTime; // Gespeicherte Zeit für den Timer public HitoriGameMain(int[][] initialBoard) { super(initialBoard); @@ -24,28 +24,26 @@ public class HitoriGameMain extends GameSolver { return scores; } - // Update serialization to handle full game state + // Speichert den aktuellen Zustand des Spiels private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); - // Save current state out.writeLong(getElapsedTimeInSeconds()); out.writeInt(mistakeCount); out.writeObject(blackCells); out.writeObject(whiteCells); } + // Stellt den gespeicherten Zustand des Spiels wieder her private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); - // Restore state long savedTime = in.readLong(); this.mistakeCount = in.readInt(); this.blackCells = (boolean[][]) in.readObject(); this.whiteCells = (boolean[][]) in.readObject(); - // Initialize timer with saved time this.timer.setElapsedTime(savedTime); } - // Timer delegation methods + // Steuerung des Timers public void startTimer() { timer.startTimer(); } @@ -62,11 +60,12 @@ public class HitoriGameMain extends GameSolver { timer.resetTimer(); } + // Gibt die verstrichene Zeit zurück public long getElapsedTimeInSeconds() { return savedTime > 0 ? savedTime : timer.getElapsedTimeInSeconds(); } - // High score delegation methods + // Highscore-Verwaltung public void addHighScore(String playerName, long timeInSeconds) { scores.addHighScore(playerName, timeInSeconds, getMistakeCount()); } @@ -87,7 +86,7 @@ public class HitoriGameMain extends GameSolver { scores.saveHighScoresToFile(); } - // Game state persistence + // Setzt den Spielzustand public void setGameState(boolean[][] blackCells, boolean[][] whiteCells, int mistakeCount, long elapsedTime) { this.blackCells = new boolean[blackCells.length][blackCells[0].length]; this.whiteCells = new boolean[whiteCells.length][whiteCells[0].length]; @@ -101,6 +100,7 @@ public class HitoriGameMain extends GameSolver { this.savedTime = elapsedTime; } + // Speichert das Spiel in einer Datei public void saveGameState() { try (ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream("gamestate.dat"))) { @@ -110,11 +110,11 @@ public class HitoriGameMain extends GameSolver { } } + // Lädt das Spiel aus einer Datei public static HitoriGameMain loadGameState() { try (ObjectInputStream ois = new ObjectInputStream( new FileInputStream("gamestate.dat"))) { HitoriGameMain loadedGame = (HitoriGameMain) ois.readObject(); - // Initialize transient fields loadedGame.timer.resetTimer(); return loadedGame; } catch (IOException | ClassNotFoundException e) { @@ -122,6 +122,7 @@ public class HitoriGameMain extends GameSolver { } } + // Stellt den gespeicherten Zustand des Spiels wieder her public void restoreGameState(HitoriGameMain savedGame) { if (savedGame != null) { this.setGameState(savedGame.blackCells, savedGame.whiteCells, @@ -132,7 +133,6 @@ public class HitoriGameMain extends GameSolver { @Override public void reset() { super.reset(); - // Don't reset timer anymore - savedTime = 0; + savedTime = 0; // Timer wird nicht zurückgesetzt } -} \ No newline at end of file +} diff --git a/src/main/java/domain/HitoriGameMoves.java b/src/main/java/domain/HitoriGameMoves.java deleted file mode 100644 index 9a4ccb7..0000000 --- a/src/main/java/domain/HitoriGameMoves.java +++ /dev/null @@ -1,96 +0,0 @@ -package domain; - -import java.io.Serializable; -import java.util.*; - -public class HitoriGameMoves extends GameBase { - private List history; - private int historyPointer; - - private static class GameState implements Serializable { - boolean[][] blackCells; - boolean[][] whiteCells; - - GameState(boolean[][] blackCells, boolean[][] whiteCells) { - this.blackCells = new boolean[blackCells.length][blackCells[0].length]; - this.whiteCells = new boolean[whiteCells.length][whiteCells[0].length]; - for (int i = 0; i < blackCells.length; i++) { - this.blackCells[i] = Arrays.copyOf(blackCells[i], blackCells[i].length); - this.whiteCells[i] = Arrays.copyOf(whiteCells[i], whiteCells[i].length); - } - } - } - - public HitoriGameMoves(int[][] initialBoard) { - super(initialBoard); - this.history = new ArrayList<>(); - this.historyPointer = -1; - saveState(); - } - - public void markCellAsBlack(int row, int col) { - blackCells[row][col] = true; - whiteCells[row][col] = false; - saveState(); - } - - public void markCellAsWhite(int row, int col) { - whiteCells[row][col] = true; - blackCells[row][col] = false; - saveState(); - } - - protected void saveState() { - while (history.size() > historyPointer + 1) { - history.remove(history.size() - 1); - } - history.add(new GameState(blackCells, whiteCells)); - historyPointer++; - } - - public boolean undo() { - if (historyPointer > 0) { - historyPointer--; - GameState state = history.get(historyPointer); - restoreState(state); - return true; - } - return false; - } - - public boolean redo() { - if (historyPointer < history.size() - 1) { - historyPointer++; - GameState state = history.get(historyPointer); - restoreState(state); - return true; - } - return false; - } - - private void restoreState(GameState state) { - for (int i = 0; i < board.length; i++) { - blackCells[i] = Arrays.copyOf(state.blackCells[i], state.blackCells[i].length); - whiteCells[i] = Arrays.copyOf(state.whiteCells[i], state.whiteCells[i].length); - } - } - - @Override - public void reset() { - // Save mistake count before reset - int currentMistakes = mistakeCount; - - // Call parent reset which resets the board state - super.reset(); - - // Clear history - history.clear(); - historyPointer = -1; - - // Restore mistake count - mistakeCount = currentMistakes; - - // Save initial state - saveState(); - } -} \ No newline at end of file diff --git a/src/main/java/domain/HitoriGameScores.java b/src/main/java/domain/HitoriGameScores.java index 482373a..498d68f 100644 --- a/src/main/java/domain/HitoriGameScores.java +++ b/src/main/java/domain/HitoriGameScores.java @@ -8,6 +8,7 @@ public class HitoriGameScores implements Serializable { private Map> highScores; + // Speichert einzelne Highscore-Einträge private static class HighScoreEntry implements Serializable { String playerName; long time; @@ -24,17 +25,20 @@ public class HitoriGameScores implements Serializable { this.highScores = new HashMap<>(); } + // Fügt einen neuen Highscore hinzu public void addHighScore(String playerName, long timeInSeconds, int mistakes) { highScores.putIfAbsent(playerName, new ArrayList<>()); highScores.get(playerName).add(new HighScoreEntry(playerName, timeInSeconds, mistakes)); saveHighScoresToFile(); } + // Löscht alle Highscores public void deleteHighScores() { highScores.clear(); saveHighScoresToFile(); } + // Gibt die besten Highscores mit Durchschnittszeit zurück public List getHighScoresWithAverage() { List result = new ArrayList<>(); List allEntries = new ArrayList<>(); @@ -43,24 +47,27 @@ public class HitoriGameScores implements Serializable { allEntries.addAll(entries); } - allEntries.sort((a, b) -> Long.compare(a.time, b.time)); + allEntries.sort((a, b) -> Long.compare(a.time, b.time)); // Sortiert nach Zeit + // Berechnet den Durchschnitt double avgTime = allEntries.stream() .mapToLong(e -> e.time) .average() .orElse(0); + // Fügt die besten 10 Einträge hinzu for (int i = 0; i < Math.min(10, allEntries.size()); i++) { HighScoreEntry entry = allEntries.get(i); result.add(String.format("%s - Time: %ds - Mistakes: %d", entry.playerName, entry.time, entry.mistakes)); } - result.add(String.format("Average Time: %.1fs", avgTime)); + result.add(String.format("Average Time: %.1fs", avgTime)); // Durchschnittszeit hinzufügen return result; } + // Speichert die Highscores in einer Datei public void saveHighScoresToFile() { try (ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream("highscores.dat"))) { @@ -70,13 +77,14 @@ public class HitoriGameScores implements Serializable { } } + // Lädt die Highscores aus einer Datei @SuppressWarnings("unchecked") public void loadHighScoresFromFile() { try (ObjectInputStream ois = new ObjectInputStream( new FileInputStream("highscores.dat"))) { highScores = (Map>) ois.readObject(); } catch (IOException | ClassNotFoundException e) { - highScores = new HashMap<>(); + highScores = new HashMap<>(); // Leert die Highscores bei Fehler } } -} \ No newline at end of file +} diff --git a/src/main/java/domain/HitoriGameTimer.java b/src/main/java/domain/HitoriGameTimer.java index d9b7998..d4bffd3 100644 --- a/src/main/java/domain/HitoriGameTimer.java +++ b/src/main/java/domain/HitoriGameTimer.java @@ -8,29 +8,31 @@ import java.io.Serializable; public class HitoriGameTimer implements Serializable { private static final long serialVersionUID = 1L; - private transient long startTime; // Time when timer was last started - private long elapsedTime; // Total accumulated time - private boolean isPaused; // Current pause state - private long lastPauseTime; // When the timer was last paused + private transient long startTime; + private long elapsedTime; + private boolean isPaused; + private long lastPauseTime; public HitoriGameTimer() { this.startTime = 0; this.elapsedTime = 0; - this.isPaused = true; // Start paused + this.isPaused = true; // Timer beginnt pausiert this.lastPauseTime = 0; } + // Timer starten public void startTimer() { if (isPaused) { startTime = System.currentTimeMillis(); isPaused = false; - // If this is a resume after pause, handle accumulated time + if (lastPauseTime > 0) { startTime = System.currentTimeMillis(); } } } + // Timer pausieren public void pauseTimer() { if (!isPaused && startTime > 0) { lastPauseTime = System.currentTimeMillis(); @@ -40,6 +42,7 @@ public class HitoriGameTimer implements Serializable { } } + // Timer stoppen public void stopTimer() { if (!isPaused && startTime > 0) { long stopTime = System.currentTimeMillis(); @@ -50,6 +53,7 @@ public class HitoriGameTimer implements Serializable { } } + // Timer zurücksetzen public void resetTimer() { startTime = 0; elapsedTime = 0; @@ -57,11 +61,13 @@ public class HitoriGameTimer implements Serializable { lastPauseTime = 0; } + // Setzt die vergangene Zeit manuell public void setElapsedTime(long timeInSeconds) { - this.elapsedTime = timeInSeconds * 1000; // Convert to milliseconds + this.elapsedTime = timeInSeconds * 1000; // Umrechnung in Millisekunden this.lastPauseTime = System.currentTimeMillis(); } + // Gibt die vergangene Zeit in Sekunden zurück public long getElapsedTimeInSeconds() { if (isPaused) { return elapsedTime / 1000; @@ -70,23 +76,25 @@ public class HitoriGameTimer implements Serializable { return (elapsedTime + (currentTime - startTime)) / 1000; } + // Gibt zurück, ob der Timer pausiert ist public boolean isPaused() { return isPaused; } - // For serialization + // Für die Serialisierung: Speichert den aktuellen Zustand private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); - // Save current elapsed time if timer is running + if (!isPaused && startTime > 0) { elapsedTime += System.currentTimeMillis() - startTime; } } + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); - // Initialize transient fields + startTime = 0; - isPaused = true; // Start paused when restored + isPaused = true; } -} \ No newline at end of file +} diff --git a/src/test/java/HitoriBoardPanelTest.java b/src/test/java/HitoriBoardPanelTest.java index a8b8442..5808669 100644 --- a/src/test/java/HitoriBoardPanelTest.java +++ b/src/test/java/HitoriBoardPanelTest.java @@ -31,12 +31,14 @@ class HitoriBoardPanelTest { boardPanel = new HitoriBoardPanel(gameMoves, gameSolver, controller); } + // Testet, ob das Board korrekt initialisiert wurde @Test void testInitialization() { assertNotNull(boardPanel); assertEquals(9, boardPanel.getChildren().size()); // 3x3 board = 9 buttons } + // Testet, ob die Buttons korrekt erstellt wurden @Test void testCellCreation() { var children = boardPanel.getChildren(); @@ -44,6 +46,7 @@ class HitoriBoardPanelTest { assertEquals("1", firstButton.getText()); } + // Testet das Styling der Buttons @Test void testButtonStyling() { var children = boardPanel.getChildren(); @@ -51,21 +54,23 @@ class HitoriBoardPanelTest { assertEquals("-fx-background-color: lightgray; -fx-text-fill: black;", button.getStyle()); } + // Testet das Aktualisieren des Boards @Test void testUpdateBoard() { boardPanel.updateBoard(); assertEquals(9, boardPanel.getChildren().size()); } + // Testet die Anzeige von Fehlern auf dem Board @Test void testShowErrors() { - // Mark some cells as black to create errors + gameMoves.markCellAsBlack(0, 0); gameMoves.markCellAsBlack(0, 1); boardPanel.showErrors(); - // Verify that error cells are marked red + // Verifiziere, dass fehlerhafte Zellen rot markiert werden var children = boardPanel.getChildren(); for (var child : children) { Button button = (Button) child; diff --git a/src/test/java/HitoriControlPanelTest.java b/src/test/java/HitoriControlPanelTest.java index 1c59cb4..7d0c29b 100644 --- a/src/test/java/HitoriControlPanelTest.java +++ b/src/test/java/HitoriControlPanelTest.java @@ -19,12 +19,14 @@ class HitoriControlPanelTest { controlPanel = new HitoriControlPanel(controller); } + // Testet, ob das Control-Panel korrekt initialisiert wurde @Test void testInitialization() { assertNotNull(controlPanel); assertTrue(controlPanel.getChildren().size() > 0); } + // Testet das Aktualisieren des Timer-Labels @Test void testUpdateTimerLabel() { controlPanel.updateTimerLabel(42); @@ -32,6 +34,7 @@ class HitoriControlPanelTest { assertNotNull(42); } + // Testet das Aktualisieren des Fehler-Labels @Test void testUpdateMistakeLabel() { controlPanel.updateMistakeLabel(5); @@ -39,6 +42,7 @@ class HitoriControlPanelTest { assertNotNull(5); } + // Testet das Setzen des Textes für den Pause-Button @Test void testSetPauseButtonText() { controlPanel.setPauseButtonText("Test"); @@ -46,6 +50,7 @@ class HitoriControlPanelTest { assertNotNull(pauseButton); } + // Testet die Aktion des Pause-Buttons @Test void testPauseButtonAction() { var pauseButton = findButtonByText(controlPanel, "Pause"); @@ -55,6 +60,7 @@ class HitoriControlPanelTest { verify(controller, times(1)).togglePause(); } + // Testet die Aktion des Reset-Buttons @Test void testResetButtonAction() { var resetButton = findButtonByText(controlPanel, "Reset"); @@ -64,6 +70,7 @@ class HitoriControlPanelTest { verify(controller, times(1)).resetGame(); } + // Testet die Aktion des Undo-Buttons @Test void testUndoButtonAction() { var undoButton = findButtonByText(controlPanel, "Undo"); @@ -73,6 +80,7 @@ class HitoriControlPanelTest { verify(controller, times(1)).undo(); } + // Testet die Aktion des Redo-Buttons @Test void testRedoButtonAction() { var redoButton = findButtonByText(controlPanel, "Redo"); @@ -82,6 +90,7 @@ class HitoriControlPanelTest { verify(controller, times(1)).redo(); } + // Testet die Aktion des Check-Solution-Buttons @Test void testCheckSolutionButtonAction() { var checkButton = findButtonByText(controlPanel, "Check Solution"); @@ -91,6 +100,7 @@ class HitoriControlPanelTest { verify(controller, times(1)).checkSolution(); } + // Testet die Aktion des New-Game-Buttons @Test void testNewGameButtonAction() { var newGameButton = findButtonByText(controlPanel, "New Game"); @@ -100,6 +110,7 @@ class HitoriControlPanelTest { verify(controller, times(1)).newGame(); } + // Testet die Aktion des Show-Errors-Buttons @Test void testShowErrorsButtonAction() { var showErrorsButton = findButtonByText(controlPanel, "Show Errors"); @@ -109,6 +120,7 @@ class HitoriControlPanelTest { verify(controller, times(1)).showErrors(); } + // Hilfsmethode: Sucht ein Label mit einem bestimmten Text im Panel private Label findLabelByText(HitoriControlPanel panel, String text) { return (Label) panel.getChildren().stream() .filter(node -> node instanceof Label && ((Label) node).getText().equals(text)) @@ -116,6 +128,7 @@ class HitoriControlPanelTest { .orElse(null); } + // Hilfsmethode: Sucht einen Button mit einem bestimmten Text im Panel private Button findButtonByText(HitoriControlPanel panel, String text) { return (Button) panel.getChildren().stream() .flatMap(node -> node.lookupAll("Button").stream()) diff --git a/src/test/java/HitoriGameSolverTest.java b/src/test/java/HitoriGameSolverTest.java index 51d0fa7..c128708 100644 --- a/src/test/java/HitoriGameSolverTest.java +++ b/src/test/java/HitoriGameSolverTest.java @@ -16,14 +16,16 @@ class HitoriGameSolverTest { game = new GameSolver(TEST_BOARD); } + // Testet den Anfangszustand: Das Puzzle sollte nicht gelöst sein @Test void testUnsolvedInitialState() { assertFalse(game.isSolved()); } + // Testet das Lösen des Puzzles mit einer bekannten Lösung @Test void testSolvingPuzzle() { - // Apply known solution + game.markCellAsBlack(0, 2); game.markCellAsWhite(0, 0); game.markCellAsWhite(0, 1); @@ -37,19 +39,21 @@ class HitoriGameSolverTest { assertFalse(game.isSolved()); } + // Testet eine falsche Lösung, bei der alle Zellen weiß markiert sind @Test void testIncorrectSolution() { - // Mark all cells white + for (int i = 0; i < TEST_BOARD.length; i++) { for (int j = 0; j < TEST_BOARD[0].length; j++) { game.markCellAsWhite(i, j); } } - // Should not be solved due to duplicate numbers + assertFalse(game.isSolved()); } + // Testet, ob das Puzzle nicht gelöst ist, wenn weiße Zellen nicht verbunden sind @Test void testDisconnectedWhiteCells() { // Create a solution with disconnected white cells @@ -59,21 +63,22 @@ class HitoriGameSolverTest { game.markCellAsBlack(1, 1); game.markCellAsWhite(2, 2); - // Should not be solved due to disconnected white cells + assertFalse(game.isSolved()); } + // Testet die Erkennung von ungültigen schwarzen Markierungen (benachbarte schwarze Zellen) @Test void testFindIncorrectBlackMarks() { - // Create adjacent black cells + game.markCellAsBlack(0, 0); - game.markCellAsBlack(0, 1); // This creates an invalid situation + game.markCellAsBlack(0, 1); List errors = game.findIncorrectBlackMarks(); assertFalse(errors.isEmpty()); - assertEquals(2, errors.size()); // Both cells should be reported + assertEquals(2, errors.size()); + - // Verify error coordinates boolean foundFirst = false; boolean foundSecond = false; for (int[] error : errors) { @@ -83,9 +88,10 @@ class HitoriGameSolverTest { assertTrue(foundFirst && foundSecond); } + // Testet den Fall, dass es keine ungültigen schwarzen Markierungen gibt @Test void testNoIncorrectBlackMarks() { - // Make valid black marks + game.markCellAsBlack(0, 0); game.markCellAsBlack(2, 2); @@ -93,34 +99,37 @@ class HitoriGameSolverTest { assertTrue(errors.isEmpty()); } + // Testet, ob das Puzzle nicht gelöst ist, wenn einige Zellen unmarkiert bleiben @Test void testUnmarkedCellsNotSolved() { - // Leave some cells unmarked + game.markCellAsWhite(0, 0); game.markCellAsBlack(0, 1); - // Don't mark other cells + assertFalse(game.isSolved()); } + // Testet den Fall von doppelten Zahlen in einer Zeile @Test void testDuplicateNumbersInRows() { - // Mark cells to create duplicate numbers in a row + game.markCellAsWhite(0, 0); game.markCellAsWhite(0, 1); game.markCellAsWhite(0, 2); - // Row now has duplicate numbers + assertFalse(game.isSolved()); } + // Testet den Fall von doppelten Zahlen in einer Spalte @Test void testDuplicateNumbersInColumns() { - // Mark cells to create duplicate numbers in a column + game.markCellAsWhite(0, 0); game.markCellAsWhite(1, 0); game.markCellAsWhite(2, 0); - // Column now has duplicate numbers + assertFalse(game.isSolved()); } diff --git a/src/test/java/HitoriGameTest.java b/src/test/java/HitoriGameTest.java index 9b276aa..dbda62b 100644 --- a/src/test/java/HitoriGameTest.java +++ b/src/test/java/HitoriGameTest.java @@ -14,19 +14,24 @@ class HitoriGameTest { @BeforeEach void setUp() { game = new HitoriGameMain(TEST_BOARD); + + // Löscht alte Spielstand- und Highscore-Dateien (falls vorhanden) new File("gamestate.dat").delete(); new File("highscores.dat").delete(); } @AfterEach void tearDown() { + // Löscht nach jedem Test die erstellten Dateien new File("gamestate.dat").delete(); new File("highscores.dat").delete(); } @Test void testGameIntegration() { - // Test timer functionality + // Testet die Integration verschiedener Spielfunktionen + + // Timer starten und prüfen, ob Zeit gezählt wird game.startTimer(); try { Thread.sleep(1100); @@ -35,31 +40,33 @@ class HitoriGameTest { } assertTrue(game.getElapsedTimeInSeconds() >= 1); - // Test game moves + // Testet das Markieren von Zellen game.markCellAsBlack(0, 2); assertTrue(game.getBlackCells()[0][2]); - // Test scoring + // Testet das Hinzufügen von Highscores game.addHighScore("TestPlayer", 100); assertFalse(game.getHighScoresWithAverage().isEmpty()); } @Test void testSaveAndLoadGameState() { - // Make some moves + // Testet das Speichern und Laden des Spielstands + + // Einige Zellen markieren und Timer starten game.markCellAsWhite(0, 0); game.markCellAsBlack(1, 1); game.startTimer(); try { - Thread.sleep(1000); + Thread.sleep(1000); // 1 Sekunde warten } catch (InterruptedException e) { fail("Timer test interrupted"); } - // Save game state + game.saveGameState(); - // Load game state + // Spielstand laden und prüfen HitoriGameMain loadedGame = HitoriGameMain.loadGameState(); assertNotNull(loadedGame); assertTrue(loadedGame.getWhiteCells()[0][0]); @@ -69,15 +76,17 @@ class HitoriGameTest { @Test void testResetAll() { - // Setup some game state + // Testet das vollständige Zurücksetzen des Spiels + + // Spielzustand einrichten game.markCellAsBlack(0, 0); game.startTimer(); game.addHighScore("TestPlayer", 100); - // Reset everything + game.reset(); - // Verify reset + // Prüfen, ob das Spiel zurückgesetzt wurde assertFalse(game.getBlackCells()[0][0]); assertEquals(0, game.getElapsedTimeInSeconds()); assertEquals(0, game.getMistakeCount()); @@ -85,10 +94,11 @@ class HitoriGameTest { @Test void testCompleteGameFlow() { - // Start game + // Testet einen kompletten Spielablauf + game.startTimer(); - // Make some moves towards solution + // Zellen markieren, um das Spiel zu lösen game.markCellAsBlack(0, 2); game.markCellAsWhite(0, 0); game.markCellAsWhite(0, 1); @@ -99,14 +109,14 @@ class HitoriGameTest { game.markCellAsWhite(2, 1); game.markCellAsBlack(2, 2); - // Verify solution + assertFalse(game.isSolved()); - // Add score + game.stopTimer(); game.addHighScore("Winner", game.getElapsedTimeInSeconds()); - // Verify score was recorded + // Prüfen, ob der Highscore gespeichert wurde boolean found = false; for (String score : game.getHighScoresWithAverage()) { if (score.contains("Winner")) { @@ -119,6 +129,9 @@ class HitoriGameTest { @Test void testTimerPauseResume() { + // Testet das Pausieren und Fortsetzen des Timers + + game.startTimer(); try { Thread.sleep(1000); @@ -126,6 +139,7 @@ class HitoriGameTest { fail("Timer test interrupted"); } + // Timer pausieren und aktuelle Zeit speichern game.pauseTimer(); long pausedTime = game.getElapsedTimeInSeconds(); @@ -135,17 +149,18 @@ class HitoriGameTest { fail("Timer test interrupted"); } - // Time should not increase while paused + // Zeit sollte während der Pause nicht weiterlaufen assertEquals(pausedTime, game.getElapsedTimeInSeconds()); - game.startTimer(); // Resume + // Timer fortsetzen und prüfen, ob Zeit weiterläuft + game.startTimer(); try { Thread.sleep(1000); } catch (InterruptedException e) { fail("Timer test interrupted"); } - // Time should increase after resume + assertTrue(game.getElapsedTimeInSeconds() > pausedTime); } } diff --git a/src/test/java/HitoriGameTimerTest.java b/src/test/java/HitoriGameTimerTest.java index 6463f83..b0a469b 100644 --- a/src/test/java/HitoriGameTimerTest.java +++ b/src/test/java/HitoriGameTimerTest.java @@ -10,17 +10,19 @@ class HitoriGameTimerTest { timer = new HitoriGameTimer(); } + // Testet den Anfangszustand des Timers @Test void testInitialState() { assertEquals(0, timer.getElapsedTimeInSeconds()); - assertFalse(timer.isPaused()); + assertTrue(timer.isPaused()); } + // Testet das Starten des Timers @Test void testStartTimer() { timer.startTimer(); try { - Thread.sleep(1100); // Wait a bit more than 1 second + Thread.sleep(1100); } catch (InterruptedException e) { fail("Timer test interrupted"); } @@ -29,6 +31,7 @@ class HitoriGameTimerTest { assertFalse(timer.isPaused()); } + // Testet das Pausieren des Timers @Test void testPauseTimer() { timer.startTimer(); @@ -48,10 +51,11 @@ class HitoriGameTimerTest { fail("Timer test interrupted"); } - // Time should not have increased while paused + assertEquals(pausedTime, timer.getElapsedTimeInSeconds()); } + // Testet das Fortsetzen des Timers nach einer Pause @Test void testResumeTimer() { timer.startTimer(); @@ -64,7 +68,7 @@ class HitoriGameTimerTest { timer.pauseTimer(); long pausedTime = timer.getElapsedTimeInSeconds(); - timer.startTimer(); // Resume + timer.startTimer(); try { Thread.sleep(1000); } catch (InterruptedException e) { @@ -74,6 +78,7 @@ class HitoriGameTimerTest { assertTrue(timer.getElapsedTimeInSeconds() > pausedTime); } + // Testet das Stoppen des Timers @Test void testStopTimer() { timer.startTimer(); @@ -95,6 +100,7 @@ class HitoriGameTimerTest { assertEquals(stoppedTime, timer.getElapsedTimeInSeconds()); } + // Testet das Zurücksetzen des Timers @Test void testResetTimer() { timer.startTimer(); @@ -106,9 +112,10 @@ class HitoriGameTimerTest { timer.resetTimer(); assertEquals(0, timer.getElapsedTimeInSeconds()); - assertFalse(timer.isPaused()); + assertTrue(timer.isPaused()); } + // Testet das mehrfache Pausieren und Fortsetzen des Timers @Test void testMultiplePauseResume() { timer.startTimer(); -- 2.51.0