From ae5fb68bd49105742715df12743da477ea3d5020 Mon Sep 17 00:00:00 2001 From: Leon <3010261@stud.hs-mannheim.de> Date: Mon, 6 Jan 2025 19:42:02 +0100 Subject: [PATCH] Musste neuen Commit machen, nachdem Datenstand nicht den gleichen Stand hatte wie main um einen Pull request in main zu gestatten --- .../de/deversmann/domain/Zeiterfassung.java | 1 - .../java/de/deversmann/facade/Facade.java | 52 +--- src/main/java/de/deversmann/gui/GameView.java | 235 +++++++++++++++++- .../java/de/deversmann/gui/HitoriApp.java | 14 ++ .../java/de/deversmann/gui/SpielfeldGUI.java | 7 +- 5 files changed, 252 insertions(+), 57 deletions(-) diff --git a/src/main/java/de/deversmann/domain/Zeiterfassung.java b/src/main/java/de/deversmann/domain/Zeiterfassung.java index f3b7012..1b40e8e 100644 --- a/src/main/java/de/deversmann/domain/Zeiterfassung.java +++ b/src/main/java/de/deversmann/domain/Zeiterfassung.java @@ -1,6 +1,5 @@ package de.deversmann.domain; - public class Zeiterfassung { private long startTime; diff --git a/src/main/java/de/deversmann/facade/Facade.java b/src/main/java/de/deversmann/facade/Facade.java index 8562fc9..d8dcef2 100644 --- a/src/main/java/de/deversmann/facade/Facade.java +++ b/src/main/java/de/deversmann/facade/Facade.java @@ -1,54 +1,4 @@ package de.deversmann.facade; -import java.io.IOException; -import java.util.List; - public class Facade { - private final CSVReader csvReader; - private final HighscoreManager_2_0 highscoreManager; - private final Zeiterfassung_2_0 zeiterfassung; - - // Hier speichern wir das aktuell geladene Puzzle (mit Lösung) - private PuzzleData currentPuzzleData; - - public Facade() { - this.csvReader = new CSVReader(); - this.highscoreManager = new HighscoreManager_2_0(); - this.zeiterfassung = new Zeiterfassung_2_0(); - } - - public void ladeSpielfeld(String csvPfad) throws IOException { - // Liest Puzzle + Lösung aus der CSV - this.currentPuzzleData = csvReader.readPuzzleWithSolution(csvPfad); - } - - public int[][] getAktuellesPuzzle() { - return (currentPuzzleData != null) - ? currentPuzzleData.getPuzzle() - : null; - } - - public List getLoesungsKoordinaten() { - return (currentPuzzleData != null) - ? currentPuzzleData.getSolutionCoordinates() - : null; - } - - public void startZeiterfassung() { - zeiterfassung.start(); - } - - public long stopZeiterfassung() { - zeiterfassung.stop(); - return zeiterfassung.getElapsedTimeInSeconds(); - } - - public void addHighscore(int score) { - highscoreManager.addHighscore(score); - } - - public List getAllHighscores() { - return highscoreManager.getHighscores(); - } - -} +} \ No newline at end of file diff --git a/src/main/java/de/deversmann/gui/GameView.java b/src/main/java/de/deversmann/gui/GameView.java index ea9fe0d..e2afa5f 100644 --- a/src/main/java/de/deversmann/gui/GameView.java +++ b/src/main/java/de/deversmann/gui/GameView.java @@ -1,4 +1,235 @@ package de.deversmann.gui; -public class GameView { -} +import de.deversmann.facade.Facade; + +import javax.swing.*; +import java.awt.*; +import java.io.IOException; +import java.util.List; +import java.util.Random; + +public class GameView extends JFrame { + + private final Facade facade; + private SpielfeldGUI spielfeldGUI; + + private JComboBox cbSpielfelder; + private JButton btnLoad; + private JButton btnRandom; + private JButton btnCheckSolution; + private JButton btnShowSolution; + private JButton btnReset; + private JLabel timeLabel; + private Timer timer; + + private final String[] spielfelder = { + "4x4.csv", + "5x5.csv", + "8x8_leicht.csv", + "8x8_medium.csv", + "10x10.csv", + "15x15.csv" + }; + + public GameView(Facade facade) { + this.facade = facade; + setTitle("Hitori App"); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setSize(800, 700); + initComponents(); + startTimer(); + setVisible(true); + } + + private void initComponents() { + JPanel controlPanel = new JPanel(); + + cbSpielfelder = new JComboBox<>(spielfelder); + btnLoad = new JButton("Spielfeld laden"); + btnRandom = new JButton("Zufällig"); + btnCheckSolution = new JButton("Lösung prüfen"); + btnShowSolution = new JButton("Lösung anzeigen"); + btnReset = new JButton("Reset"); + + timeLabel = new JLabel("Time: 0s"); + + btnLoad.addActionListener(e -> { + String selectedFile = (String) cbSpielfelder.getSelectedItem(); + if (selectedFile != null) { + ladeSpielfeld("src/Spielfelder/" + selectedFile); + } + }); + + btnRandom.addActionListener(e -> { + Random rand = new Random(); + int idx = rand.nextInt(spielfelder.length); + String randomField = spielfelder[idx]; + cbSpielfelder.setSelectedItem(randomField); + ladeSpielfeld("src/Spielfelder/" + randomField); + }); + + btnCheckSolution.addActionListener(e -> checkSolution()); + btnShowSolution.addActionListener(e -> showSolution()); + btnReset.addActionListener(e -> resetField()); + + controlPanel.add(new JLabel("Wähle ein Spielfeld:")); + controlPanel.add(cbSpielfelder); + controlPanel.add(btnLoad); + controlPanel.add(btnRandom); + controlPanel.add(btnCheckSolution); + controlPanel.add(btnShowSolution); + controlPanel.add(btnReset); + controlPanel.add(timeLabel); + + getContentPane().setLayout(new BorderLayout()); + getContentPane().add(controlPanel, BorderLayout.NORTH); + + spielfeldGUI = new SpielfeldGUI(1, 1); + getContentPane().add(spielfeldGUI, BorderLayout.CENTER); + } + + private void startTimer() { + timer = new Timer(1000, e -> { + long seconds = facade.getElapsedTimeSoFar(); + timeLabel.setText("Time: " + seconds + "s"); + }); + timer.start(); + } + + private void ladeSpielfeld(String pfad) { + try { + facade.ladeSpielfeld(pfad); + facade.loadCurrentPuzzleHighscoreFromFile(); + + int[][] feld = facade.getAktuellesPuzzle(); + if (feld != null) { + spielfeldGUI.updateGrid(feld); + timeLabel.setText("Time: 0s"); + } + } catch (IOException ex) { + JOptionPane.showMessageDialog(this, + "Fehler beim Laden: " + ex.getMessage(), + "Fehler", + JOptionPane.ERROR_MESSAGE + ); + } + } + + private void checkSolution() { + var blackCells = spielfeldGUI.getBlackCells(); + var solutionCoordinates = facade.getLoesungsKoordinaten(); + if (solutionCoordinates == null) { + JOptionPane.showMessageDialog(this, "Kein Puzzle geladen!", "Fehler", JOptionPane.ERROR_MESSAGE); + return; + } + + Set solutionSet = new HashSet<>(); + for (int[] sol : solutionCoordinates) { + solutionSet.add((sol[0] - 1) + "," + (sol[1] - 1)); + } + + int errorsThisCheck = 0; + for (int[] bc : blackCells) { + String bcStr = bc[0] + "," + bc[1]; + if (!solutionSet.contains(bcStr)) { + spielfeldGUI.markCellAsError(bc[0], bc[1]); + facade.incrementErrorCount(); + errorsThisCheck++; + } + } + + if (errorsThisCheck > 0) { + JOptionPane.showMessageDialog(this, + "Noch nicht korrekt! " + errorsThisCheck + " falsche Felder markiert.", + "Ergebnis", + JOptionPane.WARNING_MESSAGE + ); + return; + } + + boolean allSet = true; + for (String sol : solutionSet) { + if (!containsCell(blackCells, sol)) { + allSet = false; + break; + } + } + if (!allSet) { + JOptionPane.showMessageDialog(this, + "Nicht alle richtigen Felder sind schwarz!", + "Ergebnis", + JOptionPane.WARNING_MESSAGE + ); + return; + } + + long finalTime = facade.stopZeiterfassung(); + timeLabel.setText("Time: " + finalTime + "s"); + + String playerName = JOptionPane.showInputDialog( + this, + "Gratulation, richtig gelöst!\nBitte Namen eingeben:", + "Name eingeben", + JOptionPane.QUESTION_MESSAGE + ); + if (playerName == null || playerName.isBlank()) { + playerName = "Unbekannt"; + } + + int totalErrors = facade.getCurrentErrorCount(); + facade.addHighscoreForCurrentPuzzle(playerName, finalTime, totalErrors); + + try { + facade.saveCurrentPuzzleHighscoreToFile(); + } catch (IOException e) { + System.out.println("Konnte Puzzle-spezifischen Highscore nicht speichern: " + e.getMessage()); + } + + double avgTime = facade.getAverageTimeForCurrentPuzzle(); + StringBuilder sb = new StringBuilder(); + sb.append("Spiel gelöst!\n"); + sb.append("Deine Zeit: ").append(finalTime).append("s\n"); + sb.append("Fehler: ").append(totalErrors).append("\n"); + if (avgTime < 0) { + sb.append("Durchschnittszeit: Keine Einträge\n"); + } else { + sb.append(String.format("Durchschnittszeit: %.2f s\n", avgTime)); + } + + JOptionPane.showMessageDialog(this, sb.toString(), "Ergebnis", JOptionPane.INFORMATION_MESSAGE); + } + + private boolean containsCell(List blackCells, String sol) { + String[] parts = sol.split(","); + int rr = Integer.parseInt(parts[0]); + int cc = Integer.parseInt(parts[1]); + for (int[] bc : blackCells) { + if (bc[0] == rr && bc[1] == cc) { + return true; + } + } + return false; + } + + private void showSolution() { + var feld = facade.getAktuellesPuzzle(); + if (feld == null) return; + spielfeldGUI.updateGrid(feld); + + var solution = facade.getLoesungsKoordinaten(); + if (solution != null) { + for (int[] coord : solution) { + spielfeldGUI.setCellBlack(coord[0] - 1, coord[1] - 1); + } + } + spielfeldGUI.setAllNonBlackToWhite(); + } + + private void resetField() { + var feld = facade.getAktuellesPuzzle(); + if (feld != null) { + spielfeldGUI.updateGrid(feld); + timeLabel.setText("Time: 0s"); + } + } +} \ No newline at end of file diff --git a/src/main/java/de/deversmann/gui/HitoriApp.java b/src/main/java/de/deversmann/gui/HitoriApp.java index 8a5c3e7..fbdaa60 100644 --- a/src/main/java/de/deversmann/gui/HitoriApp.java +++ b/src/main/java/de/deversmann/gui/HitoriApp.java @@ -1,4 +1,18 @@ package de.deversmann.gui; +import de.deversmann.facade.Facade; + + public class HitoriApp { + + private Facade facade; + + public HitoriApp() { + facade = new Facade(); + } + + public void start() { + GameView view = new GameView(facade); + view.setVisible(true); + } } diff --git a/src/main/java/de/deversmann/gui/SpielfeldGUI.java b/src/main/java/de/deversmann/gui/SpielfeldGUI.java index 3b244cf..b7d1a51 100644 --- a/src/main/java/de/deversmann/gui/SpielfeldGUI.java +++ b/src/main/java/de/deversmann/gui/SpielfeldGUI.java @@ -5,13 +5,14 @@ import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.*; +import java.util.List; -public class SpielfeldGUI_2_0 extends JPanel { +public class SpielfeldGUI extends JPanel { private JLabel[][] grid; private Set errorCells = new HashSet<>(); - public SpielfeldGUI_2_0(int rows, int cols) { + public SpielfeldGUI(int rows, int cols) { setLayout(new GridLayout(rows, cols)); grid = new JLabel[rows][cols]; @@ -132,4 +133,4 @@ public class SpielfeldGUI_2_0 extends JPanel { if (grid == null) return false; return (r >= 0 && r < grid.length && c >= 0 && c < grid[r].length); } -} \ No newline at end of file +}