Änderungen für Redo und Undo Button vorgenommen

currentStatus
Vickvick2002 2025-01-05 15:18:52 +01:00
parent 3d0f808daf
commit eb30f5cd13
3 changed files with 142 additions and 88 deletions

View File

@ -1,37 +1,77 @@
package PR2.HitoriSpiel.Domain; package PR2.HitoriSpiel.Domain;
import java.io.*;
import java.util.Stack; import java.util.Stack;
public class StateManager { public class StateManager implements Serializable {
private final Stack<int[][]> undoStack = new Stack<>(); private final Stack<int[][]> undoStack = new Stack<>();
private final Stack<int[][]> redoStack = new Stack<>(); private final Stack<int[][]> redoStack = new Stack<>();
public void saveState(int[][] state) { public void saveState(int[][] state) {
undoStack.push(copyArray(state)); undoStack.push(copyState(state));
redoStack.clear(); // Redo-Stack leeren, da ein neuer Zustand hinzugefügt wurde redoStack.clear(); // Redo-Stack leeren, da ein neuer Zustand hinzugefügt wurde
} }
// Macht die letzte Änderung rückgängig
public int[][] undo(int[][] currentState) { public int[][] undo(int[][] currentState) {
if (!undoStack.isEmpty()) { if (!undoStack.isEmpty()) {
redoStack.push(copyArray(currentState)); // Aktuellen Zustand im Redo-Stack speichern redoStack.push(copyState(currentState)); // Speichere aktuellen Zustand für Redo
return undoStack.pop(); return undoStack.pop(); // Gib den vorherigen Zustand zurück
} }
return null; // Kein Zustand zum Zurücksetzen return null; // Kein Zustand mehr verfügbar
} }
// Wiederholt die letzte rückgängig gemachte Änderung
public int[][] redo(int[][] currentState) { public int[][] redo(int[][] currentState) {
if (!redoStack.isEmpty()) { if (!redoStack.isEmpty()) {
undoStack.push(copyArray(currentState)); // Aktuellen Zustand im Undo-Stack speichern undoStack.push(copyState(currentState)); // Speichere aktuellen Zustand für Undo
return redoStack.pop(); return redoStack.pop(); // Gib den Redo-Zustand zurück
} }
return null; // Kein Zustand zum Wiederherstellen return null; // Kein Zustand verfügbar
} }
private int[][] copyArray(int[][] original) { // Hilfsmethode, um eine Kopie des Zustands zu erstellen
int[][] copy = new int[original.length][]; private int[][] copyState(int[][] state) {
for (int i = 0; i < original.length; i++) { int[][] copy = new int[state.length][state[0].length];
copy[i] = original[i].clone(); for (int i = 0; i < state.length; i++) {
System.arraycopy(state[i], 0, copy[i], 0, state[i].length);
} }
return copy; return copy;
} }
// Speichert die gesamte StateManager-Instanz in einer Datei
public void saveStateToFile() {
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("undoRedoState.dat"))) {
out.writeObject(undoStack); // Schreibe den Undo-Stack
out.writeObject(redoStack); // Schreibe den Redo-Stack
System.out.println("Zustände wurden erfolgreich gespeichert.");
} catch (IOException e) {
System.err.println("Fehler beim Speichern der Zustände: " + e.getMessage());
}
}
// Lädt den StateManager aus einer Datei
public static StateManager loadStateFromFile() {
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("undoRedoState.dat"))) {
StateManager stateManager = new StateManager();
stateManager.undoStack.addAll((Stack<int[][]>) in.readObject());
stateManager.redoStack.addAll((Stack<int[][]>) in.readObject());
System.out.println("Zustände wurden erfolgreich geladen.");
return stateManager;
} catch (IOException | ClassNotFoundException e) {
System.err.println("Fehler beim Laden der Zustände: " + e.getMessage());
return new StateManager(); // Gibt eine neue Instanz zurück, falls ein Fehler auftritt
}
}
// Überprüft, ob Undo-Operationen verfügbar sind
public boolean canUndo() {
return !undoStack.isEmpty();
}
// Überprüft, ob Redo-Operationen verfügbar sind
public boolean canRedo() {
return !redoStack.isEmpty();
}
} }

View File

