Сейчас я программирую игру в шахматы. Я хочу отметить все возможные ходы фигуры, если щелкну по ней. Чтобы ход был законным, он должен следовать за движением фигуры, находиться в границах шахматной доски и быть безопасным для собственного короля. Моя проблема связана с последним. Потому что, чтобы определить, атакует ли фигура короля после хода, вам придется смоделировать ее, а затем проверить, может ли что-то атаковать короля. но если просто обновить все возможные ходы и посмотреть, не атакует ли что-нибудь короля после симуляции, вы получите бесконечную рекурсию. Мой единственный способ заключался в том, чтобы иметь дополнительную переменную (canAttackKing // после хода) и метод, подобный тому, который определяет возможные ходы, только без проверки, безопасно ли это. По этой причине у меня есть методы canAttack и canAttack2 и так далее. Это просто раздражает и с этим трудно справиться. Постоянно возникают какие-то ошибки и т. д. Итак, мой вопрос: есть ли лучший способ определить, безопасен ли ход, чем просто просмотреть список всех вражеских фигур и посмотреть, может ли что-нибудь атаковать короля в точках x, y, как я это делаю? прямо сейчас?
Все Pieces имеют разные классы, которые наследуют класс Piece следующим образом:
import schach.SchachScreen.Chessboard;
import schach.SchachScreen.SchachScreenPresenter;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class Pawn extends Piece {
private boolean moved = false;
private int direction;
public Pawn(boolean white) {
super(white);
direction = isWhite() ? -1 : 1; // White moves up (negative), Black moves down (positive)
}
@Override
public String getFenNotation() {
return isWhite() ? "P" : "p"; // Return "P" for white, "p" for black
}
@Override
public void setPossibleMoves() {
c = Chessboard.getInstance();
possibleMoves = new int[8][8]; // Initialize the move matrix
checkMoveForward(); // Regular move forward by one
checkInitialDoubleMove(); // First move double-step
checkEnPassant(); // En Passant
checkDiagonalCaptures(); // Diagonal captures
}
private void checkMoveForward() {
if (c.check(x, y + direction, this) == 1) {
addMoveIfSafe(x, y + direction); // Regular forward move if the square is empty
}
}
private void checkInitialDoubleMove() {
if (!moved && c.check(x, y + 2 * direction, this) == 1
&& c.check(x, y + direction, this) == 1) {
addMoveIfSafe(x, y + 2 * direction); // Double move on first move if both squares are free
}
}
private void checkDiagonalCaptures() {
if (c.getPiece(x + 1, y + direction) != null
&& c.check(x + 1, y + direction, this) == 2) {
addMoveIfSafe(x + 1, y + direction); // Capture to the right
}
if (c.getPiece(x - 1, y + direction) != null
&& c.check(x - 1, y + direction, this) == 2) {
addMoveIfSafe(x - 1, y + direction); // Capture to the left
}
}
private void checkEnPassant() {
// En Passant to the right (if valid)
if (SchachScreenPresenter.convertToChessNotation(x + 1, y + direction)
.equals(c.getPossibleEnPassant()) && c.getPiece(x + 1, y) instanceof Pawn) {
addEnPassantIfSafe(true); // Right side en passant
}
// En Passant to the left (if valid)
else if (SchachScreenPresenter.convertToChessNotation(x - 1, y + direction)
.equals(c.getPossibleEnPassant()) && c.getPiece(x - 1, y) instanceof Pawn) {
addEnPassantIfSafe(false); // Left side en passant
}
}
private void addEnPassantIfSafe(boolean right) {
if (c.simEnPassant(this, right)) {
// En Passant capture move is represented as `5` in the move matrix
possibleMoves[x + (right ? 1 : -1)][y + direction] = 5;
}
}
@Override
public void updateCanAttackKing2() {
canAttackKing = false;
c = Chessboard.getInstance();
int x = getX();
int y = getY();
checkKingAttack(x + 1, y + direction); // Check for possible attack on the right diagonal
checkKingAttack(x - 1, y + direction); // Check for possible attack on the left diagonal
}
private void checkKingAttack(int x, int y) {
if (c.check(x, y, this) == 2 && c.getPiece(x, y) instanceof King) {
canAttackKing = true; // Mark as can attack king if the square is occupied by the opposing king
}
}
}
import schach.figuren.*;
import javafx.scene.shape.MoveTo;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
@Getter
@Setter
public class Chessboard {
private boolean gameRunning = true;
private Piece[][] board = new Piece[8][8];
private List
whitePieces = new ArrayList();
private List blackPieces = new ArrayList();
private int moveCounter;
private boolean whiteTurn;
private King whiteKing, blackKing;
private Piece selectedPiece = null;
private static Chessboard instance;
private String possibleEnPassant;
//fifty move rule and threefold repetition rule
private int fiftyMoveCounter; // 1 Move consists of both Players making a move, therefore this variable has to reach 100 for a draw
private List boardStates;
private Chessboard() {
fiftyMoveCounter = 0;
possibleEnPassant = "-";
moveCounter = 0;
whiteTurn = true;
boardStates = new ArrayList();
}
public static Chessboard getInstance() {
if (instance == null) {
instance = new Chessboard();
}
return instance;
}
public static void resetInstance() {
instance = new Chessboard();
}
public void initializeBoard() {
board = new Piece[8][8];
whiteTurn = true;
moveCounter = 0;
selectedPiece = null;
// Place white pieces at the bottom
addPiece(new Rook(true), 0, 7);
addPiece(new Knight(true), 1, 7);
addPiece(new Bishop(true), 2, 7);
addPiece(new Queen(true), 3, 7);
addPiece(new King(true), 4, 7);
addPiece(new Bishop(true), 5, 7);
addPiece(new Knight(true), 6, 7);
addPiece(new Rook(true), 7, 7);
for (int i = 0; i < 8; i++) {
addPiece(new Pawn(true), i, 6);
}
// Place black pieces at the top
addPiece(new Rook(false), 0, 0);
addPiece(new Knight(false), 1, 0);
addPiece(new Bishop(false), 2, 0);
addPiece(new Queen(false), 3, 0);
addPiece(new King(false), 4, 0);
addPiece(new Bishop(false), 5, 0);
addPiece(new Knight(false), 6, 0);
addPiece(new Rook(false), 7, 0);
for (int i = 0; i < 8; i++) {
addPiece(new Pawn(false), i, 1);
}
whiteKing = (King) board[4][7];
blackKing = (King) board[4][0];
updatePossibleMoves();
}
// Generates a valid FEN string for UCI compatibility
public String getFen() {
StringBuilder fen = new StringBuilder();
fen.append(getBoardState());
fen.append(' ').append(isWhiteTurn() ? 'w' : 'b');
fen.append(' ').append(getCastlingRights());
fen.append(' ').append(possibleEnPassant);
fen.append(' ').append(fiftyMoveCounter);
fen.append(' ').append((moveCounter / 2) + 1);
return fen.toString();
}
private String getCastlingRights() {
StringBuilder rights = new StringBuilder();
if (!whiteKing.isMoved()) {
if (!isRookMoved(7, 7)) rights.append('K');
if (!isRookMoved(0, 7)) rights.append('Q');
}
if (!blackKing.isMoved()) {
if (!isRookMoved(7, 0)) rights.append('k');
if (!isRookMoved(0, 0)) rights.append('q');
}
return rights.length() > 0 ? rights.toString() : "-";
}
private boolean isRookMoved(int x, int y) {
Piece rook = board[x][y];
return !(rook instanceof Rook) || ((Rook) rook).isMoved();
}
public void updateGameState(Piece piece, Piece capturedPiece, boolean doubleMove) {
whiteTurn = !whiteTurn;
moveCounter++;
selectedPiece = null;
switch (piece) {
case Pawn pawn -> {
pawn.setMoved(true);
if (doubleMove) {
possibleEnPassant = SchachScreenPresenter.convertToChessNotation(piece.getX(),
piece.getY() + (pawn.isWhite() ? 1 : -1));
}
else {
possibleEnPassant = "-";
}
}
case King king -> {
king.setMoved(true);
possibleEnPassant = "-";
}
case Rook rook -> {
rook.setMoved(true);
possibleEnPassant = "-";
}
default -> { possibleEnPassant = "-";
}
}
updatePossibleMoves();
if (piece instanceof Pawn || capturedPiece != null) {
fiftyMoveCounter = 0;
} else {
fiftyMoveCounter++;
}
boardStates.add(getBoardState());
}
public String getBoardState() {
StringBuilder boardState = new StringBuilder();
for (int y = 0; y < 8; y++) {
int emptyCount = 0;
for (int x = 0; x < 8; x++) {
Piece piece = board[x][y];
if (piece == null) {
emptyCount++;
} else {
if (emptyCount > 0) {
boardState.append(emptyCount);
emptyCount = 0;
}
boardState.append(piece.getFenNotation());
}
}
if (emptyCount > 0) {
boardState.append(emptyCount);
}
if (y < 7) {
boardState.append('/');
}
}
return boardState.toString();
}
private boolean checkThreefoldRepetition() {
int count = 0;
String currentState = getBoardState();
for (String state : boardStates) {
if (state.equals(currentState)) {
count++;
}
}
return count >= 3;
}
public void addPiece(Piece piece, int x, int y) {
board[x][y] = piece;
piece.setPosition(x, y);
if(piece.isWhite()){
whitePieces.add(piece);
}else{
blackPieces.add(piece);
}
}
public void removePiece(Piece piece) {
int x = piece.getX();
int y = piece.getY();
piece.setPosition(-1, -1);
board[x][y] = null;
if(piece.isWhite()){
whitePieces.remove(piece);
}else{
blackPieces.remove(piece);
}
}
//returns 0 if the move is invalid, 1 if the move is valid, 2 if the move is a valid capture
public int check(int x, int y, Piece piece) {
if (x < 0 || x >= 8 || y < 0 || y >= 8) {
return 0; // Out of bounds
}
Piece targetPiece = board[x][y];
if (targetPiece == null) {
return 1; // Empty square
} else if (targetPiece.isWhite() != piece.isWhite()) {
return 2; // Opponent's piece
} else {
return 0; // Own piece
}
}
public boolean isInCheck(King king, int i) {
if (i == 1) {
return canAttack(king.getX(), king.getY(), !king.isWhite());
} else {
return canAttack2(king.getX(), king.getY(), !king.isWhite());
}
}
public boolean canAttack(int targetX, int targetY, boolean isWhite) {
List pieces = isWhite ? whitePieces : blackPieces;
for (Piece piece : pieces) {
int cell = piece.getPossibleMoves()[targetX][targetY];
if (cell == 2) {
System.out.println("Piece: " + piece.getFenNotation() + SchachScreenPresenter.convertToChessNotation(piece.getX(), piece.getY())
+ " can attack: " + SchachScreenPresenter.convertToChessNotation(targetX, targetY));
return true;
}
}
return false;
}
public boolean isSquareSafe(int targetX, int targetY, boolean isWhite){
List pieces = isWhite ? whitePieces : blackPieces;
for (Piece piece : pieces) {
int cell = piece.getPossibleMoves()[targetX][targetY];
if (cell == 2 || (cell == 1) && !(piece instanceof Pawn)) {
System.out.println("Piece: " + piece.getFenNotation() + SchachScreenPresenter.convertToChessNotation(piece.getX(), piece.getY())
+ " can attack: " + SchachScreenPresenter.convertToChessNotation(targetX, targetY));
return false;
}
}
return true;
}
public boolean canAttack2(int x, int y, boolean isWhite) {
List pieces = isWhite ? whitePieces : blackPieces;
for (Piece piece : pieces) {
if (piece.canAttackKing()) {
return true;
}
}
return false;
}
public void movePiece(int x, int y, Piece piece) {
int[] originalPosition = new int[]{piece.getX(), piece.getY()};
Piece capturedPiece = null;
// Clear the target position
if (board[x][y] != null) {
capturedPiece = board[x][y];
removePiece(capturedPiece);
}
// Execute the move
addPiece(piece, x, y);
board[originalPosition[0]][originalPosition[1]] = null;
updateGameState(piece, capturedPiece,
y - originalPosition[1] == 2 || y - originalPosition[1] == -2);
}
public boolean simMovePiece(int x, int y, Piece piece) {
if (moveCounter < 3) return true;
boolean isSafe = true;
// Save original position
int[] originalPosition = new int[]{piece.getX(), piece.getY()};
Piece targetedPiece = board[x][y];
// Simulate move
addPiece(piece, x, y);
board[originalPosition[0]][originalPosition[1]] = null;
if (targetedPiece != null) {
removePiece(targetedPiece);
}
// Update possible King attacks for opponent pieces after the Move of the piece
updatePossibleMoves2(piece);
// Check if the king is in check
if (isInCheck(getKing(piece.isWhite()), 2)) {
isSafe = false;
}
// Revert move
addPiece(piece, originalPosition[0], originalPosition[1]);
if (targetedPiece != null) {
addPiece(targetedPiece, x, y);
} else {
board[x][y] = null;
}
return isSafe;
}
public boolean simEnPassant(Pawn pawn, boolean right) {
int startX = pawn.getX();
int startY = pawn.getY();
int endX = pawn.getX() + (right ? 1 : -1);
int endY = pawn.getY() + (pawn.isWhite() ? -1 : 1);
Pawn capturedPawn = (Pawn) board[endX][endY - (pawn.isWhite() ? -1 : 1)];
boolean isSafe = true;
// Simulate move
addPiece(pawn, endX, endY);
board[startX][startY] = null;
removePiece(capturedPawn);
// Update possible King attacks for opponent pieces after the move of the piece
updatePossibleMoves2(pawn);
// Check if the king is in check
if (isInCheck(getKing(pawn.isWhite()), 2)) {
isSafe = false;
}
// Revert move
addPiece(pawn, startX, startY);
addPiece(capturedPawn, endX,endY - (pawn.isWhite() ? -1 : 1)); // Restore the en passant captured pawn
board[endX][endY] = null;
return isSafe;
}
public String checkForEnd(){
//Check for fifty move rule
if(fiftyMoveCounter >= 100){
return "Fifty move rule";
}
if (checkThreefoldRepetition()) {
return "Threefold repetition rule";
}
//Check for checkmate or stalemate
boolean check = isInCheck(getKing(whiteTurn),1);
boolean possibleMoveExists = false;
for(int i = 0; i < 8; i++){
for(int j = 0; j < 8; j++){
Piece piece = board[i][j];
if(piece != null && piece.isWhite() == whiteTurn){
for(int k = 0; k < 8; k++){
for(int l = 0; l < 8; l++){
if(piece.getPossibleMoves()[k][l] != 0){
possibleMoveExists = true;
}
}
}
}
}
}
if(!possibleMoveExists){
if(check){
return "Checkmate";
}else{
return "Stalemate";
}
}
return "";
}
public void castle(King king, boolean kingside) {
int y = king.getY();
int x = king.getX();
int rookX = kingside ? 7 : 0;
int newKingX = kingside ? 6 : 2;
int newRookX = kingside ? 5 : 3;
// Move the king and rook to their new positions
addPiece(king, newKingX, y);
addPiece(board[rookX][y], newRookX, y);
// Clear the old positions
board[x][y] = null;
board[rookX][y] = null;
updateGameState(king, null, false);
}
public void enPassant(Pawn pawn, int x, int y) {
int direction = pawn.isWhite() ? -1 : 1;
board[x][y - direction] = null;
movePiece(x, y, pawn);
}
public King getKing(boolean isWhite) {
return isWhite ? whiteKing : blackKing;
}
public void updatePossibleMoves() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
Piece piece = board[i][j];
if (piece != null) {
piece.setPossibleMoves();
}
}
}
}
public void updatePossibleMoves2(Piece exception) {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
Piece piece = board[i][j];
if (piece != null) {
if (piece.isWhite() != exception.isWhite()) {
piece.updateCanAttackKing2();
}
}
}
}
}
public Piece getPiece(int x, int y) {
if(x > 7 || x < 0 || y > 7 || y < 0) return null;
return board[x][y];
}
public void setPiece(int x, int y, Piece piece) {
board[x][y] = piece;
}
public Piece promotePawn(Pawn pawn, String pieceType, int newX, int newY) {
Piece capturedPiece = board[newX][newY];
Piece newPiece = switch (pieceType) {
case "Queen" -> new Queen(pawn.isWhite());
case "Rook" -> new Rook(pawn.isWhite());
case "Bishop" -> new Bishop(pawn.isWhite());
case "Knight" -> new Knight(pawn.isWhite());
default -> null;
};
if (newPiece != null) {
removePiece(pawn);
addPiece(newPiece, newX, newY);
}
updateGameState(pawn, capturedPiece, false);
return newPiece;
}
}
Как я уже говорил, я пытался проверить, безопасно ли перемещение, с помощью дополнительной переменной и методов, но то, как оно запрограммировано сейчас, очень неясно/сбивает с толку/трудно работать.
В какой-то момент это работало, но как только я начинал что-то добавлять или изменять, оно всегда полностью ломалось.
Сейчас я программирую игру в шахматы. Я хочу отметить все возможные ходы фигуры, если щелкну по ней. Чтобы ход был законным, он должен следовать за движением фигуры, находиться в границах шахматной доски и быть безопасным для собственного короля. Моя проблема связана с последним. Потому что, чтобы определить, атакует ли фигура короля после хода, вам придется смоделировать ее, а затем проверить, может ли что-то атаковать короля. но если просто обновить все возможные ходы и посмотреть, не атакует ли что-нибудь короля после симуляции, вы получите бесконечную рекурсию. Мой единственный способ заключался в том, чтобы иметь дополнительную переменную (canAttackKing // после хода) и метод, подобный тому, который определяет возможные ходы, только без проверки, безопасно ли это. По этой причине у меня есть методы canAttack и canAttack2 и так далее. Это просто раздражает и с этим трудно справиться. Постоянно возникают какие-то ошибки и т. д. Итак, мой вопрос: есть ли лучший способ определить, безопасен ли ход, чем просто просмотреть список всех вражеских фигур и посмотреть, может ли что-нибудь атаковать короля в точках x, y, как я это делаю? прямо сейчас? Все Pieces имеют разные классы, которые наследуют класс Piece следующим образом: [code]import lombok.Getter; import javafx.scene.image.Image; import schach.SchachScreen.Chessboard; import lombok.Setter;
import java.util.Objects;
@Getter public abstract class Piece { private final boolean white; protected int x,y; private final Image image; protected Chessboard c;
@Setter protected int[][] possibleMoves = new int[8][8]; // 0 = no move, 1 = move, 2 = capture
protected void checkStraights() { c = Chessboard.getInstance(); int originalX = x; int originalY = y;
checkLine(originalX, originalY, 1, 0); // Right checkLine(originalX, originalY, -1, 0); // Left checkLine(originalX, originalY, 0, 1); // Up checkLine(originalX, originalY, 0, -1); // Down }
private void checkLine(int startX, int startY, int xIncrement, int yIncrement) { for (int i = 1; startX + i * xIncrement < 8 && startX + i * xIncrement >= 0 && startY + i * yIncrement < 8 && startY + i * yIncrement >= 0; i++) { int newX = startX + i * xIncrement; int newY = startY + i * yIncrement; if (c.check(newX, newY, this) == 0) break; addMoveIfSafe(newX, newY); if (c.check(newX, newY, this) == 2) break; } }
// 2cnd Step (It doesn't have to check if its safe, // if it attacks the King its over before the other player can move) protected void checkDiagonals2() { c = Chessboard.getInstance(); int originalX = x; int originalY = y;
@Setter @Getter public class Pawn extends Piece { private boolean moved = false; private int direction;
public Pawn(boolean white) { super(white); direction = isWhite() ? -1 : 1; // White moves up (negative), Black moves down (positive) }
@Override public String getFenNotation() { return isWhite() ? "P" : "p"; // Return "P" for white, "p" for black }
@Override public void setPossibleMoves() { c = Chessboard.getInstance(); possibleMoves = new int[8][8]; // Initialize the move matrix
checkMoveForward(); // Regular move forward by one checkInitialDoubleMove(); // First move double-step checkEnPassant(); // En Passant checkDiagonalCaptures(); // Diagonal captures }
private void checkMoveForward() { if (c.check(x, y + direction, this) == 1) { addMoveIfSafe(x, y + direction); // Regular forward move if the square is empty } }
private void checkInitialDoubleMove() { if (!moved && c.check(x, y + 2 * direction, this) == 1 && c.check(x, y + direction, this) == 1) { addMoveIfSafe(x, y + 2 * direction); // Double move on first move if both squares are free } }
private void checkDiagonalCaptures() { if (c.getPiece(x + 1, y + direction) != null && c.check(x + 1, y + direction, this) == 2) { addMoveIfSafe(x + 1, y + direction); // Capture to the right } if (c.getPiece(x - 1, y + direction) != null && c.check(x - 1, y + direction, this) == 2) { addMoveIfSafe(x - 1, y + direction); // Capture to the left } }
private void checkEnPassant() { // En Passant to the right (if valid) if (SchachScreenPresenter.convertToChessNotation(x + 1, y + direction) .equals(c.getPossibleEnPassant()) && c.getPiece(x + 1, y) instanceof Pawn) { addEnPassantIfSafe(true); // Right side en passant } // En Passant to the left (if valid) else if (SchachScreenPresenter.convertToChessNotation(x - 1, y + direction) .equals(c.getPossibleEnPassant()) && c.getPiece(x - 1, y) instanceof Pawn) { addEnPassantIfSafe(false); // Left side en passant } }
private void addEnPassantIfSafe(boolean right) { if (c.simEnPassant(this, right)) { // En Passant capture move is represented as `5` in the move matrix possibleMoves[x + (right ? 1 : -1)][y + direction] = 5; } }
@Override public void updateCanAttackKing2() { canAttackKing = false; c = Chessboard.getInstance(); int x = getX(); int y = getY();
checkKingAttack(x + 1, y + direction); // Check for possible attack on the right diagonal checkKingAttack(x - 1, y + direction); // Check for possible attack on the left diagonal }
private void checkKingAttack(int x, int y) { if (c.check(x, y, this) == 2 && c.getPiece(x, y) instanceof King) { canAttackKing = true; // Mark as can attack king if the square is occupied by the opposing king } } } [/code] [code]import schach.figuren.*; import javafx.scene.shape.MoveTo; import lombok.Getter; import lombok.Setter;
private Piece[][] board = new Piece[8][8]; private List whitePieces = new ArrayList(); private List blackPieces = new ArrayList();
private int moveCounter; private boolean whiteTurn; private King whiteKing, blackKing; private Piece selectedPiece = null;
private static Chessboard instance;
private String possibleEnPassant;
//fifty move rule and threefold repetition rule private int fiftyMoveCounter; // 1 Move consists of both Players making a move, therefore this variable has to reach 100 for a draw private List boardStates;
public String getBoardState() { StringBuilder boardState = new StringBuilder(); for (int y = 0; y < 8; y++) { int emptyCount = 0; for (int x = 0; x < 8; x++) { Piece piece = board[x][y]; if (piece == null) { emptyCount++; } else { if (emptyCount > 0) { boardState.append(emptyCount); emptyCount = 0; } boardState.append(piece.getFenNotation()); } } if (emptyCount > 0) { boardState.append(emptyCount); } if (y < 7) { boardState.append('/'); } } return boardState.toString(); }
private boolean checkThreefoldRepetition() { int count = 0; String currentState = getBoardState(); for (String state : boardStates) { if (state.equals(currentState)) { count++; } } return count >= 3; }
public void addPiece(Piece piece, int x, int y) { board[x][y] = piece; piece.setPosition(x, y); if(piece.isWhite()){ whitePieces.add(piece); }else{ blackPieces.add(piece); } } public void removePiece(Piece piece) { int x = piece.getX(); int y = piece.getY(); piece.setPosition(-1, -1); board[x][y] = null; if(piece.isWhite()){ whitePieces.remove(piece); }else{ blackPieces.remove(piece); } }
//returns 0 if the move is invalid, 1 if the move is valid, 2 if the move is a valid capture public int check(int x, int y, Piece piece) { if (x < 0 || x >= 8 || y < 0 || y >= 8) { return 0; // Out of bounds } Piece targetPiece = board[x][y]; if (targetPiece == null) { return 1; // Empty square } else if (targetPiece.isWhite() != piece.isWhite()) { return 2; // Opponent's piece } else { return 0; // Own piece } }
public boolean isInCheck(King king, int i) { if (i == 1) { return canAttack(king.getX(), king.getY(), !king.isWhite()); } else { return canAttack2(king.getX(), king.getY(), !king.isWhite()); } }
public boolean canAttack(int targetX, int targetY, boolean isWhite) { List pieces = isWhite ? whitePieces : blackPieces; for (Piece piece : pieces) { int cell = piece.getPossibleMoves()[targetX][targetY]; if (cell == 2) { System.out.println("Piece: " + piece.getFenNotation() + SchachScreenPresenter.convertToChessNotation(piece.getX(), piece.getY()) + " can attack: " + SchachScreenPresenter.convertToChessNotation(targetX, targetY)); return true; } } return false; }
public boolean isSquareSafe(int targetX, int targetY, boolean isWhite){ List pieces = isWhite ? whitePieces : blackPieces; for (Piece piece : pieces) { int cell = piece.getPossibleMoves()[targetX][targetY]; if (cell == 2 || (cell == 1) && !(piece instanceof Pawn)) { System.out.println("Piece: " + piece.getFenNotation() + SchachScreenPresenter.convertToChessNotation(piece.getX(), piece.getY()) + " can attack: " + SchachScreenPresenter.convertToChessNotation(targetX, targetY)); return false; } } return true; }
public boolean canAttack2(int x, int y, boolean isWhite) { List pieces = isWhite ? whitePieces : blackPieces; for (Piece piece : pieces) { if (piece.canAttackKing()) { return true; } } return false; }
public void movePiece(int x, int y, Piece piece) { int[] originalPosition = new int[]{piece.getX(), piece.getY()};
Piece capturedPiece = null;
// Clear the target position if (board[x][y] != null) { capturedPiece = board[x][y]; removePiece(capturedPiece); }
// Execute the move addPiece(piece, x, y); board[originalPosition[0]][originalPosition[1]] = null;
updateGameState(piece, capturedPiece, y - originalPosition[1] == 2 || y - originalPosition[1] == -2); }
public boolean simMovePiece(int x, int y, Piece piece) { if (moveCounter < 3) return true; boolean isSafe = true;
// Save original position int[] originalPosition = new int[]{piece.getX(), piece.getY()}; Piece targetedPiece = board[x][y];
public void castle(King king, boolean kingside) { int y = king.getY(); int x = king.getX(); int rookX = kingside ? 7 : 0; int newKingX = kingside ? 6 : 2; int newRookX = kingside ? 5 : 3;
// Move the king and rook to their new positions addPiece(king, newKingX, y); addPiece(board[rookX][y], newRookX, y);
// Clear the old positions board[x][y] = null; board[rookX][y] = null;
updateGameState(king, null, false); }
public void enPassant(Pawn pawn, int x, int y) { int direction = pawn.isWhite() ? -1 : 1; board[x][y - direction] = null; movePiece(x, y, pawn); }
public King getKing(boolean isWhite) { return isWhite ? whiteKing : blackKing; }
public void updatePossibleMoves() { for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { Piece piece = board[i][j]; if (piece != null) { piece.setPossibleMoves(); } } }
} public void updatePossibleMoves2(Piece exception) { for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { Piece piece = board[i][j]; if (piece != null) { if (piece.isWhite() != exception.isWhite()) { piece.updateCanAttackKing2(); } } } } }
public Piece getPiece(int x, int y) { if(x > 7 || x < 0 || y > 7 || y < 0) return null; return board[x][y]; } public void setPiece(int x, int y, Piece piece) { board[x][y] = piece; }
public Piece promotePawn(Pawn pawn, String pieceType, int newX, int newY) { Piece capturedPiece = board[newX][newY];
Piece newPiece = switch (pieceType) { case "Queen" -> new Queen(pawn.isWhite()); case "Rook" -> new Rook(pawn.isWhite()); case "Bishop" -> new Bishop(pawn.isWhite()); case "Knight" -> new Knight(pawn.isWhite()); default -> null; }; if (newPiece != null) { removePiece(pawn); addPiece(newPiece, newX, newY); } updateGameState(pawn, capturedPiece, false);
return newPiece; } }
[/code] Как я уже говорил, я пытался проверить, безопасно ли перемещение, с помощью дополнительной переменной и методов, но то, как оно запрограммировано сейчас, очень неясно/сбивает с толку/трудно работать. В какой-то момент это работало, но как только я начинал что-то добавлять или изменять, оно всегда полностью ломалось.