Änderungen für Redo und Undo Button vorgenommen
parent
3d0f808daf
commit
eb30f5cd13
|
@ -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();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue