Compare commits

..

No commits in common. "1b64e31951e87355ed4655694da8dde40de30c73" and "8f7d815eb59f9bb70454a024ccca47cda861f408" have entirely different histories.

6 changed files with 87 additions and 348 deletions

View File

@ -54,22 +54,7 @@ public class HitoriBoard {
} }
} }
public void setNumbers(int[][] numbers) {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
board[i][j].setNumber(numbers[i][j]);
}
}
}
public int[][] getNumbers() {
int[][] numbers = new int[board.length][board[0].length];
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
numbers[i][j] = board[i][j].getNumber();
}
}
return numbers;
}
} }

View File

@ -9,7 +9,7 @@ public class HitoriCell {
public enum CellState { public enum CellState {
GRAY, WHITE, BLACK GRAY, WHITE, BLACK
} }
private int number; private final int number;
private CellState state; private CellState state;
public HitoriCell(int number) { public HitoriCell(int number) {
@ -29,8 +29,4 @@ public class HitoriCell {
this.state = state; this.state = state;
} }
public void setNumber(int number) {
this.number = number;
}
} }

View File

@ -1,37 +0,0 @@
package PR2.HitoriSpiel.Domain;
import java.util.Stack;
public class StateManager {
private final Stack<int[][]> undoStack = new Stack<>();
private final Stack<int[][]> redoStack = new Stack<>();
public void saveState(int[][] state) {
undoStack.push(copyArray(state));
redoStack.clear(); // Redo-Stack leeren, da ein neuer Zustand hinzugefügt wurde
}
public int[][] undo(int[][] currentState) {
if (!undoStack.isEmpty()) {
redoStack.push(copyArray(currentState)); // Aktuellen Zustand im Redo-Stack speichern
return undoStack.pop();
}
return null; // Kein Zustand zum Zurücksetzen
}
public int[][] redo(int[][] currentState) {
if (!redoStack.isEmpty()) {
undoStack.push(copyArray(currentState)); // Aktuellen Zustand im Undo-Stack speichern
return redoStack.pop();
}
return null; // Kein Zustand zum Wiederherstellen
}
private int[][] copyArray(int[][] original) {
int[][] copy = new int[original.length][];
for (int i = 0; i < original.length; i++) {
copy[i] = original[i].clone();
}
return copy;
}
}

View File

