Ä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;
import java.io.*;
import java.util.Stack;
public class StateManager {
public class StateManager implements Serializable {
private final Stack<int[][]> undoStack = new Stack<>();
private final Stack<int[][]> redoStack = new Stack<>();
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
}
// Macht die letzte Änderung rückgängig
public int[][] undo(int[][] currentState) {
if (!undoStack.isEmpty()) {
redoStack.push(copyArray(currentState)); // Aktuellen Zustand im Redo-Stack speichern
return undoStack.pop();
redoStack.push(copyState(currentState)); // Speichere aktuellen Zustand für Redo
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) {
if (!redoStack.isEmpty()) {
undoStack.push(copyArray(currentState)); // Aktuellen Zustand im Undo-Stack speichern
return redoStack.pop();
undoStack.push(copyState(currentState)); // Speichere aktuellen Zustand für Undo
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) {
int[][] copy = new int[original.length][];
for (int i = 0; i < original.length; i++) {
copy[i] = original[i].clone();
// Hilfsmethode, um eine Kopie des Zustands zu erstellen
private int[][] copyState(int[][] state) {
int[][] copy = new int[state.length][state[0].length];
for (int i = 0; i < state.length; i++) {
System.arraycopy(state[i], 0, copy[i], 0, state[i].length);
}
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 long startTime;
private JLabel timerLabel;
private JPanel gamePanel; // Das Spielfeld als JPanel
private final StateManager stateManager = new StateManager();
@ -34,14 +35,7 @@ public class GameBoard extends JPanel {
startTimer();
// Spielfeld erstellen
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);
}
}
gamePanel = createGamePanel();
add(gamePanel, BorderLayout.CENTER);
// Kontroll-Buttons unten hinzufügen
@ -71,7 +65,7 @@ public class GameBoard extends JPanel {
resetButton.addActionListener(e -> {
saveStateForUndo();
resetBoard();
refreshBoard();
//refreshBoard();
});
JButton undoButton = Setup.createGameBoardButton("Undo", 80, 30);
@ -79,7 +73,7 @@ public class GameBoard extends JPanel {
int[][] previousState = stateManager.undo(board.getNumbers());
if (previousState != null) {
board.setNumbers(previousState);
refreshBoard();
updateBoard();
} else {
JOptionPane.showMessageDialog(this, "Kein Zustand zum Zurücksetzen vorhanden.", "Undo", JOptionPane.INFORMATION_MESSAGE);
}
@ -112,7 +106,6 @@ public class GameBoard extends JPanel {
showPauseMenu();
});
controlPanel.add(resetButton);
controlPanel.add(undoButton);
controlPanel.add(redoButton);
@ -122,35 +115,6 @@ public class GameBoard extends JPanel {
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() {
HitoriValidator validator = new HitoriValidator(board);
@ -178,12 +142,10 @@ public class GameBoard extends JPanel {
}
private void toggleCellState(HitoriCell cell) {
if (cell == null) {
System.err.println("Ungültige Zelle! Der Zustand kann nicht geändert werden.");
return;
}
if (cell.getState() == HitoriCell.CellState.GRAY) {
cell.setState(HitoriCell.CellState.BLACK);
} else if (cell.getState() == HitoriCell.CellState.BLACK) {
@ -211,22 +173,8 @@ public class GameBoard extends JPanel {
}
}
private void saveGame() {
try {
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 saveStateForUndo() {
stateManager.saveState(board.getNumbers());
}
private void addHighscore() {
@ -280,22 +228,60 @@ public class GameBoard extends JPanel {
}
}
private JButton createButton(String text, int width, int height) {
JButton button = new JButton(text);
button.setPreferredSize(new Dimension(width, height));
return button;
}
public void resetBoard() {
// Spiellogik zurücksetzen
board.resetBoard();
// Spielfeld (CENTER) entfernen und neu erstellen
if (getLayout() instanceof BorderLayout) {
BorderLayout layout = (BorderLayout) getLayout();
private void refreshBoard() {
remove(1); // Entferne das aktuelle Spielfeld im CENTER
add(createGamePanel(), BorderLayout.CENTER); // Füge das neue Spielfeld hinzu
// 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 void saveStateForUndo() {
stateManager.saveState(board.getNumbers());
private void refreshBoard() {
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() {
@ -311,4 +297,14 @@ public class GameBoard extends JPanel {
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;
import PR2.HitoriSpiel.GUI.StartMenu;
import PR2.HitoriSpiel.Domain.StateManager;
import javax.swing.*;
@ -12,15 +13,32 @@ import javax.swing.*;
public class Main {
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);
frame.add(startMenu);
frame.setVisible(true);
// Initialisiere den StateManager
StateManager stateManager = new StateManager();
// 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);
}
});
}
}