From 32446d4652e443d578e0bd8e7046c3b6a096b556 Mon Sep 17 00:00:00 2001 From: CyB3RC0nN0R Date: Tue, 2 Jul 2019 13:49:36 +0200 Subject: [PATCH] Added block checking to move validation + Move class + Utility methods in Board + isFreePath method in Piece with implementations in every subclass - Pawn movement is still not fully implemented, including promotion, en passant and movement over two tiles --- src/dev/kske/chess/Board.java | 64 +++++++++++++++++++--------- src/dev/kske/chess/Move.java | 29 +++++++++++++ src/dev/kske/chess/piece/Bishop.java | 19 +++++++-- src/dev/kske/chess/piece/King.java | 11 +++-- src/dev/kske/chess/piece/Knight.java | 13 +++--- src/dev/kske/chess/piece/Pawn.java | 32 +++++++++++--- src/dev/kske/chess/piece/Piece.java | 31 +++++++++++--- src/dev/kske/chess/piece/Queen.java | 27 ++++++++++-- src/dev/kske/chess/piece/Rook.java | 23 ++++++++-- 9 files changed, 194 insertions(+), 55 deletions(-) create mode 100644 src/dev/kske/chess/Move.java diff --git a/src/dev/kske/chess/Board.java b/src/dev/kske/chess/Board.java index b6f80f7..df3ff7b 100644 --- a/src/dev/kske/chess/Board.java +++ b/src/dev/kske/chess/Board.java @@ -25,49 +25,71 @@ public class Board { } public boolean move(int xPos, int yPos, int xDest, int yDest) { - if (boardArr[xPos][yPos] == null || !boardArr[xPos][yPos].isValidMove(xPos, yPos, xDest, yDest)) return false; + return move(new Move(xPos, yPos, xDest, yDest)); + } + + public boolean move(Move move) { + Piece piece = getPos(move); + if (piece == null || !piece.isValidMove(move)) return false; else { - boardArr[xDest][yDest] = boardArr[xPos][yPos]; - boardArr[xPos][yPos] = null; + // Move piece + setDest(move, getPos(move)); + setPos(move, null); return true; } } + public Piece getPos(Move move) { + return boardArr[move.xPos][move.yPos]; + } + + public Piece getDest(Move move) { + return boardArr[move.xDest][move.yDest]; + } + + public void setPos(Move move, Piece piece) { + boardArr[move.xPos][move.yPos] = piece; + } + + public void setDest(Move move, Piece piece) { + boardArr[move.xDest][move.yDest] = piece; + } + /** * Initialized the board array with the default chess pieces and positions. */ private void initializeDefaultPositions() { // Initialize pawns for (int i = 0; i < 8; i++) { - boardArr[i][1] = new Pawn(Color.BLACK); - boardArr[i][6] = new Pawn(Color.WHITE); + boardArr[i][1] = new Pawn(Color.BLACK, this); + boardArr[i][6] = new Pawn(Color.WHITE, this); } // Initialize kings - boardArr[4][0] = new King(Color.BLACK); - boardArr[4][7] = new King(Color.WHITE); + boardArr[4][0] = new King(Color.BLACK, this); + boardArr[4][7] = new King(Color.WHITE, this); // Initialize queens - boardArr[3][0] = new Queen(Color.BLACK); - boardArr[3][7] = new Queen(Color.WHITE); + boardArr[3][0] = new Queen(Color.BLACK, this); + boardArr[3][7] = new Queen(Color.WHITE, this); // Initialize rooks - boardArr[0][0] = new Rook(Color.BLACK); - boardArr[0][7] = new Rook(Color.WHITE); - boardArr[7][0] = new Rook(Color.BLACK); - boardArr[7][7] = new Rook(Color.WHITE); + boardArr[0][0] = new Rook(Color.BLACK, this); + boardArr[0][7] = new Rook(Color.WHITE, this); + boardArr[7][0] = new Rook(Color.BLACK, this); + boardArr[7][7] = new Rook(Color.WHITE, this); // Initialize knights - boardArr[1][0] = new Knight(Color.BLACK); - boardArr[1][7] = new Knight(Color.WHITE); - boardArr[6][0] = new Knight(Color.BLACK); - boardArr[6][7] = new Knight(Color.WHITE); + boardArr[1][0] = new Knight(Color.BLACK, this); + boardArr[1][7] = new Knight(Color.WHITE, this); + boardArr[6][0] = new Knight(Color.BLACK, this); + boardArr[6][7] = new Knight(Color.WHITE, this); // Initialize bishops - boardArr[2][0] = new Bishop(Color.BLACK); - boardArr[2][7] = new Bishop(Color.WHITE); - boardArr[5][0] = new Bishop(Color.BLACK); - boardArr[5][7] = new Bishop(Color.WHITE); + boardArr[2][0] = new Bishop(Color.BLACK, this); + boardArr[2][7] = new Bishop(Color.WHITE, this); + boardArr[5][0] = new Bishop(Color.BLACK, this); + boardArr[5][7] = new Bishop(Color.WHITE, this); } /** diff --git a/src/dev/kske/chess/Move.java b/src/dev/kske/chess/Move.java new file mode 100644 index 0000000..345ee4f --- /dev/null +++ b/src/dev/kske/chess/Move.java @@ -0,0 +1,29 @@ +package dev.kske.chess; + +/** + * Project: Chess
+ * File: Move.java
+ * Created: 02.07.2019
+ * Author: Kai S. K. Engelbart + */ +public class Move { + + public final int xPos, yPos, xDest, yDest, xDist, yDist, xSign, ySign; + + public Move(int xPos, int yPos, int xDest, int yDest) { + this.xPos = xPos; + this.yPos = yPos; + this.xDest = xDest; + this.yDest = yDest; + xDist = Math.abs(xDest - xPos); + yDist = Math.abs(yDest - yPos); + xSign = (int) Math.signum(xDest - xPos); + ySign = (int) Math.signum(yDest - yPos); + } + + public boolean isHorizontal() { return yDist == 0; } + + public boolean isVertical() { return xDist == 0; } + + public boolean isDiagonal() { return xDist == yDist; } +} diff --git a/src/dev/kske/chess/piece/Bishop.java b/src/dev/kske/chess/piece/Bishop.java index 30ba42b..ce4d656 100644 --- a/src/dev/kske/chess/piece/Bishop.java +++ b/src/dev/kske/chess/piece/Bishop.java @@ -1,5 +1,8 @@ package dev.kske.chess.piece; +import dev.kske.chess.Board; +import dev.kske.chess.Move; + /** * Project: Chess
* File: Bishop.java
@@ -8,13 +11,21 @@ package dev.kske.chess.piece; */ public class Bishop extends Piece { - public Bishop(Color color) { - super(color); + public Bishop(Color color, Board board) { + super(color, board); } @Override - public boolean isValidMove(int xPos, int yPos, int xDest, int yDest) { - return Math.abs(xDest - xPos) == Math.abs(yDest - yPos); + public boolean isValidMove(Move move) { + return move.isDiagonal() && isFreePath(move); + } + + @Override + protected boolean isFreePath(Move move) { + for (int i = move.xPos + move.xSign, j = move.yPos + + move.ySign; i != move.xDest; i += move.xSign, j += move.ySign) + if (board.getBoardArr()[i][j] != null) return false; + return checkDestination(move); } @Override diff --git a/src/dev/kske/chess/piece/King.java b/src/dev/kske/chess/piece/King.java index d0c9c89..2766215 100644 --- a/src/dev/kske/chess/piece/King.java +++ b/src/dev/kske/chess/piece/King.java @@ -1,5 +1,8 @@ package dev.kske.chess.piece; +import dev.kske.chess.Board; +import dev.kske.chess.Move; + /** * Project: Chess
* File: King.java
@@ -8,13 +11,13 @@ package dev.kske.chess.piece; */ public class King extends Piece { - public King(Color color) { - super(color); + public King(Color color, Board board) { + super(color, board); } @Override - public boolean isValidMove(int xPos, int yPos, int xDest, int yDest) { - return Math.abs(xDest - xPos) <= 1 && Math.abs(yDest - yPos) <= 1; + public boolean isValidMove(Move move) { + return move.xDist <= 1 && move.yDist <= 1 && isFreePath(move); } @Override diff --git a/src/dev/kske/chess/piece/Knight.java b/src/dev/kske/chess/piece/Knight.java index 6e65fbb..69107c0 100644 --- a/src/dev/kske/chess/piece/Knight.java +++ b/src/dev/kske/chess/piece/Knight.java @@ -1,5 +1,8 @@ package dev.kske.chess.piece; +import dev.kske.chess.Board; +import dev.kske.chess.Move; + /** * Project: Chess
* File: Knight.java
@@ -8,15 +11,13 @@ package dev.kske.chess.piece; */ public class Knight extends Piece { - public Knight(Color color) { - super(color); + public Knight(Color color, Board board) { + super(color, board); } @Override - public boolean isValidMove(int xPos, int yPos, int xDest, int yDest) { - int xDist = Math.abs(xDest - xPos); - int yDist = Math.abs(yDest - yPos); - return Math.abs(xDist - yDist) == 1 && xDist != 0 && yDist != 0; + public boolean isValidMove(Move move) { + return Math.abs(move.xDist - move.yDist) == 1 && move.xDist != 0 && move.yDist != 0 && isFreePath(move); } @Override diff --git a/src/dev/kske/chess/piece/Pawn.java b/src/dev/kske/chess/piece/Pawn.java index 608d551..a66fc89 100644 --- a/src/dev/kske/chess/piece/Pawn.java +++ b/src/dev/kske/chess/piece/Pawn.java @@ -1,5 +1,8 @@ package dev.kske.chess.piece; +import dev.kske.chess.Board; +import dev.kske.chess.Move; + /** * Project: Chess
* File: Pawn.java
@@ -8,16 +11,31 @@ package dev.kske.chess.piece; */ public class Pawn extends Piece { - public Pawn(Color color) { - super(color); + public Pawn(Color color, Board board) { + super(color, board); } @Override - public boolean isValidMove(int xPos, int yPos, int xDest, int yDest) { - int direction = color == Color.WHITE ? -1 : 1; - int xDist = Math.abs(xDest - xPos); - int yDist = (yDest - yPos) * direction; - return (xDist == 0 && yDist > 0 && yDist <= 2) || (xDist == 1 && yDist == 1); + public boolean isValidMove(Move move) { + // TODO: Positioning, en passant + if (getColor() == Color.WHITE) + return ((move.xDist == 0 && move.yDist > 0 && move.yDist <= 2) || (move.xDist == 1 && move.yDist == 1)) + && move.ySign == -1 && isFreePath(move); + else return ((move.xDist == 0 && move.yDist > 0 && move.yDist <= 2) || (move.xDist == 1 && move.yDist == 1)) + && move.ySign == 1 + && isFreePath(move); + + } + + @Override + protected boolean isFreePath(Move move) { + // Two steps forward + if (move.yDist == 2) + return board.getBoardArr()[move.xPos][move.yDest - move.ySign] == null && checkDestination(move); + // One step forward + else if (move.xDist == 0) return board.getDest(move) == null; + // Capture move + else return board.getDest(move) != null && board.getDest(move).getColor() != getColor(); } @Override diff --git a/src/dev/kske/chess/piece/Piece.java b/src/dev/kske/chess/piece/Piece.java index ebfae3a..ef22b19 100644 --- a/src/dev/kske/chess/piece/Piece.java +++ b/src/dev/kske/chess/piece/Piece.java @@ -1,5 +1,8 @@ package dev.kske.chess.piece; +import dev.kske.chess.Board; +import dev.kske.chess.Move; + /** * Project: Chess
* File: Piece.java
@@ -8,18 +11,36 @@ package dev.kske.chess.piece; */ public abstract class Piece { - protected Color color; + protected Color color; + protected Board board; - public Piece(Color color) { - this.color = color; + public Piece(Color color, Board board) { + this.color = color; + this.board = board; } - public abstract boolean isValidMove(int xPos, int yPos, int xDest, int yDest); + public abstract boolean isValidMove(Move move); + + protected boolean isFreePath(Move move) { + // Only check destination by default + return checkDestination(move); + } + + /** + * Checks if the destination of a move is empty or a piece from the opposing + * team + * + * @param move The move to check + * @return {@code false} if the move's destination is from the same team + */ + protected final boolean checkDestination(Move move) { + return board.getDest(move) == null || board.getDest(move).getColor() != getColor(); + } public abstract Type getType(); public Color getColor() { return color; } - + public static enum Type { KING, QUEEN, ROOK, KNIGHT, BISHOP, PAWN; } diff --git a/src/dev/kske/chess/piece/Queen.java b/src/dev/kske/chess/piece/Queen.java index d215ba0..15cdba5 100644 --- a/src/dev/kske/chess/piece/Queen.java +++ b/src/dev/kske/chess/piece/Queen.java @@ -1,5 +1,8 @@ package dev.kske.chess.piece; +import dev.kske.chess.Board; +import dev.kske.chess.Move; + /** * Project: Chess
* File: Queen.java
@@ -8,13 +11,29 @@ package dev.kske.chess.piece; */ public class Queen extends Piece { - public Queen(Color color) { - super(color); + public Queen(Color color, Board board) { + super(color, board); } @Override - public boolean isValidMove(int xPos, int yPos, int xDest, int yDest) { - return (xPos == xDest || yPos == yDest) || (Math.abs(xDest - xPos) == Math.abs(yDest - yPos)); + public boolean isValidMove(Move move) { + return ((move.isHorizontal() || move.isVertical()) || move.isDiagonal()) && isFreePath(move); + } + + @Override + protected boolean isFreePath(Move move) { + if (move.isHorizontal()) { + for (int i = move.xPos + move.xSign; i != move.xDest; i += move.xSign) + if (board.getBoardArr()[i][move.yPos] != null) return false; + } else if (move.isVertical()) { + for (int i = move.yPos + move.ySign; i != move.yDest; i += move.ySign) + if (board.getBoardArr()[move.xPos][i] != null) return false; + } else { + for (int i = move.xPos + move.xSign, j = move.yPos + + move.ySign; i != move.xDest; i += move.xSign, j += move.ySign) + if (board.getBoardArr()[i][j] != null) return false; + } + return checkDestination(move); } @Override diff --git a/src/dev/kske/chess/piece/Rook.java b/src/dev/kske/chess/piece/Rook.java index 7beb93b..a7c821f 100644 --- a/src/dev/kske/chess/piece/Rook.java +++ b/src/dev/kske/chess/piece/Rook.java @@ -1,5 +1,8 @@ package dev.kske.chess.piece; +import dev.kske.chess.Board; +import dev.kske.chess.Move; + /** * Project: Chess
* File: Rook.java
@@ -8,13 +11,25 @@ package dev.kske.chess.piece; */ public class Rook extends Piece { - public Rook(Color color) { - super(color); + public Rook(Color color, Board board) { + super(color, board); } @Override - public boolean isValidMove(int xPos, int yPos, int xDest, int yDest) { - return xPos == xDest || yPos == yDest; + public boolean isValidMove(Move move) { + return (move.isHorizontal() || move.isVertical()) && isFreePath(move); + } + + @Override + protected boolean isFreePath(Move move) { + if (move.isHorizontal()) { + for (int i = move.xPos + move.xSign; i != move.xDest; i += move.xSign) + if (board.getBoardArr()[i][move.yPos] != null) return false; + } else { + for (int i = move.yPos + move.ySign; i != move.yDest; i += move.ySign) + if (board.getBoardArr()[move.xPos][i] != null) return false; + } + return checkDestination(move); } @Override