HitoriMitMaven/src/main/java/GUI/GameUIController.java

283 lines
8.8 KiB
Java

package GUI;
import domain.*;
import javafx.application.Platform;
import javafx.stage.Stage;
import java.util.*;
public class GameUIController {
private final Stage primaryStage; // Added to handle window state
private final HitoriGameMoves gameMoves;
private final GameSolver gameSolver;
private final HitoriGameTimer gameTimer;
private final HitoriGameScores gameScores;
private final HitoriDialogManager dialogManager;
private final HitoriBoardPanel boardPanel;
private final HitoriControlPanel controlPanel;
private final HitoriScorePanel scorePanel;
private Timer guiTimer;
private boolean isPaused;
public GameUIController(int[][] initialBoard, HitoriDialogManager dialogManager, Stage primaryStage, HitoriGameMain existingGame) {
this.primaryStage = primaryStage;
this.dialogManager = dialogManager;
if (existingGame != null) {
// Use existing game state
this.gameSolver = existingGame;
this.gameMoves = existingGame;
this.gameTimer = existingGame.getTimer();
this.gameScores = existingGame.getScores();
// Restore the elapsed time
this.gameTimer.setElapsedTime(existingGame.getElapsedTimeInSeconds());
} else {
// Create new game
this.gameSolver = new GameSolver(initialBoard);
this.gameMoves = gameSolver;
this.gameTimer = new HitoriGameTimer();
this.gameScores = new HitoriGameScores();
}
this.isPaused = false;
this.boardPanel = new HitoriBoardPanel(gameMoves, gameSolver, this);
this.controlPanel = new HitoriControlPanel(this);
this.scorePanel = new HitoriScorePanel(this);
startTimer();
loadHighScores();
updateUI(); // Make sure UI reflects current state
}
public void handleLeftClick(int row, int col) {
if (!isValidBlackMark(row, col)) {
gameMoves.mistakeCount++;
}
gameMoves.markCellAsBlack(row, col);
updateUI();
}
private boolean isValidBlackMark(int row, int col) {
boolean[][] blackCells = gameMoves.getBlackCells();
if (row > 0 && blackCells[row-1][col] ||
row < blackCells.length-1 && blackCells[row+1][col] ||
col > 0 && blackCells[row][col-1] ||
col < blackCells[0].length-1 && blackCells[row][col+1]) {
return false;
}
return true;
}
public void handleRightClick(int row, int col) {
gameMoves.markCellAsWhite(row, col);
updateUI();
}
public void togglePause() {
isPaused = !isPaused;
if (isPaused) {
gameTimer.pauseTimer();
controlPanel.setPauseButtonText("Resume");
boardPanel.setDisable(true);
} else {
gameTimer.startTimer();
controlPanel.setPauseButtonText("Pause");
boardPanel.setDisable(false);
}
updateTimerLabel();
}
public void resetGame() {
gameSolver.reset();
// Don't reset timer anymore
updateUI();
}
public void undo() {
if (gameSolver.undo()) {
updateUI();
}
}
public void redo() {
if (gameSolver.redo()) {
updateUI();
}
}
public void newGame() {
// Save current game state before starting new game
saveGame();
// Stop timer and cleanup current game
stopTimer();
// Start new game process
Platform.runLater(() -> {
// Close current window
primaryStage.close();
// Start fresh instance
Stage newStage = new Stage();
Main.MainMethod mainMethod = new Main.MainMethod();
try {
mainMethod.start(newStage);
} catch (Exception e) {
dialogManager.showAlert("Error", "Failed to start new game: " + e.getMessage());
}
});
}
public void checkSolution() {
if (gameSolver.isSolved()) {
handleWin();
} else {
dialogManager.showAlert("Not Solved", "The current solution is not correct. Keep trying!");
}
}
public void showErrors() {
List<int[]> errors = gameSolver.findIncorrectBlackMarks();
if (errors.isEmpty()) {
dialogManager.showAlert("No Errors", "No rule violations found in current black markings.");
return;
}
boardPanel.showErrors();
StringBuilder message = new StringBuilder("Found " + errors.size() + " error(s):\n");
for (int[] pos : errors) {
message.append(String.format("Row %d, Column %d\n", pos[0] + 1, pos[1] + 1));
}
dialogManager.showAlert("Errors Found", message.toString());
}
public void saveGame() {
HitoriGameMain saveState = new HitoriGameMain(gameMoves.getBoard());
// Copy current state to save
saveState.setGameState(gameMoves.getBlackCells(), gameMoves.getWhiteCells(),
gameMoves.getMistakeCount(), gameTimer.getElapsedTimeInSeconds());
saveState.saveGameState();
dialogManager.showAlert("Game Saved", "Your game has been saved successfully.");
}
public void deleteHighScores() {
if (dialogManager.confirmDeleteHighScores()) {
gameScores.deleteHighScores();
updateHighScoreDisplay();
dialogManager.showAlert("High Scores Deleted", "All high scores have been deleted successfully.");
}
}
private void handleWin() {
stopTimer();
Optional<String> playerName = dialogManager.askForPlayerName();
if (playerName.isPresent() && !playerName.get().trim().isEmpty()) {
gameScores.addHighScore(playerName.get(), gameTimer.getElapsedTimeInSeconds(), gameSolver.getMistakeCount());
updateHighScoreDisplay();
dialogManager.showAlert("Congratulations!", String.format(
"You've solved the puzzle!\nTime: %ds\nMistakes: %d",
gameTimer.getElapsedTimeInSeconds(),
gameSolver.getMistakeCount()
));
isPaused = false;
boardPanel.setDisable(false);
controlPanel.setPauseButtonText("Pause");
if (dialogManager.confirmNewGame()) {
newGame();
}
}
}
private void startTimer() {
if (guiTimer != null) {
guiTimer.cancel();
}
gameTimer.startTimer();
guiTimer = new Timer(true);
guiTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
Platform.runLater(() -> {
if (!isPaused) {
updateTimerLabel();
}
});
}
}, 0, 1000);
}
private void stopTimer() {
if (guiTimer != null) {
guiTimer.cancel();
guiTimer = null;
}
gameTimer.stopTimer();
}
private void updateUI() {
boardPanel.updateBoard();
updateMistakeLabel();
if (gameSolver.isSolved()) {
handleWin();
}
}
private void updateTimerLabel() {
controlPanel.updateTimerLabel(gameTimer.getElapsedTimeInSeconds());
}
private void updateMistakeLabel() {
controlPanel.updateMistakeLabel(gameSolver.getMistakeCount());
}
private void updateHighScoreDisplay() {
scorePanel.updateHighScores(String.join("\n", gameScores.getHighScoresWithAverage()));
}
private void loadHighScores() {
gameScores.loadHighScoresFromFile();
updateHighScoreDisplay();
}
public void transferHighScores(HitoriGameScores targetScores) {
for (String score : gameScores.getHighScoresWithAverage()) {
if (!score.startsWith("Average Time:")) {
String[] parts = score.split(" - ");
String playerName = parts[0];
long time = Long.parseLong(parts[1].substring(6, parts[1].length() - 1));
int mistakes = Integer.parseInt(parts[2].substring(10));
targetScores.addHighScore(playerName, time, mistakes);
}
}
}
public Set<String> convertErrorsToSet(List<int[]> errors) {
Set<String> errorPositions = new HashSet<>();
for (int[] pos : errors) {
errorPositions.add(pos[0] + "," + pos[1]);
}
return errorPositions;
}
public boolean isPaused() {
return isPaused;
}
public void cleanup() {
saveGame();
stopTimer();
}
public HitoriBoardPanel getBoardPanel() {
return boardPanel;
}
public HitoriControlPanel getControlPanel() {
return controlPanel;
}
public HitoriScorePanel getScorePanel() {
return scorePanel;
}
}