From f86a99acb6710f0a0e7cdf1a745aec60b1c930b2 Mon Sep 17 00:00:00 2001 From: Ticho Hidding Date: Sat, 20 Sep 2025 21:30:37 +0200 Subject: [PATCH] Bugfix: can no longer overwrite move with the UI. Added colours to signal end state. --- .../org/toop/frontend/UI/UIGameBoard.java | 44 +++++++++++++++---- .../toop/frontend/games/LocalTicTacToe.java | 19 ++++++-- .../game/tictactoe/ai/MinMaxTicTacToe.java | 2 +- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/toop/frontend/UI/UIGameBoard.java b/src/main/java/org/toop/frontend/UI/UIGameBoard.java index a3212a2..3d49b65 100644 --- a/src/main/java/org/toop/frontend/UI/UIGameBoard.java +++ b/src/main/java/org/toop/frontend/UI/UIGameBoard.java @@ -3,11 +3,17 @@ package org.toop.frontend.UI; import java.awt.*; import java.awt.event.ActionEvent; import javax.swing.*; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.toop.frontend.games.LocalTicTacToe; +import org.toop.game.tictactoe.GameBase; public class UIGameBoard { private static final int TICTACTOE_SIZE = 3; + private static final Logger logger = LogManager.getLogger(LocalGameSelector.class); + private JPanel tttPanel; // Root panel for this game private JButton backToMainMenuButton; private JButton[] cells; @@ -57,16 +63,21 @@ public class UIGameBoard { final int index = i; cells[i].addActionListener( (ActionEvent _) -> { - int cp = this.localTicTacToe.getCurrentPlayersTurn(); - if (cp == 0) { - this.currentPlayer = "X"; - currentPlayerIndex = 0; - } else if (cp == 1) { - this.currentPlayer = "O"; - currentPlayerIndex = 1; + if (cells[index].getText().equals(" ")) { + int cp = this.localTicTacToe.getCurrentPlayersTurn(); + if (cp == 0) { + this.currentPlayer = "X"; + currentPlayerIndex = 0; + } else if (cp == 1) { + this.currentPlayer = "O"; + currentPlayerIndex = 1; + } + this.localTicTacToe.move(index); + cells[index].setText(currentPlayer); + } + else{ + logger.info("Player " + currentPlayerIndex + " attempted invalid move at: " + cells[index].getText()); } - this.localTicTacToe.move(index); - cells[index].setText(currentPlayer); }); } @@ -77,6 +88,21 @@ public class UIGameBoard { System.out.println(cells[index].getText()); cells[index].setText(move); } + public void setState(GameBase.State state, String playerMove) { + Color color; + if (state == GameBase.State.WIN && playerMove.equals(currentPlayer)) { + color = new Color(160,220,160); + } + else if (state == GameBase.State.WIN) { + color = new Color(220,160,160); + } + else{ + color = new Color(220,220,160); + } + for (JButton cell : cells) { + cell.setBackground(color); + } + } public JPanel getTTTPanel() { return tttPanel; diff --git a/src/main/java/org/toop/frontend/games/LocalTicTacToe.java b/src/main/java/org/toop/frontend/games/LocalTicTacToe.java index 88069d8..3e442c8 100644 --- a/src/main/java/org/toop/frontend/games/LocalTicTacToe.java +++ b/src/main/java/org/toop/frontend/games/LocalTicTacToe.java @@ -142,23 +142,34 @@ public class LocalTicTacToe { // TODO: Implement runnable this.ticTacToe = new TicTacToe("X", "O"); while (running) { try { + GameBase.State state; if (!isAiPlayer[0]) { - this.ticTacToe.play(this.moveQueuePlayerA.take()); + state = this.ticTacToe.play(this.moveQueuePlayerA.take()); } else { int bestMove = aiPlayers[0].findBestMove(this.ticTacToe); - if (this.ticTacToe.play(bestMove) != GameBase.State.INVALID) { + state = this.ticTacToe.play(bestMove); + if (state != GameBase.State.INVALID) { ui.setCell(bestMove, "X"); } } + if (state == GameBase.State.WIN || state == GameBase.State.DRAW) { + ui.setState(state, "X"); + running = false; + } this.setNextPlayersTurn(); if (!isAiPlayer[1]) { - this.ticTacToe.play(this.moveQueuePlayerB.take()); + state = this.ticTacToe.play(this.moveQueuePlayerB.take()); } else { int bestMove = aiPlayers[1].findBestMove(this.ticTacToe); - if (this.ticTacToe.play(bestMove) != GameBase.State.INVALID) { + state = this.ticTacToe.play(bestMove); + if (state != GameBase.State.INVALID) { ui.setCell(bestMove, "O"); } } + if (state == GameBase.State.WIN || state == GameBase.State.DRAW) { + ui.setState(state, "O"); + running = false; + } this.setNextPlayersTurn(); } catch (InterruptedException e) { throw new RuntimeException(e); diff --git a/src/main/java/org/toop/game/tictactoe/ai/MinMaxTicTacToe.java b/src/main/java/org/toop/game/tictactoe/ai/MinMaxTicTacToe.java index a1b3b8c..cf807ed 100644 --- a/src/main/java/org/toop/game/tictactoe/ai/MinMaxTicTacToe.java +++ b/src/main/java/org/toop/game/tictactoe/ai/MinMaxTicTacToe.java @@ -28,7 +28,7 @@ public class MinMaxTicTacToe { } if (empty && game.validateMove(4)) { - return 4; + return 0; } // simulate all possible moves on the field