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
This commit is contained in:
parent
bae5618f59
commit
32446d4652
@ -25,49 +25,71 @@ public class Board {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean move(int xPos, int yPos, int xDest, int yDest) {
|
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 {
|
else {
|
||||||
boardArr[xDest][yDest] = boardArr[xPos][yPos];
|
// Move piece
|
||||||
boardArr[xPos][yPos] = null;
|
setDest(move, getPos(move));
|
||||||
|
setPos(move, null);
|
||||||
return true;
|
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.
|
* Initialized the board array with the default chess pieces and positions.
|
||||||
*/
|
*/
|
||||||
private void initializeDefaultPositions() {
|
private void initializeDefaultPositions() {
|
||||||
// Initialize pawns
|
// Initialize pawns
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
boardArr[i][1] = new Pawn(Color.BLACK);
|
boardArr[i][1] = new Pawn(Color.BLACK, this);
|
||||||
boardArr[i][6] = new Pawn(Color.WHITE);
|
boardArr[i][6] = new Pawn(Color.WHITE, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize kings
|
// Initialize kings
|
||||||
boardArr[4][0] = new King(Color.BLACK);
|
boardArr[4][0] = new King(Color.BLACK, this);
|
||||||
boardArr[4][7] = new King(Color.WHITE);
|
boardArr[4][7] = new King(Color.WHITE, this);
|
||||||
|
|
||||||
// Initialize queens
|
// Initialize queens
|
||||||
boardArr[3][0] = new Queen(Color.BLACK);
|
boardArr[3][0] = new Queen(Color.BLACK, this);
|
||||||
boardArr[3][7] = new Queen(Color.WHITE);
|
boardArr[3][7] = new Queen(Color.WHITE, this);
|
||||||
|
|
||||||
// Initialize rooks
|
// Initialize rooks
|
||||||
boardArr[0][0] = new Rook(Color.BLACK);
|
boardArr[0][0] = new Rook(Color.BLACK, this);
|
||||||
boardArr[0][7] = new Rook(Color.WHITE);
|
boardArr[0][7] = new Rook(Color.WHITE, this);
|
||||||
boardArr[7][0] = new Rook(Color.BLACK);
|
boardArr[7][0] = new Rook(Color.BLACK, this);
|
||||||
boardArr[7][7] = new Rook(Color.WHITE);
|
boardArr[7][7] = new Rook(Color.WHITE, this);
|
||||||
|
|
||||||
// Initialize knights
|
// Initialize knights
|
||||||
boardArr[1][0] = new Knight(Color.BLACK);
|
boardArr[1][0] = new Knight(Color.BLACK, this);
|
||||||
boardArr[1][7] = new Knight(Color.WHITE);
|
boardArr[1][7] = new Knight(Color.WHITE, this);
|
||||||
boardArr[6][0] = new Knight(Color.BLACK);
|
boardArr[6][0] = new Knight(Color.BLACK, this);
|
||||||
boardArr[6][7] = new Knight(Color.WHITE);
|
boardArr[6][7] = new Knight(Color.WHITE, this);
|
||||||
|
|
||||||
// Initialize bishops
|
// Initialize bishops
|
||||||
boardArr[2][0] = new Bishop(Color.BLACK);
|
boardArr[2][0] = new Bishop(Color.BLACK, this);
|
||||||
boardArr[2][7] = new Bishop(Color.WHITE);
|
boardArr[2][7] = new Bishop(Color.WHITE, this);
|
||||||
boardArr[5][0] = new Bishop(Color.BLACK);
|
boardArr[5][0] = new Bishop(Color.BLACK, this);
|
||||||
boardArr[5][7] = new Bishop(Color.WHITE);
|
boardArr[5][7] = new Bishop(Color.WHITE, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
29
src/dev/kske/chess/Move.java
Normal file
29
src/dev/kske/chess/Move.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package dev.kske.chess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project: <strong>Chess</strong><br>
|
||||||
|
* File: <strong>Move.java</strong><br>
|
||||||
|
* Created: <strong>02.07.2019</strong><br>
|
||||||
|
* Author: <strong>Kai S. K. Engelbart</strong>
|
||||||
|
*/
|
||||||
|
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; }
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
package dev.kske.chess.piece;
|
package dev.kske.chess.piece;
|
||||||
|
|
||||||
|
import dev.kske.chess.Board;
|
||||||
|
import dev.kske.chess.Move;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project: <strong>Chess</strong><br>
|
* Project: <strong>Chess</strong><br>
|
||||||
* File: <strong>Bishop.java</strong><br>
|
* File: <strong>Bishop.java</strong><br>
|
||||||
@ -8,13 +11,21 @@ package dev.kske.chess.piece;
|
|||||||
*/
|
*/
|
||||||
public class Bishop extends Piece {
|
public class Bishop extends Piece {
|
||||||
|
|
||||||
public Bishop(Color color) {
|
public Bishop(Color color, Board board) {
|
||||||
super(color);
|
super(color, board);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidMove(int xPos, int yPos, int xDest, int yDest) {
|
public boolean isValidMove(Move move) {
|
||||||
return Math.abs(xDest - xPos) == Math.abs(yDest - yPos);
|
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
|
@Override
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package dev.kske.chess.piece;
|
package dev.kske.chess.piece;
|
||||||
|
|
||||||
|
import dev.kske.chess.Board;
|
||||||
|
import dev.kske.chess.Move;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project: <strong>Chess</strong><br>
|
* Project: <strong>Chess</strong><br>
|
||||||
* File: <strong>King.java</strong><br>
|
* File: <strong>King.java</strong><br>
|
||||||
@ -8,13 +11,13 @@ package dev.kske.chess.piece;
|
|||||||
*/
|
*/
|
||||||
public class King extends Piece {
|
public class King extends Piece {
|
||||||
|
|
||||||
public King(Color color) {
|
public King(Color color, Board board) {
|
||||||
super(color);
|
super(color, board);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidMove(int xPos, int yPos, int xDest, int yDest) {
|
public boolean isValidMove(Move move) {
|
||||||
return Math.abs(xDest - xPos) <= 1 && Math.abs(yDest - yPos) <= 1;
|
return move.xDist <= 1 && move.yDist <= 1 && isFreePath(move);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package dev.kske.chess.piece;
|
package dev.kske.chess.piece;
|
||||||
|
|
||||||
|
import dev.kske.chess.Board;
|
||||||
|
import dev.kske.chess.Move;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project: <strong>Chess</strong><br>
|
* Project: <strong>Chess</strong><br>
|
||||||
* File: <strong>Knight.java</strong><br>
|
* File: <strong>Knight.java</strong><br>
|
||||||
@ -8,15 +11,13 @@ package dev.kske.chess.piece;
|
|||||||
*/
|
*/
|
||||||
public class Knight extends Piece {
|
public class Knight extends Piece {
|
||||||
|
|
||||||
public Knight(Color color) {
|
public Knight(Color color, Board board) {
|
||||||
super(color);
|
super(color, board);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidMove(int xPos, int yPos, int xDest, int yDest) {
|
public boolean isValidMove(Move move) {
|
||||||
int xDist = Math.abs(xDest - xPos);
|
return Math.abs(move.xDist - move.yDist) == 1 && move.xDist != 0 && move.yDist != 0 && isFreePath(move);
|
||||||
int yDist = Math.abs(yDest - yPos);
|
|
||||||
return Math.abs(xDist - yDist) == 1 && xDist != 0 && yDist != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package dev.kske.chess.piece;
|
package dev.kske.chess.piece;
|
||||||
|
|
||||||
|
import dev.kske.chess.Board;
|
||||||
|
import dev.kske.chess.Move;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project: <strong>Chess</strong><br>
|
* Project: <strong>Chess</strong><br>
|
||||||
* File: <strong>Pawn.java</strong><br>
|
* File: <strong>Pawn.java</strong><br>
|
||||||
@ -8,16 +11,31 @@ package dev.kske.chess.piece;
|
|||||||
*/
|
*/
|
||||||
public class Pawn extends Piece {
|
public class Pawn extends Piece {
|
||||||
|
|
||||||
public Pawn(Color color) {
|
public Pawn(Color color, Board board) {
|
||||||
super(color);
|
super(color, board);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidMove(int xPos, int yPos, int xDest, int yDest) {
|
public boolean isValidMove(Move move) {
|
||||||
int direction = color == Color.WHITE ? -1 : 1;
|
// TODO: Positioning, en passant
|
||||||
int xDist = Math.abs(xDest - xPos);
|
if (getColor() == Color.WHITE)
|
||||||
int yDist = (yDest - yPos) * direction;
|
return ((move.xDist == 0 && move.yDist > 0 && move.yDist <= 2) || (move.xDist == 1 && move.yDist == 1))
|
||||||
return (xDist == 0 && yDist > 0 && yDist <= 2) || (xDist == 1 && 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
|
@Override
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package dev.kske.chess.piece;
|
package dev.kske.chess.piece;
|
||||||
|
|
||||||
|
import dev.kske.chess.Board;
|
||||||
|
import dev.kske.chess.Move;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project: <strong>Chess</strong><br>
|
* Project: <strong>Chess</strong><br>
|
||||||
* File: <strong>Piece.java</strong><br>
|
* File: <strong>Piece.java</strong><br>
|
||||||
@ -9,12 +12,30 @@ package dev.kske.chess.piece;
|
|||||||
public abstract class Piece {
|
public abstract class Piece {
|
||||||
|
|
||||||
protected Color color;
|
protected Color color;
|
||||||
|
protected Board board;
|
||||||
|
|
||||||
public Piece(Color color) {
|
public Piece(Color color, Board board) {
|
||||||
this.color = color;
|
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 abstract Type getType();
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package dev.kske.chess.piece;
|
package dev.kske.chess.piece;
|
||||||
|
|
||||||
|
import dev.kske.chess.Board;
|
||||||
|
import dev.kske.chess.Move;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project: <strong>Chess</strong><br>
|
* Project: <strong>Chess</strong><br>
|
||||||
* File: <strong>Queen.java</strong><br>
|
* File: <strong>Queen.java</strong><br>
|
||||||
@ -8,13 +11,29 @@ package dev.kske.chess.piece;
|
|||||||
*/
|
*/
|
||||||
public class Queen extends Piece {
|
public class Queen extends Piece {
|
||||||
|
|
||||||
public Queen(Color color) {
|
public Queen(Color color, Board board) {
|
||||||
super(color);
|
super(color, board);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidMove(int xPos, int yPos, int xDest, int yDest) {
|
public boolean isValidMove(Move move) {
|
||||||
return (xPos == xDest || yPos == yDest) || (Math.abs(xDest - xPos) == Math.abs(yDest - yPos));
|
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
|
@Override
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package dev.kske.chess.piece;
|
package dev.kske.chess.piece;
|
||||||
|
|
||||||
|
import dev.kske.chess.Board;
|
||||||
|
import dev.kske.chess.Move;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project: <strong>Chess</strong><br>
|
* Project: <strong>Chess</strong><br>
|
||||||
* File: <strong>Rook.java</strong><br>
|
* File: <strong>Rook.java</strong><br>
|
||||||
@ -8,13 +11,25 @@ package dev.kske.chess.piece;
|
|||||||
*/
|
*/
|
||||||
public class Rook extends Piece {
|
public class Rook extends Piece {
|
||||||
|
|
||||||
public Rook(Color color) {
|
public Rook(Color color, Board board) {
|
||||||
super(color);
|
super(color, board);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidMove(int xPos, int yPos, int xDest, int yDest) {
|
public boolean isValidMove(Move move) {
|
||||||
return xPos == xDest || yPos == yDest;
|
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
|
@Override
|
||||||
|
Reference in New Issue
Block a user