Compare commits
No commits in common. "1a32962ba8072bd98643a2d3ec82580c5b78b8ac" and "daedc2bf63ca4faa3648a7d2f4007dcc40d6c062" have entirely different histories.
1a32962ba8
...
daedc2bf63
|
|
@ -1,83 +0,0 @@
|
||||||
7,1,2,9,12,15,8,11,11,9,11,14,13,6,3
|
|
||||||
2,3,8,1,2,11,10,9,5,8,14,3,12,13,15
|
|
||||||
4,14,13,9,4,15,9,10,12,6,5,3,11,5,12
|
|
||||||
15,9,5,6,10,15,1,15,8,3,5,4,6,2,8
|
|
||||||
5,11,7,9,15,1,4,3,8,1,9,2,10,13,2
|
|
||||||
15,15,10,3,1,14,8,12,11,1,9,8,2,7,2
|
|
||||||
10,7,7,12,9,3,15,2,5,2,10,5,1,7,4
|
|
||||||
3,8,9,14,1,6,12,4,15,2,13,11,5,10,11
|
|
||||||
8,6,7,15,11,4,5,11,2,10,3,13,8,12,9
|
|
||||||
2,2,3,3,4,13,5,6,5,11,5,15,8,9,12
|
|
||||||
2,15,15,11,13,7,6,5,3,13,8,10,5,1,11
|
|
||||||
12,5,11,13,13,2,2,8,8,4,10,9,3,2,5
|
|
||||||
1,13,8,2,1,7,11,4,9,15,4,12,9,3,10
|
|
||||||
13,10,12,5,15,3,2,7,13,14,12,12,9,11,6
|
|
||||||
7,12,4,8,14,10,13,13,7,4,2,6,15,15,11
|
|
||||||
|
|
||||||
//Lösung
|
|
||||||
1,4
|
|
||||||
1,6
|
|
||||||
1,8
|
|
||||||
1,11
|
|
||||||
2,1
|
|
||||||
2,3
|
|
||||||
2,9
|
|
||||||
2,12
|
|
||||||
2,14
|
|
||||||
3,5
|
|
||||||
3,7
|
|
||||||
3,11
|
|
||||||
3,15
|
|
||||||
4,1
|
|
||||||
4,3
|
|
||||||
4,6
|
|
||||||
4,9
|
|
||||||
4,13
|
|
||||||
5,4
|
|
||||||
5,10
|
|
||||||
5,15
|
|
||||||
6,2
|
|
||||||
6,5
|
|
||||||
6,7
|
|
||||||
6,9
|
|
||||||
6,11
|
|
||||||
6,13
|
|
||||||
7,1
|
|
||||||
7,3
|
|
||||||
7,6
|
|
||||||
7,8
|
|
||||||
7,12
|
|
||||||
7,14
|
|
||||||
8,5
|
|
||||||
8,9
|
|
||||||
8,15
|
|
||||||
9,3
|
|
||||||
9,8
|
|
||||||
9,13
|
|
||||||
10,1
|
|
||||||
10,4
|
|
||||||
10,7
|
|
||||||
10,9
|
|
||||||
10,11
|
|
||||||
11,3
|
|
||||||
11,10
|
|
||||||
11,13
|
|
||||||
11,15
|
|
||||||
12,2
|
|
||||||
12,5
|
|
||||||
12,7
|
|
||||||
12,9
|
|
||||||
12,11
|
|
||||||
12,14
|
|
||||||
13,1
|
|
||||||
13,6
|
|
||||||
13,8
|
|
||||||
13,13
|
|
||||||
14,3
|
|
||||||
14,5
|
|
||||||
14,9
|
|
||||||
14,12
|
|
||||||
15,1
|
|
||||||
15,7
|
|
||||||
15,10
|
|
||||||
15,14
|
|
||||||
|
Can't render this file because it has a wrong number of fields in line 17.
|
|
|
@ -2,7 +2,6 @@ package de.deversmann;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
de.deversmann.gui.HitoriApp app = new de.deversmann.gui.HitoriApp();
|
System.out.println("Hello, World!");
|
||||||
app.start();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
package de.deversmann.domain;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public class CSVReader {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Liest die CSV-Datei ein und gibt die enthaltenen Werte als zweidimensionales int-Array zurück.
|
|
||||||
*
|
|
||||||
* @param csvFile Pfad zur CSV-Datei
|
|
||||||
* @return zweidimensionales Array, das die Zahlen aus der CSV enthält
|
|
||||||
* @throws IOException wenn ein Fehler beim Lesen auftritt
|
|
||||||
*/
|
|
||||||
public int[][] readCsvToIntArray(String csvFile) throws IOException {
|
|
||||||
ArrayList<int[]> rows = new ArrayList<>();
|
|
||||||
|
|
||||||
try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {
|
|
||||||
String line;
|
|
||||||
while ((line = br.readLine()) != null) {
|
|
||||||
String[] tokens = line.split(",");
|
|
||||||
int[] row = new int[tokens.length];
|
|
||||||
for (int i = 0; i < tokens.length; i++) {
|
|
||||||
row[i] = Integer.parseInt(tokens[i].trim());
|
|
||||||
}
|
|
||||||
rows.add(row);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ArrayList in 2D-Array umwandeln
|
|
||||||
int[][] result = new int[rows.size()][];
|
|
||||||
for (int i = 0; i < rows.size(); i++) {
|
|
||||||
result[i] = rows.get(i);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
package de.deversmann.domain;
|
|
||||||
|
|
||||||
public class HighscoreEntry {
|
|
||||||
|
|
||||||
private final String playerName;
|
|
||||||
private final long timeSeconds;
|
|
||||||
private final int errorCount;
|
|
||||||
|
|
||||||
public HighscoreEntry(String playerName, long timeSeconds, int errorCount) {
|
|
||||||
this.playerName = playerName;
|
|
||||||
this.timeSeconds = timeSeconds;
|
|
||||||
this.errorCount = errorCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPlayerName() {
|
|
||||||
return playerName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTimeSeconds() {
|
|
||||||
return timeSeconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getErrorCount() {
|
|
||||||
return errorCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return playerName + " - " + timeSeconds + "s (Fehler: " + errorCount + ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,102 +0,0 @@
|
||||||
package de.deversmann.domain;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class HighscoreManager {
|
|
||||||
|
|
||||||
private Map<String, List<HighscoreEntry>> highscoreMap;
|
|
||||||
|
|
||||||
public HighscoreManager() {
|
|
||||||
this.highscoreMap = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addHighscore(String puzzleName, String playerName, long timeSeconds, int errorCount) {
|
|
||||||
highscoreMap.putIfAbsent(puzzleName, new ArrayList<>());
|
|
||||||
highscoreMap.get(puzzleName).add(new HighscoreEntry(playerName, timeSeconds, errorCount));
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<HighscoreEntry> getHighscores(String puzzleName) {
|
|
||||||
return highscoreMap.getOrDefault(puzzleName, Collections.emptyList());
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getAverageTime(String puzzleName) {
|
|
||||||
List<HighscoreEntry> entries = highscoreMap.get(puzzleName);
|
|
||||||
if (entries == null || entries.isEmpty()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
long sum = 0;
|
|
||||||
for (HighscoreEntry e : entries) {
|
|
||||||
sum += e.getTimeSeconds();
|
|
||||||
}
|
|
||||||
return (double) sum / entries.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveSinglePuzzle(String puzzleName, String filename) throws IOException {
|
|
||||||
List<HighscoreEntry> entries = getHighscores(puzzleName);
|
|
||||||
|
|
||||||
entries.sort(Comparator
|
|
||||||
.comparingInt(HighscoreEntry::getErrorCount)
|
|
||||||
.thenComparingLong(HighscoreEntry::getTimeSeconds));
|
|
||||||
|
|
||||||
double avgTime = getAverageTime(puzzleName);
|
|
||||||
|
|
||||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) {
|
|
||||||
if (avgTime < 0) {
|
|
||||||
writer.write("Durchschnittszeit: Keine Einträge");
|
|
||||||
} else {
|
|
||||||
writer.write(String.format("Durchschnittszeit: %.2f s", avgTime));
|
|
||||||
}
|
|
||||||
writer.newLine();
|
|
||||||
writer.newLine();
|
|
||||||
|
|
||||||
writer.write(String.format("%-6s | %-5s | %-6s | %-15s",
|
|
||||||
"Platz", "Zeit", "Fehler", "Name"));
|
|
||||||
writer.newLine();
|
|
||||||
writer.write("------------------------------------------------------------");
|
|
||||||
writer.newLine();
|
|
||||||
|
|
||||||
int place = 1;
|
|
||||||
for (HighscoreEntry e : entries) {
|
|
||||||
writer.write(String.format("%-6s | %-5d | %-6d | %-15s",
|
|
||||||
place + ".",
|
|
||||||
e.getTimeSeconds(),
|
|
||||||
e.getErrorCount(),
|
|
||||||
e.getPlayerName()));
|
|
||||||
writer.newLine();
|
|
||||||
place++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadSinglePuzzle(String puzzleName, String filename) throws IOException {
|
|
||||||
File file = new File(filename);
|
|
||||||
if (!file.exists()) {
|
|
||||||
System.out.println("Highscore-Datei " + filename + " existiert nicht; wird neu erstellt.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
|
||||||
// Durchschnittszeit und Header überspringen
|
|
||||||
reader.readLine();
|
|
||||||
reader.readLine();
|
|
||||||
reader.readLine();
|
|
||||||
reader.readLine();
|
|
||||||
|
|
||||||
String line;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
String[] parts = line.split("\\|");
|
|
||||||
if (parts.length < 4) continue;
|
|
||||||
|
|
||||||
String timeStr = parts[1].trim();
|
|
||||||
String errorStr = parts[2].trim();
|
|
||||||
String nameStr = parts[3].trim();
|
|
||||||
|
|
||||||
long timeSeconds = Long.parseLong(timeStr);
|
|
||||||
int errorCount = Integer.parseInt(errorStr);
|
|
||||||
|
|
||||||
addHighscore(puzzleName, nameStr, timeSeconds, errorCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
package de.deversmann.domain;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class PuzzleData {
|
|
||||||
|
|
||||||
private final int[][] puzzle;
|
|
||||||
private final List<int[]> solutionCoordinates;
|
|
||||||
|
|
||||||
public PuzzleData(int[][] puzzle, List<int[]> solutionCoordinates) {
|
|
||||||
this.puzzle = puzzle;
|
|
||||||
this.solutionCoordinates = solutionCoordinates;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int[][] getPuzzle() {
|
|
||||||
return puzzle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<int[]> getSolutionCoordinates() {
|
|
||||||
return solutionCoordinates;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,110 +1,4 @@
|
||||||
package de.deversmann.domain;
|
package de.deversmann.domain;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
public class Spielfeld {
|
public class Spielfeld {
|
||||||
|
|
||||||
private int[][] feld;
|
|
||||||
private String[][] zustand; // "grau", "schwarz", "weiß"
|
|
||||||
|
|
||||||
public Spielfeld() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ladeSpielfeld(String dateiPfad) {
|
|
||||||
try (BufferedReader br = new BufferedReader(new FileReader(dateiPfad))) {
|
|
||||||
String line;
|
|
||||||
int zeilenZaehler = 0;
|
|
||||||
|
|
||||||
|
|
||||||
while ((line = br.readLine()) != null) {
|
|
||||||
zeilenZaehler++;
|
|
||||||
}
|
|
||||||
|
|
||||||
br.close();
|
|
||||||
|
|
||||||
feld = new int[zeilenZaehler][];
|
|
||||||
zustand = new String[zeilenZaehler][];
|
|
||||||
|
|
||||||
try (BufferedReader br2 = new BufferedReader(new FileReader(dateiPfad))) {
|
|
||||||
int row = 0;
|
|
||||||
while ((line = br2.readLine()) != null) {
|
|
||||||
String[] werte = line.split(",");
|
|
||||||
feld[row] = new int[werte.length];
|
|
||||||
zustand[row] = new String[werte.length];
|
|
||||||
|
|
||||||
for (int col = 0; col < werte.length; col++) {
|
|
||||||
feld[row][col] = Integer.parseInt(werte[col]);
|
|
||||||
zustand[row][col] = "grau";
|
|
||||||
}
|
|
||||||
|
|
||||||
row++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.err.println("Fehler beim Laden des Spielfelds: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ladeZufaelligesSpielfeld(String ordnerPfad) {
|
|
||||||
File ordner = new File(ordnerPfad);
|
|
||||||
File[] dateien = ordner.listFiles((dir, name) -> name.endsWith(".csv"));
|
|
||||||
|
|
||||||
if (dateien != null && dateien.length > 0) {
|
|
||||||
Random random = new Random();
|
|
||||||
File zufallsDatei = dateien[random.nextInt(dateien.length)];
|
|
||||||
ladeSpielfeld(zufallsDatei.getAbsolutePath());
|
|
||||||
} else {
|
|
||||||
System.err.println("Keine CSV-Dateien im Verzeichnis gefunden!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setzeZustand(int x, int y, String neuerZustand) {
|
|
||||||
if (istImBereich(x, y)) {
|
|
||||||
zustand[x][y] = neuerZustand;
|
|
||||||
} else {
|
|
||||||
System.err.println("Koordinaten außerhalb des Spielfelds!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getZustand(int x, int y) {
|
|
||||||
if (istImBereich(x, y)) {
|
|
||||||
return zustand[x][y];
|
|
||||||
} else {
|
|
||||||
System.err.println("Koordinaten außerhalb des Spielfelds!");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getWert(int x, int y) {
|
|
||||||
if (istImBereich(x, y)) {
|
|
||||||
return feld[x][y];
|
|
||||||
} else {
|
|
||||||
System.err.println("Koordinaten außerhalb des Spielfelds!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reset() {
|
|
||||||
for (int i = 0; i < zustand.length; i++) {
|
|
||||||
for (int j = 0; j < zustand[i].length; j++) {
|
|
||||||
zustand[i][j] = "grau";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getBreite() {
|
|
||||||
return feld[0].length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHoehe() {
|
|
||||||
return feld.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean istImBereich(int x, int y) {
|
|
||||||
return x >= 0 && x < feld.length && y >= 0 && y < feld[0].length;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
package de.deversmann.domain;
|
|
||||||
|
|
||||||
public class Zeiterfassung {
|
|
||||||
|
|
||||||
private long startTime;
|
|
||||||
private long endTime;
|
|
||||||
private boolean isRunning;
|
|
||||||
|
|
||||||
public Zeiterfassung() {
|
|
||||||
this.isRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() {
|
|
||||||
if (!isRunning) {
|
|
||||||
startTime = System.currentTimeMillis();
|
|
||||||
isRunning = true;
|
|
||||||
System.out.println("Zeiterfassung gestartet");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
if (isRunning) {
|
|
||||||
endTime = System.currentTimeMillis();
|
|
||||||
isRunning = false;
|
|
||||||
System.out.println("Zeiterfassung gestoppt, diff=" + getElapsedTimeInSeconds() + "s");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getElapsedTimeInSeconds() {
|
|
||||||
if (isRunning) {
|
|
||||||
long current = System.currentTimeMillis();
|
|
||||||
return (current - startTime) / 1000;
|
|
||||||
} else {
|
|
||||||
return (endTime - startTime) / 1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package de.deversmann.facade;
|
package de.deversmann.facade;
|
||||||
|
|
||||||
public class Facade {
|
public class Facade {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,235 +0,0 @@
|
||||||
package de.deversmann.gui;
|
|
||||||
|
|
||||||
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<String> 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<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);
|
|
||||||
}
|
|
||||||
|
|
||||||
private 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
package de.deversmann.gui;
|
||||||
|
|
||||||
|
public class Spielfeld {
|
||||||
|
}
|
||||||
|
|
@ -1,136 +0,0 @@
|
||||||
package de.deversmann.gui;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.event.MouseAdapter;
|
|
||||||
import java.awt.event.MouseEvent;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class SpielfeldGUI extends JPanel {
|
|
||||||
|
|
||||||
private JLabel[][] grid;
|
|
||||||
private Set<String> errorCells = new HashSet<>();
|
|
||||||
|
|
||||||
public SpielfeldGUI(int rows, int cols) {
|
|
||||||
setLayout(new GridLayout(rows, cols));
|
|
||||||
grid = new JLabel[rows][cols];
|
|
||||||
|
|
||||||
for (int r = 0; r < rows; r++) {
|
|
||||||
for (int c = 0; c < cols; c++) {
|
|
||||||
JLabel label = createCellLabel("-", r, c);
|
|
||||||
grid[r][c] = label;
|
|
||||||
add(label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateGrid(int[][] feld) {
|
|
||||||
if (feld == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
removeAll();
|
|
||||||
int rows = feld.length;
|
|
||||||
int cols = feld[0].length;
|
|
||||||
setLayout(new GridLayout(rows, cols));
|
|
||||||
grid = new JLabel[rows][cols];
|
|
||||||
errorCells.clear();
|
|
||||||
|
|
||||||
for (int r = 0; r < rows; r++) {
|
|
||||||
for (int c = 0; c < cols; c++) {
|
|
||||||
String text = String.valueOf(feld[r][c]);
|
|
||||||
JLabel label = createCellLabel(text, r, c);
|
|
||||||
grid[r][c] = label;
|
|
||||||
add(label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
revalidate();
|
|
||||||
repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAllNonBlackToWhite() {
|
|
||||||
if (grid == null) return;
|
|
||||||
for (int r = 0; r < grid.length; r++) {
|
|
||||||
for (int c = 0; c < grid[r].length; c++) {
|
|
||||||
JLabel lbl = grid[r][c];
|
|
||||||
if (lbl != null) {
|
|
||||||
if (!lbl.getBackground().equals(Color.BLACK)) {
|
|
||||||
lbl.setBackground(Color.WHITE);
|
|
||||||
lbl.setForeground(Color.BLACK);
|
|
||||||
clearErrorMark(r, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void markCellAsError(int row, int col) {
|
|
||||||
if (!isValidCell(row, col)) return;
|
|
||||||
errorCells.add(row + "," + col);
|
|
||||||
grid[row][col].setBorder(BorderFactory.createLineBorder(Color.RED, 3));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearErrorMark(int row, int col) {
|
|
||||||
errorCells.remove(row + "," + col);
|
|
||||||
if (!isValidCell(row, col)) return;
|
|
||||||
grid[row][col].setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<int[]> getBlackCells() {
|
|
||||||
List<int[]> black = new ArrayList<>();
|
|
||||||
if (grid == null) return black;
|
|
||||||
|
|
||||||
for (int r = 0; r < grid.length; r++) {
|
|
||||||
for (int c = 0; c < grid[r].length; c++) {
|
|
||||||
JLabel lbl = grid[r][c];
|
|
||||||
if (lbl != null && lbl.getBackground().equals(Color.BLACK)) {
|
|
||||||
black.add(new int[]{r, c});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return black;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCellBlack(int row, int col) {
|
|
||||||
if (!isValidCell(row, col)) return;
|
|
||||||
JLabel lbl = grid[row][col];
|
|
||||||
lbl.setBackground(Color.BLACK);
|
|
||||||
lbl.setForeground(Color.WHITE);
|
|
||||||
clearErrorMark(row, col);
|
|
||||||
}
|
|
||||||
|
|
||||||
private JLabel createCellLabel(String text, int row, int col) {
|
|
||||||
JLabel label = new JLabel(text, SwingConstants.CENTER);
|
|
||||||
label.setOpaque(true);
|
|
||||||
label.setBackground(Color.GRAY);
|
|
||||||
label.setForeground(Color.BLACK);
|
|
||||||
label.setFont(new Font("Arial", Font.BOLD, 24));
|
|
||||||
label.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
|
|
||||||
|
|
||||||
label.addMouseListener(new MouseAdapter() {
|
|
||||||
@Override
|
|
||||||
public void mouseClicked(MouseEvent e) {
|
|
||||||
toggleColor(label, row, col);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void toggleColor(JLabel label, int row, int col) {
|
|
||||||
if (label.getBackground().equals(Color.GRAY) || label.getBackground().equals(Color.WHITE)) {
|
|
||||||
label.setBackground(Color.BLACK);
|
|
||||||
label.setForeground(Color.WHITE);
|
|
||||||
} else {
|
|
||||||
label.setBackground(Color.WHITE);
|
|
||||||
label.setForeground(Color.BLACK);
|
|
||||||
}
|
|
||||||
if (errorCells.contains(row + "," + col)) {
|
|
||||||
clearErrorMark(row, col);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isValidCell(int r, int c) {
|
|
||||||
if (grid == null) return false;
|
|
||||||
return (r >= 0 && r < grid.length && c >= 0 && c < grid[r].length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue