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
This commit is contained in:
Kai S. K. Engelbart 2019-07-08 06:41:10 +02:00
parent bbe5fcf13d
commit a3125188c1
7 changed files with 97 additions and 13 deletions

View File

@ -7,5 +7,6 @@
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="lib" path="res"/> <classpathentry kind="lib" path="res"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

View File

@ -14,7 +14,7 @@ import dev.kske.chess.board.Piece.Type;
* Created: <strong>01.07.2019</strong><br> * Created: <strong>01.07.2019</strong><br>
* Author: <strong>Kai S. K. Engelbart</strong> * Author: <strong>Kai S. K. Engelbart</strong>
*/ */
public class Board { public class Board implements Cloneable {
private Piece[][] boardArr; private Piece[][] boardArr;
private Map<Color, Position> kingPos; private Map<Color, Position> kingPos;
@ -35,10 +35,7 @@ public class Board {
Piece piece = getPos(move); Piece piece = getPos(move);
if (piece == null || !piece.isValidMove(move)) return false; if (piece == null || !piece.isValidMove(move)) return false;
else { else {
/* // Move piece
* Move piece
* Save destination piece for possible canceling of the move
*/
Piece capturePiece = move(move); Piece capturePiece = move(move);
// Revert move if it caused a check for its team // Revert move if it caused a check for its team
@ -223,6 +220,32 @@ public class Board {
boardArr[i][j] = null; 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) { public Piece get(Position pos) {
return boardArr[pos.x][pos.y]; return boardArr[pos.x][pos.y];
} }

View File

@ -9,7 +9,7 @@ import java.util.List;
* Created: <strong>01.07.2019</strong><br> * Created: <strong>01.07.2019</strong><br>
* Author: <strong>Kai S. K. Engelbart</strong> * Author: <strong>Kai S. K. Engelbart</strong>
*/ */
public abstract class Piece { public abstract class Piece implements Cloneable {
protected Color color; protected Color color;
protected Board board; protected Board board;
@ -51,6 +51,17 @@ public abstract class Piece {
return board.getDest(move) == null || board.getDest(move).getColor() != getColor(); 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 abstract Type getType();
public Color getColor() { return color; } public Color getColor() { return color; }

View File

@ -1,5 +1,7 @@
package dev.kske.chess.game; package dev.kske.chess.game;
import javax.swing.SwingUtilities;
import dev.kske.chess.board.Board; import dev.kske.chess.board.Board;
import dev.kske.chess.board.Move; import dev.kske.chess.board.Move;
import dev.kske.chess.board.Piece; import dev.kske.chess.board.Piece;
@ -22,10 +24,12 @@ public class AIPlayer extends Player {
@Override @Override
public void requestMove() { public void requestMove() {
new Thread(() -> {
count = 0; count = 0;
findBestMove(board, color, 0); findBestMove((Board) board.clone(), color, 0);
System.out.println("Moved processes: " + count); System.out.println("Moved processes: " + count);
game.onMove(this, bestMove); SwingUtilities.invokeLater(() -> game.onMove(this, bestMove));
}).start();
} }
private int findBestMove(Board board, Color color, int depth) { private int findBestMove(Board board, Color color, int depth) {

View File

@ -36,8 +36,6 @@ public class Game {
public void onMove(Player player, Move move) { public void onMove(Player player, Move move) {
if (board.getPos(move).getColor() == player.color && board.attemptMove(move)) { if (board.getPos(move).getColor() == player.color && board.attemptMove(move)) {
System.out.printf("%s: %s%n", player.color, move); System.out.printf("%s: %s%n", player.color, move);
boardPanel.repaint();
GameState eventType = board.getGameEventType(board.getDest(move).getColor().opposite()); GameState eventType = board.getGameEventType(board.getDest(move).getColor().opposite());
switch (eventType) { switch (eventType) {
case CHECKMATE: case CHECKMATE:
@ -47,7 +45,9 @@ public class Game {
case CHECK: case CHECK:
System.out.printf("%s in check!%n", player.color); System.out.printf("%s in check!%n", player.color);
default: default:
boardPanel.repaint();
players.get(player.color.opposite()).requestMove(); players.get(player.color.opposite()).requestMove();
} }
} else { } else {
System.out.printf("%s: Illegal move!%n", player.getColor()); System.out.printf("%s: Illegal move!%n", player.getColor());

View File

@ -33,6 +33,7 @@ public class NaturalPlayer extends Player {
pos = new Position(evt.getPoint().x / boardPanel.getTileSize(), pos = new Position(evt.getPoint().x / boardPanel.getTileSize(),
evt.getPoint().y / boardPanel.getTileSize()); evt.getPoint().y / boardPanel.getTileSize());
Board board = (Board) NaturalPlayer.this.board.clone();
if (board.get(pos) != null && board.get(pos).getColor() == color) if (board.get(pos) != null && board.get(pos).getColor() == color)
boardPanel.displayMoves(board.getMoves(pos)); boardPanel.displayMoves(board.getMoves(pos));
else pos = null; else pos = null;

View File

@ -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: <strong>Chess</strong><br>
* File: <strong>BoardCloneTest.java</strong><br>
* Created: <strong>08.07.2019</strong><br>
* Author: <strong>Kai S. K. Engelbart</strong>
*/
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]);
}
}