186 lines
4.4 KiB
Java
186 lines
4.4 KiB
Java
package chess.model;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import chess.model.visitor.KingIdentifier;
|
|
import chess.model.visitor.PiecePathChecker;
|
|
|
|
public class ChessBoard {
|
|
public static class Cell {
|
|
private Piece piece;
|
|
|
|
public Cell() {
|
|
this.piece = null;
|
|
}
|
|
|
|
public Piece getPiece() {
|
|
return piece;
|
|
}
|
|
|
|
public void setPiece(Piece piece) {
|
|
this.piece = piece;
|
|
}
|
|
|
|
}
|
|
|
|
private final Cell[][] cells;
|
|
private Move lastMove;
|
|
private Piece lastEjectedPiece;
|
|
|
|
public ChessBoard() {
|
|
this.cells = new Cell[Coordinate.VALUE_MAX][Coordinate.VALUE_MAX];
|
|
for (int i = 0; i < Coordinate.VALUE_MAX; i++) {
|
|
for (int j = 0; j < Coordinate.VALUE_MAX; j++) {
|
|
this.cells[i][j] = new Cell();
|
|
}
|
|
}
|
|
this.lastMove = null;
|
|
this.lastEjectedPiece = null;
|
|
}
|
|
|
|
public void applyMove(Move move) {
|
|
assert move.isValid() : "Invalid move !";
|
|
Piece deadPiece = pieceAt(move.getFinish());
|
|
if (deadPiece != null) {
|
|
this.lastEjectedPiece = deadPiece;
|
|
} else {
|
|
this.lastEjectedPiece = null;
|
|
}
|
|
Piece movingPiece = pieceAt(move.getStart());
|
|
pieceComes(movingPiece, move.getFinish());
|
|
pieceLeaves(move.getStart());
|
|
movingPiece.move();
|
|
this.lastMove = move;
|
|
}
|
|
|
|
public void undoLastMove() {
|
|
assert this.lastMove != null: "Can't undo at the beginning!";
|
|
|
|
Move move = this.lastMove;
|
|
|
|
Piece movingPiece = pieceAt(move.getFinish());
|
|
pieceComes(movingPiece, move.getStart());
|
|
pieceLeaves(move.getFinish());
|
|
movingPiece.unMove();
|
|
|
|
if (this.lastEjectedPiece == null)
|
|
return;
|
|
|
|
Piece piece = this.lastEjectedPiece;
|
|
|
|
pieceComes(piece, move.getFinish());
|
|
}
|
|
|
|
public boolean isCellEmpty(Coordinate coordinate) {
|
|
return pieceAt(coordinate) == null;
|
|
}
|
|
|
|
public Piece pieceAt(Coordinate coordinate) {
|
|
if (!coordinate.isValid())
|
|
return null;
|
|
return cellAt(coordinate).getPiece();
|
|
}
|
|
|
|
public void clearBoard() {
|
|
for (int i = 0; i < Coordinate.VALUE_MAX; i++) {
|
|
for (int j = 0; j < Coordinate.VALUE_MAX; j++) {
|
|
pieceLeaves(new Coordinate(i, j));
|
|
}
|
|
}
|
|
}
|
|
|
|
private Cell cellAt(Coordinate coordinate) {
|
|
return this.cells[coordinate.getX()][coordinate.getY()];
|
|
}
|
|
|
|
public void pieceComes(Piece piece, Coordinate coordinate) {
|
|
cellAt(coordinate).setPiece(piece);
|
|
}
|
|
|
|
public void pieceLeaves(Coordinate coordinate) {
|
|
cellAt(coordinate).setPiece(null);
|
|
}
|
|
|
|
public Coordinate findKing(Color color) {
|
|
KingIdentifier kingIdentifier = new KingIdentifier(color);
|
|
for (int i = 0; i < Coordinate.VALUE_MAX; i++) {
|
|
for (int j = 0; j < Coordinate.VALUE_MAX; j++) {
|
|
Coordinate coordinate = new Coordinate(i, j);
|
|
Piece piece = pieceAt(coordinate);
|
|
if (piece != null && kingIdentifier.visit(piece)) {
|
|
return coordinate;
|
|
}
|
|
}
|
|
}
|
|
assert false : "No king found ?!";
|
|
return null;
|
|
}
|
|
|
|
public boolean isKingInCheck(Color color) {
|
|
Coordinate kingPos = findKing(color);
|
|
assert kingPos.isValid() : "King position is invalid!";
|
|
|
|
for (int i = 0; i < Coordinate.VALUE_MAX; i++) {
|
|
for (int j = 0; j < Coordinate.VALUE_MAX; j++) {
|
|
Coordinate attackCoords = new Coordinate(i, j);
|
|
Piece attackPiece = pieceAt(attackCoords);
|
|
if (attackPiece == null)
|
|
continue;
|
|
|
|
PiecePathChecker checker = new PiecePathChecker(this, new Move(attackCoords, kingPos));
|
|
if (checker.isValid())
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean hasAllowedMoves(Color player) {
|
|
for (int i = 0; i < Coordinate.VALUE_MAX; i++) {
|
|
for (int j = 0; j < Coordinate.VALUE_MAX; j++) {
|
|
Coordinate attackCoords = new Coordinate(i, j);
|
|
Piece attackPiece = pieceAt(attackCoords);
|
|
if (attackPiece == null)
|
|
continue;
|
|
|
|
if (attackPiece.getColor() != player)
|
|
continue;
|
|
|
|
if (!getAllowedMoves(attackCoords).isEmpty())
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public List<Coordinate> getAllowedMoves(Coordinate pieceCoords) {
|
|
Piece piece = pieceAt(pieceCoords);
|
|
if (piece == null)
|
|
return null;
|
|
|
|
Color player = piece.getColor();
|
|
|
|
List<Coordinate> result = new ArrayList<>();
|
|
|
|
for (int i = 0; i < Coordinate.VALUE_MAX; i++) {
|
|
for (int j = 0; j < Coordinate.VALUE_MAX; 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);
|
|
if (!isKingInCheck(player))
|
|
result.add(destination);
|
|
undoLastMove();
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
}
|