From a3125188c1ce0c4706f5faaa45cabf27aa6053a4 Mon Sep 17 00:00:00 2001 From: CyB3RC0nN0R Date: Mon, 8 Jul 2019 06:41:10 +0200 Subject: [PATCH] Fixed rendering + Cloning support in Board and Piece - Using clones for board operations that interfere with rendering - Fixed repaint calls + Unit test for testing board cloning --- .classpath | 1 + src/dev/kske/chess/board/Board.java | 33 +++++++++++++--- src/dev/kske/chess/board/Piece.java | 13 +++++- src/dev/kske/chess/game/AIPlayer.java | 14 ++++--- src/dev/kske/chess/game/Game.java | 4 +- src/dev/kske/chess/game/NaturalPlayer.java | 1 + src/dev/kske/chess/test/BoardCloneTest.java | 44 +++++++++++++++++++++ 7 files changed, 97 insertions(+), 13 deletions(-) create mode 100644 src/dev/kske/chess/test/BoardCloneTest.java diff --git a/.classpath b/.classpath index 07b86b3..99d9707 100644 --- a/.classpath +++ b/.classpath @@ -7,5 +7,6 @@ + diff --git a/src/dev/kske/chess/board/Board.java b/src/dev/kske/chess/board/Board.java index b34c68c..b69f5c6 100644 --- a/src/dev/kske/chess/board/Board.java +++ b/src/dev/kske/chess/board/Board.java @@ -14,7 +14,7 @@ import dev.kske.chess.board.Piece.Type; * Created: 01.07.2019
* Author: Kai S. K. Engelbart */ -public class Board { +public class Board implements Cloneable { private Piece[][] boardArr; private Map kingPos; @@ -35,10 +35,7 @@ public class Board { Piece piece = getPos(move); if (piece == null || !piece.isValidMove(move)) return false; else { - /* - * Move piece - * Save destination piece for possible canceling of the move - */ + // Move piece Piece capturePiece = move(move); // Revert move if it caused a check for its team @@ -223,6 +220,32 @@ public class Board { boardArr[i][j] = null; } + /** + * @return A new instance of this class with a shallow copy of both + * {@code kingPos} and {code boardArr} + */ + @Override + public Object clone() { + Board board = null; + try { + board = (Board) super.clone(); + } catch (CloneNotSupportedException ex) { + ex.printStackTrace(); + } + board.boardArr = new Piece[8][8]; + for (int i = 0; i < 8; i++) + for (int j = 0; j < 8; j++) { + if (boardArr[i][j] == null) continue; + board.boardArr[i][j] = (Piece) boardArr[i][j].clone(); + board.boardArr[i][j].board = board; + } + + board.kingPos = new HashMap<>(); + board.kingPos.putAll(kingPos); + + return board; + } + public Piece get(Position pos) { return boardArr[pos.x][pos.y]; } diff --git a/src/dev/kske/chess/board/Piece.java b/src/dev/kske/chess/board/Piece.java index 2ef3db7..fbb8c0c 100644 --- a/src/dev/kske/chess/board/Piece.java +++ b/src/dev/kske/chess/board/Piece.java @@ -9,7 +9,7 @@ import java.util.List; * Created: 01.07.2019
* Author: Kai S. K. Engelbart */ -public abstract class Piece { +public abstract class Piece implements Cloneable { protected Color color; protected Board board; @@ -51,6 +51,17 @@ public abstract class Piece { return board.getDest(move) == null || board.getDest(move).getColor() != getColor(); } + @Override + public Object clone() { + Piece piece = null; + try { + piece = (Piece) super.clone(); + } catch (CloneNotSupportedException ex) { + ex.printStackTrace(); + } + return piece; + } + public abstract Type getType(); public Color getColor() { return color; } diff --git a/src/dev/kske/chess/game/AIPlayer.java b/src/dev/kske/chess/game/AIPlayer.java index 4cfc702..75ad70d 100644 --- a/src/dev/kske/chess/game/AIPlayer.java +++ b/src/dev/kske/chess/game/AIPlayer.java @@ -1,5 +1,7 @@ package dev.kske.chess.game; +import javax.swing.SwingUtilities; + import dev.kske.chess.board.Board; import dev.kske.chess.board.Move; import dev.kske.chess.board.Piece; @@ -13,7 +15,7 @@ import dev.kske.chess.board.Piece.Color; */ public class AIPlayer extends Player { - private Move bestMove; + private Move bestMove; private int count; public AIPlayer(Board board, Color color) { @@ -22,10 +24,12 @@ public class AIPlayer extends Player { @Override public void requestMove() { - count = 0; - findBestMove(board, color, 0); - System.out.println("Moved processes: " + count); - game.onMove(this, bestMove); + new Thread(() -> { + count = 0; + findBestMove((Board) board.clone(), color, 0); + System.out.println("Moved processes: " + count); + SwingUtilities.invokeLater(() -> game.onMove(this, bestMove)); + }).start(); } private int findBestMove(Board board, Color color, int depth) { diff --git a/src/dev/kske/chess/game/Game.java b/src/dev/kske/chess/game/Game.java index 2179d64..9953e23 100644 --- a/src/dev/kske/chess/game/Game.java +++ b/src/dev/kske/chess/game/Game.java @@ -36,8 +36,6 @@ public class Game { public void onMove(Player player, Move move) { if (board.getPos(move).getColor() == player.color && board.attemptMove(move)) { System.out.printf("%s: %s%n", player.color, move); - boardPanel.repaint(); - GameState eventType = board.getGameEventType(board.getDest(move).getColor().opposite()); switch (eventType) { case CHECKMATE: @@ -47,7 +45,9 @@ public class Game { case CHECK: System.out.printf("%s in check!%n", player.color); default: + boardPanel.repaint(); players.get(player.color.opposite()).requestMove(); + } } else { System.out.printf("%s: Illegal move!%n", player.getColor()); diff --git a/src/dev/kske/chess/game/NaturalPlayer.java b/src/dev/kske/chess/game/NaturalPlayer.java index b30225d..9229096 100644 --- a/src/dev/kske/chess/game/NaturalPlayer.java +++ b/src/dev/kske/chess/game/NaturalPlayer.java @@ -33,6 +33,7 @@ public class NaturalPlayer extends Player { pos = new Position(evt.getPoint().x / boardPanel.getTileSize(), evt.getPoint().y / boardPanel.getTileSize()); + Board board = (Board) NaturalPlayer.this.board.clone(); if (board.get(pos) != null && board.get(pos).getColor() == color) boardPanel.displayMoves(board.getMoves(pos)); else pos = null; diff --git a/src/dev/kske/chess/test/BoardCloneTest.java b/src/dev/kske/chess/test/BoardCloneTest.java new file mode 100644 index 0000000..5c7df20 --- /dev/null +++ b/src/dev/kske/chess/test/BoardCloneTest.java @@ -0,0 +1,44 @@ +package dev.kske.chess.test; + +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotSame; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import dev.kske.chess.board.Board; +import dev.kske.chess.board.Piece.Color; +import dev.kske.chess.board.Queen; + +/** + * Project: Chess
+ * File: BoardCloneTest.java
+ * Created: 08.07.2019
+ * Author: Kai S. K. Engelbart + */ +class BoardCloneTest { + + Board board; + + /** + * @throws java.lang.Exception + */ + @BeforeEach + void setUp() throws Exception { + board = new Board(); + } + + /** + * Test method for {@link dev.kske.chess.board.Board#clone()}. + */ + @Test + void testClone() { + Board clone = (Board) board.clone(); + assertNotSame(clone, board); + assertNotSame(clone.getBoardArr(), board.getBoardArr()); + + clone.getBoardArr()[0][0] = new Queen(Color.BLACK, clone); + assertNotEquals(clone.getBoardArr()[0][0], board.getBoardArr()[0][0]); + } + +}