From 2ec7be27ca0cc3ef8c7c9646dc97b4f4349c8c21 Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Sat, 5 Apr 2025 10:53:41 +0200 Subject: [PATCH] feat: add undo --- .../chess/controller/CommandExecutor.java | 4 ++ .../java/chess/controller/PlayerCommand.java | 2 +- .../controller/commands/CastlingCommand.java | 2 +- .../commands/GrandCastlingCommand.java | 2 +- .../controller/commands/MoveCommand.java | 3 +- .../controller/commands/PromoteCommand.java | 4 +- .../controller/commands/UndoCommand.java | 8 +++- app/src/main/java/chess/model/Game.java | 19 ++++++++++ .../java/chess/view/simplerender/Window.java | 38 +++++++++++++++++-- 9 files changed, 71 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/chess/controller/CommandExecutor.java b/app/src/main/java/chess/controller/CommandExecutor.java index 3dc0949..84c53eb 100644 --- a/app/src/main/java/chess/controller/CommandExecutor.java +++ b/app/src/main/java/chess/controller/CommandExecutor.java @@ -24,6 +24,10 @@ public class CommandExecutor { assert result != CommandResult.Moved || command instanceof PlayerCommand; processResult(command, result); + + if (command instanceof PlayerCommand playerCommand) + this.game.addAction(playerCommand); + command.postExec(game, outputSystem); return result; } diff --git a/app/src/main/java/chess/controller/PlayerCommand.java b/app/src/main/java/chess/controller/PlayerCommand.java index cd86d35..9a0f76b 100644 --- a/app/src/main/java/chess/controller/PlayerCommand.java +++ b/app/src/main/java/chess/controller/PlayerCommand.java @@ -3,5 +3,5 @@ package chess.controller; import chess.model.Game; public abstract class PlayerCommand extends Command{ - public abstract void undo(Game game, OutputSystem outputSystem); + public abstract CommandResult undo(Game game, OutputSystem outputSystem); } diff --git a/app/src/main/java/chess/controller/commands/CastlingCommand.java b/app/src/main/java/chess/controller/commands/CastlingCommand.java index 9d2633a..b4fbba8 100644 --- a/app/src/main/java/chess/controller/commands/CastlingCommand.java +++ b/app/src/main/java/chess/controller/commands/CastlingCommand.java @@ -16,7 +16,7 @@ public class CastlingCommand extends PlayerCommand { } @Override - public void undo(Game game, OutputSystem outputSystem) { + public CommandResult undo(Game game, OutputSystem outputSystem) { // TODO Auto-generated method stub throw new UnsupportedOperationException("Unimplemented method 'undo'"); } diff --git a/app/src/main/java/chess/controller/commands/GrandCastlingCommand.java b/app/src/main/java/chess/controller/commands/GrandCastlingCommand.java index c3b28e4..11f9fb5 100644 --- a/app/src/main/java/chess/controller/commands/GrandCastlingCommand.java +++ b/app/src/main/java/chess/controller/commands/GrandCastlingCommand.java @@ -16,7 +16,7 @@ public class GrandCastlingCommand extends PlayerCommand { } @Override - public void undo(Game game, OutputSystem outputSystem) { + public CommandResult undo(Game game, OutputSystem outputSystem) { // TODO Auto-generated method stub throw new UnsupportedOperationException("Unimplemented method 'undo'"); } diff --git a/app/src/main/java/chess/controller/commands/MoveCommand.java b/app/src/main/java/chess/controller/commands/MoveCommand.java index 819765e..1540c5b 100644 --- a/app/src/main/java/chess/controller/commands/MoveCommand.java +++ b/app/src/main/java/chess/controller/commands/MoveCommand.java @@ -57,10 +57,11 @@ public class MoveCommand extends PlayerCommand { } @Override - public void undo(Game game, OutputSystem outputSystem) { + public CommandResult undo(Game game, OutputSystem outputSystem) { final ChessBoard board = game.getBoard(); board.undoMove(move, deadPiece); + return CommandResult.Moved; } @Override diff --git a/app/src/main/java/chess/controller/commands/PromoteCommand.java b/app/src/main/java/chess/controller/commands/PromoteCommand.java index f091cb4..318d408 100644 --- a/app/src/main/java/chess/controller/commands/PromoteCommand.java +++ b/app/src/main/java/chess/controller/commands/PromoteCommand.java @@ -75,7 +75,7 @@ public class PromoteCommand extends PlayerCommand { } @Override - public void undo(Game game, OutputSystem outputSystem) { + public CommandResult undo(Game game, OutputSystem outputSystem) { final ChessBoard board = game.getBoard(); Piece promoted = board.pieceAt(this.pieceCoords); @@ -84,6 +84,8 @@ public class PromoteCommand extends PlayerCommand { Color player = promoted.getColor(); board.pieceComes(new Pawn(player), this.pieceCoords); + + return CommandResult.ActionNeeded; } } diff --git a/app/src/main/java/chess/controller/commands/UndoCommand.java b/app/src/main/java/chess/controller/commands/UndoCommand.java index de847a1..6ec2566 100644 --- a/app/src/main/java/chess/controller/commands/UndoCommand.java +++ b/app/src/main/java/chess/controller/commands/UndoCommand.java @@ -2,14 +2,18 @@ package chess.controller.commands; import chess.controller.Command; import chess.controller.OutputSystem; +import chess.controller.PlayerCommand; import chess.model.Game; public class UndoCommand extends Command{ @Override public CommandResult execute(Game game, OutputSystem outputSystem) { - //TODO - return CommandResult.Moved; + PlayerCommand lastAction = game.getLastAction(); + if (lastAction == null) + return CommandResult.NotAllowed; + + return lastAction.undo(game, outputSystem); } } diff --git a/app/src/main/java/chess/model/Game.java b/app/src/main/java/chess/model/Game.java index 767a022..83c1b22 100644 --- a/app/src/main/java/chess/model/Game.java +++ b/app/src/main/java/chess/model/Game.java @@ -1,10 +1,15 @@ package chess.model; +import java.util.EmptyStackException; +import java.util.Stack; + +import chess.controller.PlayerCommand; import chess.model.visitor.PawnIdentifier; public class Game { private final ChessBoard board; private Color playerTurn; + private final Stack movesHistory; public enum GameStatus { Check, CheckMate, OnGoing, Pat; @@ -12,6 +17,7 @@ public class Game { public Game(ChessBoard board) { this.board = board; + this.movesHistory = new Stack<>(); } public ChessBoard getBoard() { @@ -80,4 +86,17 @@ public class Game { return null; } + public void addAction(PlayerCommand command) { + this.movesHistory.add(command); + } + + public PlayerCommand getLastAction() { + try { + PlayerCommand last = this.movesHistory.pop(); + return last; + } catch (EmptyStackException e) { + return null; + } + } + } diff --git a/app/src/main/java/chess/view/simplerender/Window.java b/app/src/main/java/chess/view/simplerender/Window.java index e0b78d6..5284a3f 100644 --- a/app/src/main/java/chess/view/simplerender/Window.java +++ b/app/src/main/java/chess/view/simplerender/Window.java @@ -6,6 +6,7 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.List; +import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; @@ -13,31 +14,38 @@ import javax.swing.JPanel; import javax.swing.SwingUtilities; import chess.controller.Command; +import chess.controller.Command.CommandResult; import chess.controller.CommandExecutor; import chess.controller.OutputSystem; -import chess.controller.Command.CommandResult; +import chess.controller.commands.CastlingCommand; import chess.controller.commands.GetAllowedMovesCommand; import chess.controller.commands.GetPieceAtCommand; +import chess.controller.commands.GrandCastlingCommand; import chess.controller.commands.MoveCommand; import chess.controller.commands.PromoteCommand; import chess.controller.commands.PromoteCommand.PromoteType; +import chess.controller.commands.UndoCommand; import chess.model.Coordinate; import chess.model.Move; import chess.model.Piece; public class Window extends JFrame implements OutputSystem { - private final JLabel cells[][]; - private final JLabel displayText; private final CommandExecutor commandExecutor; private Coordinate lastClick = null; + private final JLabel cells[][]; + private final JLabel displayText; + private final JButton castlingButton = new JButton("Roque"); + private final JButton bigCastlingButton = new JButton("Grand Roque"); + private final JButton undoButton = new JButton("Annuler le coup précédent"); + public Window(CommandExecutor commandExecutor) { this.cells = new JLabel[8][8]; this.displayText = new JLabel(); this.commandExecutor = commandExecutor; - setSize(800, 870); + setSize(800, 910); setVisible(true); setLocationRelativeTo(null); setDefaultCloseOperation(DISPOSE_ON_CLOSE); @@ -51,12 +59,34 @@ public class Window extends JFrame implements OutputSystem { return ((x + y) % 2 == 1) ? Color.BLACK : Color.WHITE; } + private void buildButtons(JPanel bottom) { + castlingButton.addActionListener((event) -> { + sendCommand(new CastlingCommand()); + }); + + bigCastlingButton.addActionListener((event) -> { + sendCommand(new GrandCastlingCommand()); + }); + + undoButton.addActionListener((event) -> { + sendCommand(new UndoCommand()); + }); + + bottom.add(castlingButton); + bottom.add(bigCastlingButton); + bottom.add(undoButton); + } + private void buildBoard() { JPanel content = new JPanel(); JPanel grid = new JPanel(new GridLayout(8, 8)); + JPanel bottom = new JPanel(); + + buildButtons(bottom); content.add(this.displayText); content.add(grid); + content.add(bottom); setContentPane(content);