From 97cafb903aec98f86394f25bb67ce64e9a49ba24 Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Wed, 2 Apr 2025 10:54:14 +0200 Subject: [PATCH] juste better --- app/src/main/java/chess/App.java | 16 ++- .../main/java/chess/io/CommandExecutor.java | 24 ++-- app/src/main/java/chess/io/OutputSystem.java | 18 ++- .../java/chess/io/OutputSystemInterface.java | 18 --- .../io/commands/GetAllowedMovesCommand.java | 42 ++++++ .../chess/io/commands/GetPieceAtCommand.java | 34 +++++ .../chess/io/commands/NewGameCommand.java | 2 + app/src/main/java/chess/model/ChessBoard.java | 31 ++--- app/src/main/java/chess/model/Game.java | 12 -- .../java/chess/simplerender/PieceIcon.java | 15 ++- .../main/java/chess/simplerender/Window.java | 127 +++++++++--------- app/src/test/java/chess/AppTest.java | 4 +- 12 files changed, 212 insertions(+), 131 deletions(-) delete mode 100644 app/src/main/java/chess/io/OutputSystemInterface.java create mode 100644 app/src/main/java/chess/io/commands/GetAllowedMovesCommand.java create mode 100644 app/src/main/java/chess/io/commands/GetPieceAtCommand.java diff --git a/app/src/main/java/chess/App.java b/app/src/main/java/chess/App.java index 5010ca6..bc87e18 100644 --- a/app/src/main/java/chess/App.java +++ b/app/src/main/java/chess/App.java @@ -3,16 +3,22 @@ */ package chess; +import chess.io.CommandExecutor; +import chess.io.commands.NewGameCommand; import chess.model.ChessBoard; import chess.model.Game; import chess.simplerender.Window; public class App { - public String getGreeting() { - return "Hello World!"; - } - public static void main(String[] args) { - new Window(new Game(new ChessBoard())); + CommandExecutor commandExecutor = new CommandExecutor(); + + Game game = new Game(new ChessBoard()); + Window window = new Window(commandExecutor); + + commandExecutor.setGame(game); + commandExecutor.setOutputSystem(window); + + commandExecutor.executeCommand(new NewGameCommand()); } } diff --git a/app/src/main/java/chess/io/CommandExecutor.java b/app/src/main/java/chess/io/CommandExecutor.java index 0732a1e..99ff429 100644 --- a/app/src/main/java/chess/io/CommandExecutor.java +++ b/app/src/main/java/chess/io/CommandExecutor.java @@ -4,12 +4,12 @@ import chess.model.Game; public class CommandExecutor { - private final Game game; - private final OutputSystem outputSystem; + private Game game; + private OutputSystem outputSystem; - public CommandExecutor(Game game, OutputSystem outputSystem) { - this.game = game; - this.outputSystem = outputSystem; + public CommandExecutor() { + this.game = null; + this.outputSystem = null; } public CommandResult executeCommand(Command command) { @@ -22,16 +22,14 @@ public class CommandExecutor { private void alternatePlayers() { this.game.switchPlayerTurn(); this.outputSystem.playerTurn(this.game.getPlayerTurn()); + } + + public void setOutputSystem(OutputSystem outputSystem) { + this.outputSystem = outputSystem; } - public Game getGame() { - return game; + public void setGame(Game game) { + this.game = game; } - public OutputSystem getOutputSystem() { - return outputSystem; - } - - - } diff --git a/app/src/main/java/chess/io/OutputSystem.java b/app/src/main/java/chess/io/OutputSystem.java index 7138368..2f16fea 100644 --- a/app/src/main/java/chess/io/OutputSystem.java +++ b/app/src/main/java/chess/io/OutputSystem.java @@ -1,8 +1,20 @@ package chess.io; -public abstract class OutputSystem implements OutputSystemInterface { +import chess.model.Color; - public OutputSystem() { - } +public interface OutputSystem { + void playerTurn(Color color); + + void winnerIs(Color color); + + void kingIsInCheck(); + + void kingIsInMat(); + + void patSituation(); + + void hasSurrendered(Color color); + + void gameStarted(); } diff --git a/app/src/main/java/chess/io/OutputSystemInterface.java b/app/src/main/java/chess/io/OutputSystemInterface.java deleted file mode 100644 index 2d2c023..0000000 --- a/app/src/main/java/chess/io/OutputSystemInterface.java +++ /dev/null @@ -1,18 +0,0 @@ -package chess.io; - -import chess.model.Color; - -public interface OutputSystemInterface { - - void playerTurn(Color color); - - void winnerIs(Color color); - - void kingIsInCheck(); - - void kingIsInMat(); - - void patSituation(); - - void hasSurrendered(Color color); -} diff --git a/app/src/main/java/chess/io/commands/GetAllowedMovesCommand.java b/app/src/main/java/chess/io/commands/GetAllowedMovesCommand.java new file mode 100644 index 0000000..ec74723 --- /dev/null +++ b/app/src/main/java/chess/io/commands/GetAllowedMovesCommand.java @@ -0,0 +1,42 @@ +package chess.io.commands; + +import java.util.ArrayList; +import java.util.List; + +import chess.io.Command; +import chess.io.CommandResult; +import chess.io.OutputSystem; +import chess.model.ChessBoard; +import chess.model.Coordinate; +import chess.model.Game; +import chess.model.Piece; + +public class GetAllowedMovesCommand extends Command { + + private final Coordinate start; + private List destinations; + + public GetAllowedMovesCommand(Coordinate start) { + this.start = start; + this.destinations = new ArrayList<>(); + } + + @Override + public CommandResult execute(Game game, OutputSystem outputSystem) { + final ChessBoard board = game.getBoard(); + Piece piece = board.pieceAt(start); + + if (piece == null) + return CommandResult.NotAllowed; + + if (piece.getColor() != game.getPlayerTurn()) + return CommandResult.NotAllowed; + + this.destinations = board.getAllowedMoves(start); + return CommandResult.NotMoved; + } + + public List getDestinations() { + return destinations; + } +} diff --git a/app/src/main/java/chess/io/commands/GetPieceAtCommand.java b/app/src/main/java/chess/io/commands/GetPieceAtCommand.java new file mode 100644 index 0000000..d248261 --- /dev/null +++ b/app/src/main/java/chess/io/commands/GetPieceAtCommand.java @@ -0,0 +1,34 @@ +package chess.io.commands; + +import chess.io.Command; +import chess.io.CommandResult; +import chess.io.OutputSystem; +import chess.model.Coordinate; +import chess.model.Game; +import chess.model.Piece; + +public class GetPieceAtCommand extends Command{ + + private final Coordinate pieceCoords; + private Piece piece; + + public GetPieceAtCommand(Coordinate pieceCoords) { + this.pieceCoords = pieceCoords; + this.piece = null; + } + + @Override + public CommandResult execute(Game game, OutputSystem outputSystem) { + if (!pieceCoords.isValid()) + return CommandResult.NotAllowed; + + this.piece = game.getBoard().pieceAt(pieceCoords); + + return CommandResult.NotMoved; + } + + public Piece getPiece() { + return piece; + } + +} diff --git a/app/src/main/java/chess/io/commands/NewGameCommand.java b/app/src/main/java/chess/io/commands/NewGameCommand.java index 74ebe9b..3bb09c4 100644 --- a/app/src/main/java/chess/io/commands/NewGameCommand.java +++ b/app/src/main/java/chess/io/commands/NewGameCommand.java @@ -49,6 +49,8 @@ public class NewGameCommand extends Command { game.resetPlayerTurn(); + outputSystem.gameStarted(); + return CommandResult.NotMoved; } } diff --git a/app/src/main/java/chess/model/ChessBoard.java b/app/src/main/java/chess/model/ChessBoard.java index aed435c..4355f93 100644 --- a/app/src/main/java/chess/model/ChessBoard.java +++ b/app/src/main/java/chess/model/ChessBoard.java @@ -1,5 +1,7 @@ package chess.model; +import java.util.ArrayList; +import java.util.List; import java.util.Stack; import chess.model.visitor.KingIdentifier; @@ -148,44 +150,39 @@ public class ChessBoard { if (attackPiece.getColor() != player) continue; - if (getAllowedMoves(attackCoords) != null) + if (!getAllowedMoves(attackCoords).isEmpty()) return true; } } return false; } - public boolean[][] getAllowedMoves(Coordinate pieceCoords) { + public List getAllowedMoves(Coordinate pieceCoords) { Piece piece = pieceAt(pieceCoords); if (piece == null) return null; - Color player = piece.getColor(); + Color player = piece.getColor(); + + List result = new ArrayList<>(); - boolean[][] result = new boolean[Coordinate.VALUE_MAX][Coordinate.VALUE_MAX]; for (int i = 0; i < Coordinate.VALUE_MAX; i++) { for (int j = 0; j < Coordinate.VALUE_MAX; j++) { - Move move = new Move(pieceCoords, new Coordinate(i, j)); + Coordinate destination = new Coordinate(i, j); + Move move = new Move(pieceCoords, destination); + PiecePathChecker piecePathChecker = new PiecePathChecker(this, move); if (!piecePathChecker.isValid()) continue; - + applyMove(move); - result[i][j] = !isKingInCheck(player); + if (!isKingInCheck(player)) + result.add(destination); undoLastMove(); } } - - // return null is no valid moves are possible - for (int x = 0; x < 8; x++) { - for (int y = 0; y < 8; y++) { - if (result[x][y]) - return result; - } - } - - return null; + return result; } } diff --git a/app/src/main/java/chess/model/Game.java b/app/src/main/java/chess/model/Game.java index 18fafea..65e7582 100644 --- a/app/src/main/java/chess/model/Game.java +++ b/app/src/main/java/chess/model/Game.java @@ -24,16 +24,4 @@ public class Game { playerTurn = Color.getEnemy(playerTurn); } - public boolean[][] getAllowedMoves(Coordinate coordinate) { - Piece piece = this.board.pieceAt(coordinate); - - if (piece == null) - return null; - - if (piece.getColor() != getPlayerTurn()) - return null; - - return this.board.getAllowedMoves(coordinate); - } - } diff --git a/app/src/main/java/chess/simplerender/PieceIcon.java b/app/src/main/java/chess/simplerender/PieceIcon.java index f47f509..5d201e7 100644 --- a/app/src/main/java/chess/simplerender/PieceIcon.java +++ b/app/src/main/java/chess/simplerender/PieceIcon.java @@ -1,6 +1,8 @@ package chess.simplerender; import java.awt.Image; +import java.util.HashMap; +import java.util.Map; import javax.swing.Icon; import javax.swing.ImageIcon; @@ -18,11 +20,22 @@ import chess.model.pieces.Rook; public class PieceIcon implements PieceVisitor { private static final String basePath = "app/src/main/resources/pieces2D/"; + private static final Map cache = new HashMap<>(); public Icon getIcon(Piece piece) { if (piece == null) return null; - return new ImageIcon(new ImageIcon(basePath + colorToString(piece.getColor()) + "-" + visit(piece) + ".png").getImage().getScaledInstance(100,100, Image.SCALE_SMOOTH)); + String path = basePath + colorToString(piece.getColor()) + "-" + visit(piece) + ".png"; + return getIcon(path); + } + + private Icon getIcon(String path) { + Icon image = cache.get(path); + if (image != null) + return image; + image = new ImageIcon(new ImageIcon(path).getImage().getScaledInstance(100,100, Image.SCALE_SMOOTH)); + cache.put(path, image); + return image; } private String colorToString(Color color) { diff --git a/app/src/main/java/chess/simplerender/Window.java b/app/src/main/java/chess/simplerender/Window.java index 895453b..c332958 100644 --- a/app/src/main/java/chess/simplerender/Window.java +++ b/app/src/main/java/chess/simplerender/Window.java @@ -4,6 +4,7 @@ import java.awt.Color; import java.awt.GridLayout; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.List; import javax.swing.JFrame; import javax.swing.JLabel; @@ -13,68 +14,26 @@ import chess.io.Command; import chess.io.CommandExecutor; import chess.io.CommandResult; import chess.io.OutputSystem; +import chess.io.commands.GetAllowedMovesCommand; +import chess.io.commands.GetPieceAtCommand; import chess.io.commands.MoveCommand; -import chess.io.commands.NewGameCommand; -import chess.model.ChessBoard; import chess.model.Coordinate; -import chess.model.Game; import chess.model.Move; +import chess.model.Piece; -public class Window extends JFrame { +public class Window extends JFrame implements OutputSystem { private final JLabel cells[][]; private final CommandExecutor commandExecutor; - private final ChessBoard board; private Coordinate lastClick = null; - public Window(Game game) { + public Window(CommandExecutor commandExecutor) { this.cells = new JLabel[8][8]; - this.commandExecutor = new CommandExecutor(game, initSlots()); - this.board = this.commandExecutor.getGame().getBoard(); - build(); + this.commandExecutor = commandExecutor; setSize(800, 800); setVisible(true); setDefaultCloseOperation(EXIT_ON_CLOSE); - sendCommand(new NewGameCommand()); - updateBoard(); - } - - private OutputSystem initSlots() { - OutputSystem outputSystem = new OutputSystem() { - - @Override - public void playerTurn(chess.model.Color color) { - System.out.println("Player turn " + color); - } - - @Override - public void winnerIs(chess.model.Color color) { - System.out.println("Winner is " + color); - } - - @Override - public void kingIsInCheck() { - System.out.println("Check"); - } - - @Override - public void kingIsInMat() { - System.out.println("CheckMate"); - } - - @Override - public void patSituation() { - System.out.println("Pat"); - } - - @Override - public void hasSurrendered(chess.model.Color color) { - System.out.println("Surrendered"); - } - - }; - return outputSystem; } private CommandResult sendCommand(Command command) { @@ -89,7 +48,7 @@ public class Window extends JFrame { return ((x + y) % 2 == 1) ? Color.BLACK : Color.WHITE; } - private void build() { + private void buildBoard() { JPanel content = new JPanel(new GridLayout(8, 8)); setContentPane(content); for (int y = 0; y < 8; y++) { @@ -104,9 +63,10 @@ public class Window extends JFrame { label.addMouseListener(new MouseAdapter() { @Override - public void mouseClicked(MouseEvent e) { + public void mousePressed(MouseEvent e) { onCellClicked(xx, yy); } + }); content.add(label); } @@ -114,26 +74,38 @@ public class Window extends JFrame { updateBoard(); } + private boolean isCellEmpty(int x, int y) { + return pieceAt(x, y) == null; + } + + private Piece pieceAt(int x, int y) { + GetPieceAtCommand command = new GetPieceAtCommand(new Coordinate(x, y)); + sendCommand(command); + return command.getPiece(); + } + private void updateBoard() { PieceIcon pieceIcon = new PieceIcon(); for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { JLabel cell = this.cells[x][y]; - cell.setIcon(pieceIcon.getIcon(this.board.pieceAt(new Coordinate(x, y)))); + cell.setIcon(pieceIcon.getIcon(pieceAt(x, y))); } } } private boolean previewMoves(int x, int y) { - boolean[][] allowedMoves = this.commandExecutor.getGame().getAllowedMoves(new Coordinate(x, y)); - if (allowedMoves == null) + GetAllowedMovesCommand movesCommand = new GetAllowedMovesCommand(new Coordinate(x, y)); + if(sendCommand(movesCommand) == CommandResult.NotAllowed) return false; - for (int i = 0; i < 8; i++) { - for (int j = 0; j < 8; j++) { - JLabel cell = this.cells[i][j]; - if (allowedMoves[i][j]) - cell.setBackground(Color.CYAN); - } + + List allowedMoves = movesCommand.getDestinations(); + if (allowedMoves.isEmpty()) + return false; + + for (Coordinate destCoord : allowedMoves) { + JLabel cell = this.cells[destCoord.getX()][destCoord.getY()]; + cell.setBackground(Color.CYAN); } return true; } @@ -157,7 +129,7 @@ public class Window extends JFrame { private void onCellClicked(int x, int y) { clearMoves(); if (this.lastClick == null) { - if (this.board.isCellEmpty(new Coordinate(x, y))) + if (isCellEmpty(x, y)) return; if (!previewMoves(x, y)) return; @@ -173,4 +145,39 @@ public class Window extends JFrame { this.lastClick = null; } + @Override + public void playerTurn(chess.model.Color color) { + System.out.println("C'est au tour de " + color); + } + + @Override + public void winnerIs(chess.model.Color color) { + System.out.println("Victoire de " + color); + } + + @Override + public void kingIsInCheck() { + System.out.println("Échec !"); + } + + @Override + public void kingIsInMat() { + System.out.println("Échec et mat !"); + } + + @Override + public void patSituation() { + System.out.println("Pat. Égalité !"); + } + + @Override + public void hasSurrendered(chess.model.Color color) { + System.out.println("Abandon de " + color); + } + + @Override + public void gameStarted() { + buildBoard(); + } + } diff --git a/app/src/test/java/chess/AppTest.java b/app/src/test/java/chess/AppTest.java index 3f66471..56c64dc 100644 --- a/app/src/test/java/chess/AppTest.java +++ b/app/src/test/java/chess/AppTest.java @@ -8,7 +8,7 @@ import static org.junit.jupiter.api.Assertions.*; class AppTest { @Test void appHasAGreeting() { - App classUnderTest = new App(); - assertNotNull(classUnderTest.getGreeting(), "app should have a greeting"); + // App classUnderTest = new App(); + // assertNotNull(classUnderTest.getGreeting(), "app should have a greeting"); } }