@ -17,6 +17,7 @@ public class GameBoard extends JPanel {
private Timer timer; private Timer timer;
private long startTime; private long startTime;
private JLabel timerLabel; private JLabel timerLabel;
private JPanel gamePanel; // Das Spielfeld als JPanel
private final StateManager stateManager = new StateManager(); private final StateManager stateManager = new StateManager();
@ -34,14 +35,7 @@ public class GameBoard extends JPanel {
startTimer(); startTimer();
// Spielfeld erstellen // Spielfeld erstellen
JPanel gamePanel = new JPanel(new GridLayout(board.getSize(), board.getSize())); gamePanel = createGamePanel();
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); add(gamePanel, BorderLayout.CENTER);
// Kontroll-Buttons unten hinzufügen // Kontroll-Buttons unten hinzufügen
@ -71,7 +65,7 @@ public class GameBoard extends JPanel {
resetButton.addActionListener(e -> { resetButton.addActionListener(e -> {
saveStateForUndo(); saveStateForUndo();
resetBoard(); resetBoard();
refreshBoard(); //refreshBoard();
}); });
JButton undoButton = Setup.createGameBoardButton("Undo", 80, 30); JButton undoButton = Setup.createGameBoardButton("Undo", 80, 30);
@ -79,7 +73,7 @@ public class GameBoard extends JPanel {
int[][] previousState = stateManager.undo(board.getNumbers()); int[][] previousState = stateManager.undo(board.getNumbers());
if (previousState != null) { if (previousState != null) {
board.setNumbers(previousState); board.setNumbers(previousState);
refreshBoard(); updateBoard();
} else { } else {
JOptionPane.showMessageDialog(this, "Kein Zustand zum Zurücksetzen vorhanden.", "Undo", JOptionPane.INFORMATION_MESSAGE); JOptionPane.showMessageDialog(this, "Kein Zustand zum Zurücksetzen vorhanden.", "Undo", JOptionPane.INFORMATION_MESSAGE);
} }
@ -112,7 +106,6 @@ public class GameBoard extends JPanel {
showPauseMenu(); showPauseMenu();
}); });
controlPanel.add(resetButton); controlPanel.add(resetButton);
controlPanel.add(undoButton); controlPanel.add(undoButton);
controlPanel.add(redoButton); controlPanel.add(redoButton);
@ -122,35 +115,6 @@ public class GameBoard extends JPanel {
return controlPanel; return controlPanel;
} }
public void resetBoard() {
// Spiellogik zurücksetzen
board.resetBoard();
// Spielfeld (CENTER) entfernen und neu erstellen
if (getLayout() instanceof BorderLayout) {
BorderLayout layout = (BorderLayout) getLayout();
// Komponente im CENTER entfernen
Component centerComponent = layout.getLayoutComponent(BorderLayout.CENTER);
if (centerComponent != null) {
remove(centerComponent);
}
// Neues Spielfeld hinzufügen
add(createGamePanel(), BorderLayout.CENTER);
// Kontroll-Buttons (SOUTH) entfernen und neu hinzufügen
Component southComponent = layout.getLayoutComponent(BorderLayout.SOUTH);
if (southComponent != null) {
remove(southComponent);
}
add(createControlPanel(), BorderLayout.SOUTH);
}
// Oberfläche aktualisieren
revalidate();
repaint();
}
public boolean validateCurrentBoard() { public boolean validateCurrentBoard() {
HitoriValidator validator = new HitoriValidator(board); HitoriValidator validator = new HitoriValidator(board);
@ -178,12 +142,10 @@ public class GameBoard extends JPanel {
} }
private void toggleCellState(HitoriCell cell) { private void toggleCellState(HitoriCell cell) {
if (cell == null) { if (cell == null) {
System.err.println("Ungültige Zelle! Der Zustand kann nicht geändert werden."); System.err.println("Ungültige Zelle! Der Zustand kann nicht geändert werden.");
return; return;
} }
if (cell.getState() == HitoriCell.CellState.GRAY) { if (cell.getState() == HitoriCell.CellState.GRAY) {
cell.setState(HitoriCell.CellState.BLACK); cell.setState(HitoriCell.CellState.BLACK);
} else if (cell.getState() == HitoriCell.CellState.BLACK) { } else if (cell.getState() == HitoriCell.CellState.BLACK) {
@ -211,22 +173,8 @@ public class GameBoard extends JPanel {
} }
} }
private void saveGame() { private void saveStateForUndo() {
try { stateManager.saveState(board.getNumbers());
FileWriter writer = new FileWriter("hitori_savegame.txt");
writer.write("Spielzeit: " + (System.currentTimeMillis() - startTime) / 1000 + " Sekunden\n");
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 addHighscore() { private void addHighscore() {
@ -280,22 +228,60 @@ public class GameBoard extends JPanel {
} }
} }
private JButton createButton(String text, int width, int height) { public void resetBoard() {
JButton button = new JButton(text); // Spiellogik zurücksetzen
button.setPreferredSize(new Dimension(width, height)); board.resetBoard();
return button; // Spielfeld (CENTER) entfernen und neu erstellen
} if (getLayout() instanceof BorderLayout) {
BorderLayout layout = (BorderLayout) getLayout();
private void refreshBoard() { // Komponente im CENTER entfernen
remove(1); // Entferne das aktuelle Spielfeld im CENTER Component centerComponent = layout.getLayoutComponent(BorderLayout.CENTER);
add(createGamePanel(), BorderLayout.CENTER); // Füge das neue Spielfeld hinzu if (centerComponent != null) {
remove(centerComponent);
}
// Neues Spielfeld hinzufügen
add(createGamePanel(), BorderLayout.CENTER);
// Kontroll-Buttons (SOUTH) entfernen und neu hinzufügen
Component southComponent = layout.getLayoutComponent(BorderLayout.SOUTH);
if (southComponent != null) {
remove(southComponent);
}
add(createControlPanel(), BorderLayout.SOUTH);
}
// Oberfläche aktualisieren
revalidate(); revalidate();
repaint(); repaint();
} }
private void saveStateForUndo() { private void refreshBoard() {
stateManager.saveState(board.getNumbers()); remove(1); // Entferne das aktuelle Spielfeld im CENTER
if (getLayout() instanceof BorderLayout) {
BorderLayout layout = (BorderLayout) getLayout();
// Komponente im CENTER entfernen
Component centerComponent = layout.getLayoutComponent(BorderLayout.CENTER);
if (centerComponent != null) {
remove(centerComponent);
}
// Neues Spielfeld hinzufügen
add(createGamePanel(), BorderLayout.CENTER);
// Kontroll-Buttons (SOUTH) entfernen und neu hinzufügen
Component southComponent = layout.getLayoutComponent(BorderLayout.SOUTH);
if (southComponent != null) {
remove(southComponent);
}
add(createControlPanel(), BorderLayout.SOUTH);
}
// Oberfläche aktualisieren
revalidate();
repaint();
} }
private JPanel createGamePanel() { private JPanel createGamePanel() {
@ -311,4 +297,14 @@ public class GameBoard extends JPanel {
return gamePanel; return gamePanel;
} }
private void updateBoard() {
for (int i = 0; i < board.getSize(); i++) {
for (int j = 0; j < board.getSize(); j++) {
HitoriCell cell = board.getCell(i, j);
JButton button = (JButton) gamePanel.getComponent(i * board.getSize() + j); // Hole den Button
updateButtonState(button, cell); // Aktualisiere den Button basierend auf dem Zustand
}
}
}
} }

View File

@ -1,6 +1,7 @@
package PR2.HitoriSpiel.Main; package PR2.HitoriSpiel.Main;
import PR2.HitoriSpiel.GUI.StartMenu; import PR2.HitoriSpiel.GUI.StartMenu;
import PR2.HitoriSpiel.Domain.StateManager;
import javax.swing.*; import javax.swing.*;
@ -12,15 +13,32 @@ import javax.swing.*;
public class Main { public class Main {
public static void main(String[] args) { public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Hitori - Hauptmenü");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
StartMenu startMenu = new StartMenu(frame); // Initialisiere den StateManager
frame.add(startMenu); StateManager stateManager = new StateManager();
frame.setVisible(true);
// Füge einen Shutdown-Hook hinzu, um Zustände bei Beendigung zu speichern
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
stateManager.saveStateToFile(); // Speichert die aktuellen Zustände in einer Datei
System.out.println("Spielzustände wurden gespeichert.");
}));
// Starte das Hauptmenü der Anwendung
SwingUtilities.invokeLater(() -> {
try {
JFrame frame = new JFrame("Hitori - Hauptmenü");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
// Lade das Startmenü
frame.add(new StartMenu(frame));
frame.setVisible(true);
frame.setLocationRelativeTo(null);
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, "Ein schwerer Fehler ist aufgetreten: " + e.getMessage(), "Fehler", JOptionPane.ERROR_MESSAGE);
}
}); });
} }
} }