@ -1,170 +1,38 @@
package PR2.HitoriSpiel.GUI; package PR2.HitoriSpiel.GUI;
import PR2.HitoriSpiel.Domain.StateManager;
import PR2.HitoriSpiel.Domain.HitoriBoard; import PR2.HitoriSpiel.Domain.HitoriBoard;
import PR2.HitoriSpiel.Domain.HitoriCell; import PR2.HitoriSpiel.Domain.HitoriCell;
import PR2.HitoriSpiel.Domain.HitoriValidator; import PR2.HitoriSpiel.Domain.HitoriValidator;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.io.FileWriter; import java.awt.event.ActionEvent;
import java.io.IOException;
public class GameBoard extends JPanel { public class GameBoard extends JPanel {
private final HitoriBoard board;
private Timer timer;
private long startTime;
private JLabel timerLabel;
private final StateManager stateManager = new StateManager();
private final HitoriBoard board; // Verbindung zur Logik
public GameBoard(HitoriBoard board) { public GameBoard(HitoriBoard board) {
this.board = board; this.board = board;
setLayout(new BorderLayout()); setLayout(new GridLayout(board.getSize(), board.getSize()));
// Timer-Label oben hinzufügen // Buttons für jede Zelle erstellen
timerLabel = new JLabel("Zeit: 0 Sekunden");
timerLabel.setHorizontalAlignment(SwingConstants.CENTER);
add(timerLabel, BorderLayout.NORTH);
// Timer starten
startTimer();
// Spielfeld erstellen
JPanel gamePanel = new JPanel(new GridLayout(board.getSize(), board.getSize()));
for (int i = 0; i < board.getSize(); i++) { for (int i = 0; i < board.getSize(); i++) {
for (int j = 0; j < board.getSize(); j++) { for (int j = 0; j < board.getSize(); j++) {
HitoriCell cell = board.getCell(i, j); HitoriCell cell = board.getCell(i, j);
JButton button = createCellButton(cell, i, j); JButton button = createCellButton(cell, i, j);
gamePanel.add(button); add(button);
} }
} }
add(gamePanel, BorderLayout.CENTER);
// Kontroll-Buttons unten hinzufügen
JPanel controlPanel = createControlPanel();
add(controlPanel, BorderLayout.SOUTH);
}
private void startTimer() {
startTime = System.currentTimeMillis();
timer = new Timer(1000, e -> {
long elapsedTime = (System.currentTimeMillis() - startTime) / 1000;
timerLabel.setText("Zeit: " + elapsedTime + " Sekunden");
});
timer.start();
}
private void stopTimer() {
if (timer != null) {
timer.stop();
}
}
private JPanel createControlPanel() {
JPanel controlPanel = new JPanel();
JButton resetButton = createButton("Zurücksetzen", 200, 30);
resetButton.addActionListener(e -> {
saveStateForUndo();
resetBoard();
refreshBoard();
});
JButton undoButton = createButton("Undo", 200, 30);
undoButton.addActionListener(e -> {
int[][] previousState = stateManager.undo(board.getNumbers());
if (previousState != null) {
board.setNumbers(previousState);
refreshBoard();
} else {
JOptionPane.showMessageDialog(this, "Kein Zustand zum Zurücksetzen vorhanden.", "Undo", JOptionPane.INFORMATION_MESSAGE);
}
});
JButton redoButton = createButton("Redo", 200, 30);
redoButton.addActionListener(e -> {
int[][] nextState = stateManager.redo(board.getNumbers());
if (nextState != null) {
board.setNumbers(nextState);
refreshBoard();
} else {
JOptionPane.showMessageDialog(this, "Kein Zustand zum Wiederholen vorhanden.", "Redo", JOptionPane.INFORMATION_MESSAGE);
}
});
JButton validateButton = createButton("Validieren", 200, 30);
validateButton.addActionListener(e -> {
if (validateCurrentBoard()) {
stopTimer();
JOptionPane.showMessageDialog(this, "Das Spielfeld ist korrekt gelöst!", "Erfolg", JOptionPane.INFORMATION_MESSAGE);
} else {
JOptionPane.showMessageDialog(this, "Das Spielfeld enthält Fehler!", "Fehler", JOptionPane.ERROR_MESSAGE);
}
});
JButton pauseButton = createButton("Pause", 200, 30);
pauseButton.addActionListener(e -> {
stopTimer();
showPauseMenu();
});
controlPanel.add(resetButton);
controlPanel.add(undoButton);
controlPanel.add(redoButton);
controlPanel.add(validateButton);
controlPanel.add(pauseButton);
return controlPanel;
}
public void resetBoard() {
// Spielfeldlogik zurücksetzen
//stopTimer();
//startTimer(); // Timer neu starten
board.resetBoard();
removeAll();
add(timerLabel, BorderLayout.NORTH);
JPanel gamePanel = new JPanel(new GridLayout(board.getSize(), board.getSize()));
for (int i = 0; i < board.getSize(); i++) {
for (int j = 0; j < board.getSize(); j++) {
HitoriCell cell = board.getCell(i, j);
JButton button = createCellButton(cell, i, j);
gamePanel.add(button);
}
}
add(gamePanel, BorderLayout.CENTER);
// Kontroll-Buttons unten behalten
JPanel controlPanel = createControlPanel();
add(controlPanel, BorderLayout.SOUTH);
// Oberfläche neu laden
revalidate();
repaint();
}
// TODO: Spiel validieren
public boolean validateCurrentBoard() {
return true;
}
private void showPauseMenu() {
PauseMenu pauseMenu = new PauseMenu(
(JFrame) SwingUtilities.getWindowAncestor(this),
e -> startTimer(), // Spiel fortsetzen
e -> returnToMainMenu(), // Zum Hauptmenü
e -> System.exit(0) // Spiel beenden
);
pauseMenu.setVisible(true);
} }
private JButton createCellButton(HitoriCell cell, int row, int col) { private JButton createCellButton(HitoriCell cell, int row, int col) {
JButton button = new JButton(String.valueOf(cell.getNumber())); JButton button = new JButton(String.valueOf(cell.getNumber()));
button.setBackground(Color.LIGHT_GRAY); updateButtonState(button, cell);
button.addActionListener(e -> {
// ActionListener für Benutzereinganen
button.addActionListener((ActionEvent e) -> {
toggleCellState(cell); toggleCellState(cell);
updateButtonState(button, cell); updateButtonState(button, cell);
}); });
@ -191,7 +59,6 @@ public class GameBoard extends JPanel {
switch (cell.getState()) { switch (cell.getState()) {
case GRAY: case GRAY:
button.setBackground(Color.LIGHT_GRAY); button.setBackground(Color.LIGHT_GRAY);
button.setText(String.valueOf(cell.getNumber()));
break; break;
case BLACK: case BLACK:
button.setBackground(Color.BLACK); button.setBackground(Color.BLACK);
@ -199,68 +66,33 @@ public class GameBoard extends JPanel {
break; break;
case WHITE: case WHITE:
button.setBackground(Color.WHITE); button.setBackground(Color.WHITE);
button.setText(String.valueOf(cell.getNumber()));
button.setForeground(Color.BLACK); button.setForeground(Color.BLACK);
break; break;
} }
} }
private void saveGame() { public void resetBoard() {
try { board.resetBoard(); // Logik zurücksetzen
FileWriter writer = new FileWriter("hitori_savegame.txt"); removeAll(); // Entferne alle bisherigen Komponenten (Buttons)
writer.write("Spielzeit: " + (System.currentTimeMillis() - startTime) / 1000 + " Sekunden\n"); setLayout(new GridLayout(board.getSize(), board.getSize()));
writer.write("Spielfeldzustand:\n");
for (int i = 0; i < board.getSize(); i++) {
for (int j = 0; j < board.getSize(); j++) {
writer.write(board.getCell(i, j).getState().name() + " ");
}
writer.write("\n");
}
writer.close();
JOptionPane.showMessageDialog(this, "Spiel erfolgreich gespeichert.");
} catch (IOException ex) {
JOptionPane.showMessageDialog(this, "Fehler beim Speichern des Spiels: " + ex.getMessage(), "Fehler", JOptionPane.ERROR_MESSAGE);
}
}
private void returnToMainMenu() { // Neue Buttons erstellen und hinzufügen
// Eltern-Frame abrufen
JFrame parentFrame = (JFrame) SwingUtilities.getWindowAncestor(this);
// Inhalt des Frames auf das Hauptmenü setzen
parentFrame.getContentPane().removeAll();
parentFrame.add(new StartMenu());
parentFrame.revalidate();
parentFrame.repaint();
}
private JButton createButton(String text, int width, int height) {
JButton button = new JButton(text);
button.setPreferredSize(new Dimension(width, height));
return button;
}
private void refreshBoard() {
removeAll();
JPanel gamePanel = new JPanel(new GridLayout(board.getSize(), board.getSize()));
for (int i = 0; i < board.getSize(); i++) { for (int i = 0; i < board.getSize(); i++) {
for (int j = 0; j < board.getSize(); j++) { for (int j = 0; j < board.getSize(); j++) {
HitoriCell cell = board.getCell(i, j); HitoriCell cell = board.getCell(i, j);
JButton button = createCellButton(cell, i, j); JButton button = createCellButton(cell, i, j);
gamePanel.add(button); add(button);
} }
} }
add(gamePanel, BorderLayout.CENTER);
JPanel controlPanel = createControlPanel(); revalidate(); // Layout neu laden
add(controlPanel, BorderLayout.SOUTH); repaint(); // Oberfläche neu zeichnen
System.out.println("Spielfeld wurde aktualisiert");
revalidate();
repaint();
} }
private void saveStateForUndo() { public boolean validateCurrentBoard() {
stateManager.saveState(board.getNumbers()); HitoriValidator validator = new HitoriValidator(board);
return validator.validateBoard(board.getSolutionCoordinates());
} }
} }

View File

@ -1,47 +0,0 @@
package PR2.HitoriSpiel.GUI;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
public class PauseMenu extends JDialog {
public PauseMenu(JFrame parent, ActionListener resumeAction, ActionListener mainMenuAction, ActionListener exitAction) {
super(parent, "Pause", true);
setLayout(new GridLayout(3, 1));
setSize(300, 200);
setLocationRelativeTo(parent);
// "Spiel fortsetzen"-Button
JButton resumeButton = new JButton("Spiel fortsetzen");
resumeButton.addActionListener(e -> {
dispose();
if (resumeAction != null) {
resumeAction.actionPerformed(e);
}
});
// "Zum Hauptmenü"-Button
JButton mainMenuButton = new JButton("Zum Hauptmenü");
mainMenuButton.addActionListener(e -> {
dispose();
if (mainMenuAction != null) {
mainMenuAction.actionPerformed(e);
}
});
// "Spiel beenden"-Button
JButton exitButton = new JButton("Spiel beenden");
exitButton.addActionListener(e -> {
dispose();
if (exitAction != null) {
exitAction.actionPerformed(e);
}
});
// Buttons hinzufügen
add(resumeButton);
add(mainMenuButton);
add(exitButton);
}
}

View File

@ -8,9 +8,6 @@ import java.awt.*;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import java.util.Random;
import static PR2.HitoriSpiel.GUI.BoardLoader.loadBoard;
public class StartMenu extends JFrame { public class StartMenu extends JFrame {
private JPanel mainPanel; private JPanel mainPanel;
@ -98,7 +95,7 @@ public class StartMenu extends JFrame {
System.out.println("Lade Datei von Pfad: " + resourcePath); System.out.println("Lade Datei von Pfad: " + resourcePath);
int[][] boardData = loadBoard(resourcePath); int[][] boardData = BoardLoader.loadBoard(resourcePath);
List<String> solutionCoordinates = HitoriSolutionLoader.loadSolution(resourcePath); List<String> solutionCoordinates = HitoriSolutionLoader.loadSolution(resourcePath);
HitoriBoard hitoriBoard = new HitoriBoard(boardData, solutionCoordinates); // Stelle sicher, dass die Lösung korrekt geladen wird HitoriBoard hitoriBoard = new HitoriBoard(boardData, solutionCoordinates); // Stelle sicher, dass die Lösung korrekt geladen wird
@ -106,7 +103,7 @@ public class StartMenu extends JFrame {
loadGameBoard2(gameBoard, solutionCoordinates); loadGameBoard2(gameBoard, solutionCoordinates);
//loadGameBoard(boardData); //loadGameBoard(boardData);
// addGameControls(gameBoard); addGameControls(gameBoard);
System.out.println("Verfügbare Spielfelder: " + boardFileNames); System.out.println("Verfügbare Spielfelder: " + boardFileNames);
System.out.println("Ausgewählte Datei: " + selectedFile); System.out.println("Ausgewählte Datei: " + selectedFile);
@ -122,46 +119,10 @@ public class StartMenu extends JFrame {
} }
private void randomBoard() { private void randomBoard() {
// Lade alle verfügbaren Spielfeld-Dateien // TODO: Logik zum Auswählen eines zufälligen Spielfeldes implementieren
List<String> boardFileNames = BoardLoader.loadBoardsAsList(); JOptionPane.showMessageDialog(this, "Zufälliges Spielfeld wurde angeklickt");
// Überprüfe, ob Dateien verfügbar sind
if (boardFileNames.isEmpty()) {
JOptionPane.showMessageDialog(this, "Keine Spielfelder gefunden.", "Fehler", JOptionPane.ERROR_MESSAGE);
return;
} }
// Wähle eine zufällige Datei
String randomFile = boardFileNames.get(new Random().nextInt(boardFileNames.size()));
System.out.println("Zufällige Datei gewählt: " + randomFile);
try {
// Lade das zufällige Spielfeld
String resourcePath = "/persistent/Hitori_Spielfelder/" + randomFile;
System.out.println("Lade Datei von Pfad: " + resourcePath);
InputStream inputStream = getClass().getResourceAsStream(resourcePath);
if (inputStream == null) {
throw new IOException("Ressourcendatei nicht gefunden: " + resourcePath);
}
// Spielfeld-Daten laden
int[][] boardData = BoardLoader.loadBoard(resourcePath);
List<String> solutionCoordinates = HitoriSolutionLoader.loadSolution(resourcePath);
// Spielfeld erstellen und anzeigen
HitoriBoard hitoriBoard = new HitoriBoard(boardData, solutionCoordinates);
GameBoard gameBoard = new GameBoard(hitoriBoard);
loadGameBoard2(gameBoard, solutionCoordinates);
} catch (IOException e) {
// Fehler beim Laden des Spielfelds
JOptionPane.showMessageDialog(this, "Fehler beim Laden des Spielfelds: " + e.getMessage(), "Fehler", JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
}
}
private void highscorelist() { private void highscorelist() {
// TODO: Logik zur Anzeige der Highscoreliste implementieren // TODO: Logik zur Anzeige der Highscoreliste implementieren
JOptionPane.showMessageDialog(this, "Highscoreliste wurde angeklickt"); JOptionPane.showMessageDialog(this, "Highscoreliste wurde angeklickt");
@ -191,5 +152,54 @@ public class StartMenu extends JFrame {
mainPanel.repaint(); mainPanel.repaint();
} }
private void addGameControls(GameBoard gameBoard) {
JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); // Buttons zentriert anordnen
// "Zurücksetzen"-Button
JButton resetButton = createButton("Zurücksetzen", 200, 30);
resetButton.addActionListener(e -> {
System.out.println("Reset-Button gedrückt");
gameBoard.resetBoard(); // Zurücksetzen des Spielfelds
//JOptionPane.showMessageDialog(this, "Spielfeld zurückgesetzt!", "Info", JOptionPane.INFORMATION_MESSAGE);
});
// "Validieren"-Button
JButton validateButton = createButton("Validieren", 200, 30);
validateButton.addActionListener(e -> {
boolean isValid = gameBoard.validateCurrentBoard(); // Prüfen, ob das Spielfeld korrekt gelöst ist
if (isValid) {
JOptionPane.showMessageDialog(this, "Das Spielfeld ist korrekt gelöst!", "Erfolg", JOptionPane.INFORMATION_MESSAGE);
} else {
JOptionPane.showMessageDialog(this, "Das Spielfeld enthält Fehler!", "Fehler", JOptionPane.ERROR_MESSAGE);
}
});
controlPanel.add(resetButton);
controlPanel.add(validateButton);
// Control-Panel unterhalb des Spielfelds hinzufügen
mainPanel.add(controlPanel, BorderLayout.SOUTH);
mainPanel.revalidate();
mainPanel.repaint();
}
/* private void loadAndShowGameBoard(String resourcePath) {
try {
int[][] boardData = BoardLoader.loadBoard(resourcePath);
List<String> solutionCoordinates = HitoriSolutionLoader.loadSolution(resourcePath);
HitoriBoard hitoriBoard = new HitoriBoard(boardData, solutionCoordinates);
GameBoard gameBoard = new GameBoard(hitoriBoard);
loadGameBoard(boardData);
addGameControls(gameBoard);
} catch (IOException ex) {
JOptionPane.showMessageDialog(this, "Fehler beim Laden des Spielfelds: " + ex.getMessage(), "Fehler", JOptionPane.ERROR_MESSAGE);
ex.printStackTrace();
}
}*/
} }