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