diff --git a/bin/coursework/GameState.class b/bin/coursework/GameState.class new file mode 100644 index 0000000000000000000000000000000000000000..05a8e904dce51e954e51bf717fb058b235294275 Binary files /dev/null and b/bin/coursework/GameState.class differ diff --git a/bin/coursework/Main.class b/bin/coursework/Main.class index ed2ce99b3a07ae04a7b79c6a058d9939fb40ebf8..d732c086f0f50b0b91218527463bd8a5593b2706 100644 Binary files a/bin/coursework/Main.class and b/bin/coursework/Main.class differ diff --git a/src/coursework/GameState.java b/src/coursework/GameState.java new file mode 100644 index 0000000000000000000000000000000000000000..092aa5eaf00f4146a8594d214cb45320248222ff --- /dev/null +++ b/src/coursework/GameState.java @@ -0,0 +1,25 @@ +package coursework; + +import javafx.scene.control.TextField; + +public class GameState { + + private String[] gridValues; + + public GameState(String[] gridValues) { + this.gridValues = gridValues; + } + + public String[] getGameState() { + return gridValues; + } + + public static String[] getCurrentGameState(TextField[] gridNumbers) { + String[] gridValues = new String[Main.N*Main.N]; + for (int k = 0; k < gridValues.length; k++) { + gridValues[k] = gridNumbers[k].getText(); + } + return gridValues; + } + +} diff --git a/src/coursework/Main.java b/src/coursework/Main.java index 7a28ea1bbee7c520bac574a44e2c8c8375d43b8d..417ce75c94aaefee20e8f1ccc113827571e366e3 100644 --- a/src/coursework/Main.java +++ b/src/coursework/Main.java @@ -5,6 +5,9 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; +import java.util.List; +import java.util.Stack; +import java.util.Vector; import javafx.application.*; import javafx.event.EventHandler; @@ -13,7 +16,10 @@ import javafx.geometry.Pos; import javafx.scene.Group; import javafx.scene.Node; import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.image.Image; @@ -49,6 +55,13 @@ public class Main extends Application { private boolean isWider; private HBox previousHBox = null; private Square previousSquare = null; + private boolean clearing = false; + + private Stack<GameState> undoStack = new Stack<GameState>(); + private Stack<GameState> redoStack = new Stack<GameState>(); + + private Button undoButton; + private Button redoButton; private GridPane setupGrid() { GridPane gridPane = new GridPane(); @@ -75,6 +88,15 @@ public class Main extends Application { gridPane.add(group, j, i); gridPane.add(hbox, j, i); + textField.textProperty().addListener((observable, oldValue, newValue) -> { + if (!clearing) { + undoStack.push(new GameState(GameState.getCurrentGameState(gridNumbers))); + if (undoButton.isDisabled()) { + undoButton.setDisable(false); + } + } + }); + square.getRectangle().toFront(); return gridPane; } @@ -170,14 +192,54 @@ public class Main extends Application { new Cage(ids, value, operator); } + + private void updateGameState(GameState gameState) { + String[] gameValues = gameState.getGameState(); + for (int i = 0; i < gridNumbers.length; i++) { +// if (!gridNumbers[i].getText().equals("") && gameValues.equals("")) +// System.out.println("Current: " + gridNumbers[i].getText() + ", Previous: " + textFields[i].getText()); + gridNumbers[i].setText(gameValues[i]); + } + } + private HBox setupBottomHBox() { HBox bottomHBox = new HBox(); bottomHBox.setSpacing(10); bottomHBox.setAlignment(Pos.TOP_CENTER); - Button undoButton = new Button("", new ImageView(new Image("file:Images/undo_icon.png"))); - Button redoButton = new Button("", new ImageView(new Image("file:Images/redo_icon.png"))); + undoButton = new Button("", new ImageView(new Image("file:Images/undo_icon.png"))); + redoButton = new Button("", new ImageView(new Image("file:Images/redo_icon.png"))); Button clearButton = new Button("Clear"); + undoButton.setOnAction(e -> { + // undoStack.pop() is the current GameState + + redoStack.push(undoStack.pop()); + updateGameState(undoStack.peek()); + + // + if (!redoStack.empty()) { + redoButton.setDisable(false); + } + if (undoStack.size() == 1) { + undoButton.setDisable(true); + } + }); + redoButton.setOnAction(e -> { + GameState gameState = redoStack.pop(); + updateGameState(gameState); + + undoStack.push(gameState); + + if (!undoStack.empty()) { + undoButton.setDisable(false); + } + if (redoStack.empty()) { + redoButton.setDisable(true); + } + }); + + undoButton.setDisable(true); + redoButton.setDisable(true); clearButton.setPrefHeight(36); clearButton.setPrefWidth(120); clearButtonClickEvent(clearButton); @@ -194,14 +256,26 @@ public class Main extends Application { hbox.setStyle("-fx-border-color:red; -fx-border-width:2px;"); previousHBox = hbox; previousSquare = square; + for (TextField textField : gridNumbers) { + textField.deselect(); + } }); } - private void clearButtonClickEvent(Button clearButton) { + private void clearButtonClickEvent(Button clearButton) { clearButton.setOnAction(e -> { - for (TextField textField : gridNumbers) { - textField.setText(""); - } + clearing = true; + undoStack.push(new GameState(GameState.getCurrentGameState(gridNumbers))); + Alert alert = new Alert(AlertType.CONFIRMATION); + alert.setContentText("Are you sure you wish to clear the board?"); + alert.showAndWait().ifPresent(type -> { + if (type == ButtonType.OK) { + for (TextField textField : gridNumbers) { + textField.setText(""); + } + } + });; + clearing = false; }); } @@ -284,6 +358,7 @@ public class Main extends Application { vBox.setAlignment(Pos.CENTER); GridPane gridPane = setupGrid(); + undoStack.push(new GameState(GameState.getCurrentGameState(gridNumbers))); HBox topHBox = setupTopHBox(); HBox centerHBox = setupCenterHBox();