This question is fairly large and difficult to solve without looking through my code, and if it's exceedingly so, then the scope is probably too large and I'll delete the question. Basically I have a working Chess game with all of the rules of Chess except Check (and thus also not Checkmate, stalemate, etc.) implemented.
I went about implementing Check by assigning the Squares of my ChessBoard two booleans: protectedByWhite
and protectedByBlack
. There are two main pieces of logic with check:
protectedByBlack
, and vice versa with Black, the move is
"undone". protectedByWhite
, and vice versa with Black, Black's next move must place his king on a square that is not protectedByWhite
.Thus the logic is fairly simple. In my ChessBoard
class, I have testCheckWhite
and testCheckBlack
functions that are called after every move. Moves are called in my Square
class (a simple mouse click function).
The main problem is that the code is buggy... and I'm not sure why/where. The main bug is that:
For example, I have labels on the side that alert when Black/White are in check. When I initially "Check" the opponent, the label notifies me of the check. However, when I try to move the king to a square where I would still be in check, the label incorrectly says that there is no Check. I've been working for some time now trying to identify where I've gone wrong, and I could use some direction.
RELEVANT CODE:
ChessBoard.Java
public static void setProtectedSquares() {
// Reset
for(Square s : BOARD_SQUARES) {
s.protectedByWhite = false;
s.protectedByBlack = false;
}
// Now set protections
for(Square s : BOARD_SQUARES) {
if(s.hasPiece() && s.getPiece().getTeamColor().equals(TeamColor.WHITE)) {
Piece p = s.getPiece();
for(int[] position : p.getLegalMoves(p.getPosition())) {
if(hasSquare(position)) {
getSquare(position).protectedByWhite = true;
}
}
}
}
for(Square s : BOARD_SQUARES) {
if(s.hasPiece() && s.getPiece().getTeamColor().equals(TeamColor.BLACK)) {
Piece p = s.getPiece();
for(int[] position : p.getLegalMoves(p.getPosition())) {
if(hasSquare(position)) {
getSquare(position).protectedByBlack = true;
}
}
}
}
}
public static boolean testCheckWhite() {
// Get king position
int[] whiteKingPosition = new int[]{};
for(Square s : BOARD_SQUARES) {
Piece p = s.getPiece();
if(s.hasPiece() && (p.getPieceType()).equals(PieceType.KING)) {
if((p.getTeamColor()).equals(TeamColor.WHITE)) {
whiteKingPosition = p.getPosition();
}
}
}
if(hasSquare(whiteKingPosition) && getSquare(whiteKingPosition).protectedByBlack) {
GameInfoPanel.inCheckWhite.setText("White is in check");
return true;
} else {
GameInfoPanel.inCheckWhite.setText("White is not in check");
return false;
}
}
public static boolean testCheckBlack() {
// Get king position
int[] blackKingPosition = new int[]{};
for(Square s : BOARD_SQUARES) {
Piece p = s.getPiece();
if(s.hasPiece() && (p.getPieceType()).equals(PieceType.KING)) {
if((p.getTeamColor()).equals(TeamColor.BLACK)) {
blackKingPosition = p.getPosition();
}
}
}
if(hasSquare(blackKingPosition) && getSquare(blackKingPosition).protectedByWhite) {
GameInfoPanel.inCheckBlack.setText("Black is in check");
return true;
} else {
GameInfoPanel.inCheckBlack.setText("Black is not in check");
return false;
}
}
Square.java
.... // If a square is clicked that IS colored...
} else {
for(Square s : ChessBoard.BOARD_SQUARES) {
if(s.hasPiece() && (s.getPiece()).getFocus()) {
// Check to make sure that the target square and current
// square are not the same
if(!this.equals(s)) {
movePiece(s);
ChessBoard.setProtectedSquares();
// Test for check
// 1) Find out what color the moved piece is
if((ChessBoard.getTurn()) == TeamColor.WHITE) {
if(ChessBoard.testCheckWhite()) {
// Undo move
s.movePiece(ChessBoard.getSquare(STORED_POSITION));
GameInfoPanel.gameStatus.setText("Illegal move, white in check");
} else if(ChessBoard.testCheckBlack()) {
// Move is okay, black is now in check
GameInfoPanel.gameStatus.setText("Okay move, black in check");
// Switch players' turn
ChessBoard.switchTurn();
} else {
// Move is okay, nothing happened
GameInfoPanel.gameStatus.setText("No one in check");
// Switch players' turn
ChessBoard.switchTurn();
}
} else {
if(ChessBoard.testCheckBlack()) {
// Undo move
s.movePiece(ChessBoard.getSquare(STORED_POSITION));
GameInfoPanel.gameStatus.setText("Illegal move, black in check");
} else if(ChessBoard.testCheckWhite()) {
// Move is okay, white is now in check
GameInfoPanel.gameStatus.setText("Okay move, white in check");
// Switch players' turn
ChessBoard.switchTurn();
} else {
// Move is okay, nothing happened
GameInfoPanel.gameStatus.setText("No one in check");
// Switch players' turn
ChessBoard.switchTurn();
}
}
}
}
}
// Clear all color and focus
ChessBoard.clearFocus();
ChessBoard.setProtectedSquares();
}
I quite understand the algorithm of your code. Unfortunately, I don't see anything wrong with the snippet that you posted.
That's why you should always use Unit Tests while you code. :)
for(Square s : ChessBoard.BOARD_SQUARES) {...}
These will help you in the long run.
However, if you want to solve (hopefully) things quicker, use the debugger mode from your IDE.
Here's a suggested line of investigation. Let's assume this is the scenario: white has checked black and black king can move to another square protected by white.
Based on the code provided and the fact that black (when under check) can move to a square which is protected by white, it must be the case that ChessBoard.testCheckBlack()
method is returning false. Now based on implementation ChessBoard.testCheckBlack()
method, we can conclude that the text
"Black is in check"
must be output on GameInfoPanel
.
If that is correct then following need to be checked, one by one:
hasSquare(blackKingPosition)
getSquare(blackKingPosition).protectedByWhite // just protectedByWhite
It would be great if you could post GameInfoPanel
messages for the scenario above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With