PR2-Heimtestat/src/main/java/de/deversmann/gui/GameView.java

237 lines
7.4 KiB
Java

package de.deversmann.gui;
import de.deversmann.facade.Facade;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
public class GameView extends JFrame {
private final Facade facade;
SpielfeldGUI spielfeldGUI;
JComboBox<String> cbSpielfelder;
JButton btnLoad;
JButton btnRandom;
JButton btnCheckSolution;
JButton btnShowSolution;
JButton btnReset;
JLabel timeLabel;
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();
}
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
);
}
}
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<String> 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);
}
boolean containsCell(List<int[]> 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;
}
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();
}
void resetField() {
var feld = facade.getAktuellesPuzzle();
if (feld != null) {
spielfeldGUI.updateGrid(feld);
timeLabel.setText("Time: 0s");
}
}
}