Сейчас я программирую игру в шахматы. Я хочу отметить все возможные ходы фигуры, если щелкну по ней. Чтобы ход был законным, он должен следовать за движением фигуры, находиться в границах шахматной доски и быть безопасным для собственного короля. Моя проблема связана с последним. Потому что, чтобы определить, атакует ли фигура короля после хода, вам придется смоделировать ее, а затем проверить, может ли что-то атаковать короля. но если просто обновить все возможные ходы и посмотреть, не атакует ли что-нибудь короля после симуляции, вы получите бесконечную рекурсию. Мой единственный способ заключался в том, чтобы иметь дополнительную переменную (canAttackKing // после хода) и метод, подобный тому, который определяет возможные ходы, только без проверки, безопасно ли это. По этой причине у меня есть методы canAttack и canAttack2 и так далее. Это просто раздражает и с этим трудно справиться. Постоянно возникают какие-то ошибки и т. д. Итак, мой вопрос: есть ли лучший способ определить, безопасен ли ход, чем просто просмотреть список всех вражеских фигур и посмотреть, может ли что-нибудь атаковать короля в точках x, y, как я это делаю? прямо сейчас?
Все Pieces имеют разные классы, которые наследуют класс Piece следующим образом:
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
@Setter
protected boolean canAttackKing = false; // If something else Moves
public Piece(boolean white) {
this.white = white;
this.image = loadImage();
}
private Image loadImage() {
String color = white ? "white" : "black";
String className = this.getClass().getSimpleName().toLowerCase();
String imagePath = "/Images/figuren/" + color + "_" + className + ".png";
return new Image(Objects.requireNonNull(getClass().getResourceAsStream(imagePath)));
}
public void setPosition(int x, int y) {
this.x = x;
this.y = y;
}
public abstract void setPossibleMoves();
public abstract void updateCanAttackKing2();
public abstract String getFenNotation();
public boolean canAttackKing() {
return canAttackKing;
}
protected void addMoveIfSafe(int x, int y) {
if (c.simMovePiece(x, y, this)) {
possibleMoves[x][y] = c.getPiece(x, y) == null ? 1 : 2;
}
}
protected void checkDiagonals() {
c = Chessboard.getInstance();
int originalX = x;
int originalY = y;
checkLine(originalX, originalY, 1, 1); // Top-right
checkLine(originalX, originalY, -1, -1); // Bottom-left
checkLine(originalX, originalY, -1, 1); // Top-left
checkLine(originalX, originalY, 1, -1); // Bottom-right
}
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;
checkLine2(originalX, originalY, 1, 1); // Top-right
checkLine2(originalX, originalY, -1, -1); // Bottom-left
checkLine2(originalX, originalY, -1, 1); // Top-left
checkLine2(originalX, originalY, 1, -1); // Bottom-right
}
protected void checkStraights2() {
c = Chessboard.getInstance();
int originalX = x;
int originalY = y;
checkLine2(originalX, originalY, 1, 0); // Right
checkLine2(originalX, originalY, -1, 0); // Left
checkLine2(originalX, originalY, 0, 1); // Up
checkLine2(originalX, originalY, 0, -1); // Down
}
private void checkLine2(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) == 2) {
if (c.getBoard()[newX][newY] instanceof King) {
canAttackKing = true;
}
break;
}
}
}
}
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[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[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[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;
}
}
Подробнее здесь: https://stackoverflow.com/questions/793 ... me-in-java
Как проверить, безопасен ли ход в шахматах для шахматной игры на Java? [закрыто] ⇐ JAVA
Программисты JAVA общаются здесь
1735382255
Anonymous
Сейчас я программирую игру в шахматы. Я хочу отметить все возможные ходы фигуры, если щелкну по ней. Чтобы ход был законным, он должен следовать за движением фигуры, находиться в границах шахматной доски и быть безопасным для собственного короля. Моя проблема связана с последним. Потому что, чтобы определить, атакует ли фигура короля после хода, вам придется смоделировать ее, а затем проверить, может ли что-то атаковать короля. но если просто обновить все возможные ходы и посмотреть, не атакует ли что-нибудь короля после симуляции, вы получите бесконечную рекурсию. Мой единственный способ заключался в том, чтобы иметь дополнительную переменную (canAttackKing // после хода) и метод, подобный тому, который определяет возможные ходы, только без проверки, безопасно ли это. По этой причине у меня есть методы canAttack и canAttack2 и так далее. Это просто раздражает и с этим трудно справиться. Постоянно возникают какие-то ошибки и т. д. Итак, мой вопрос: есть ли лучший способ определить, безопасен ли ход, чем просто просмотреть список всех вражеских фигур и посмотреть, может ли что-нибудь атаковать короля в точках x, y, как я это делаю? прямо сейчас?
Все Pieces имеют разные классы, которые наследуют класс Piece следующим образом:
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
@Setter
protected boolean canAttackKing = false; // If something else Moves
public Piece(boolean white) {
this.white = white;
this.image = loadImage();
}
private Image loadImage() {
String color = white ? "white" : "black";
String className = this.getClass().getSimpleName().toLowerCase();
String imagePath = "/Images/figuren/" + color + "_" + className + ".png";
return new Image(Objects.requireNonNull(getClass().getResourceAsStream(imagePath)));
}
public void setPosition(int x, int y) {
this.x = x;
this.y = y;
}
public abstract void setPossibleMoves();
public abstract void updateCanAttackKing2();
public abstract String getFenNotation();
public boolean canAttackKing() {
return canAttackKing;
}
protected void addMoveIfSafe(int x, int y) {
if (c.simMovePiece(x, y, this)) {
possibleMoves[x][y] = c.getPiece(x, y) == null ? 1 : 2;
}
}
protected void checkDiagonals() {
c = Chessboard.getInstance();
int originalX = x;
int originalY = y;
checkLine(originalX, originalY, 1, 1); // Top-right
checkLine(originalX, originalY, -1, -1); // Bottom-left
checkLine(originalX, originalY, -1, 1); // Top-left
checkLine(originalX, originalY, 1, -1); // Bottom-right
}
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;
checkLine2(originalX, originalY, 1, 1); // Top-right
checkLine2(originalX, originalY, -1, -1); // Bottom-left
checkLine2(originalX, originalY, -1, 1); // Top-left
checkLine2(originalX, originalY, 1, -1); // Bottom-right
}
protected void checkStraights2() {
c = Chessboard.getInstance();
int originalX = x;
int originalY = y;
checkLine2(originalX, originalY, 1, 0); // Right
checkLine2(originalX, originalY, -1, 0); // Left
checkLine2(originalX, originalY, 0, 1); // Up
checkLine2(originalX, originalY, 0, -1); // Down
}
private void checkLine2(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) == 2) {
if (c.getBoard()[newX][newY] instanceof King) {
canAttackKing = true;
}
break;
}
}
}
}
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;
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79311600/how-to-check-if-a-move-is-safe-in-chess-for-a-chess-game-in-java[/url]
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Как узнать, что какой-то ход является допустимым для моей шахматной партии? [закрыто]
Anonymous » » в форуме JAVAСейчас я программирую игру в шахматы. Я хочу отметить все возможные ходы фигуры, если щелкну по ней. Чтобы ход был законным, он должен следовать за движением фигуры, находиться в границах шахматной доски и быть безопасным для собственного короля.... - 0 Ответы
- 17 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Создаю игру «Крестики-нолики», но ход второго игрока пропускается, если он делает неправильный ход в заполненной строке.
Anonymous » » в форуме PythonВо-первых, я все еще новичок в программировании, поэтому, пожалуйста, не ругайте меня за то, что я что-то делаю неправильно. Все в коде — это то, чему я научился на уроках.
Итак, я создал игру «Крестики-нолики», и, как сказано в названии, ход... - 0 Ответы
- 54 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Как узнать, что какой-то ход является допустимым для моей шахматной партии?
Anonymous » » в форуме JAVAСейчас я программирую игру в шахматы. Я хочу отметить все возможные ходы фигуры, если щелкну по ней. Чтобы ход был законным, он должен следовать за движением фигуры, находиться в границах шахматной доски и быть безопасным для собственного короля.... - 0 Ответы
- 15 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Фигуры в графическом интерфейсе шахматной игры не видны в Java Swing
Anonymous » » в форуме JAVAВ настоящее время я работаю над Java-проектом, реализуя правила игры в шахматы в существующем скелетном коде, который предоставляет мне шахматную игровую доску и основную функцию. Как вы можете видеть в моем следующем коде, он состоит из двух... - 0 Ответы
- 21 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Как сохранить ход игры в памяти сервера в веб-API ASP.NET Core 8?
Anonymous » » в форуме C#Например, в игре есть кнопка, на которую нажимает авторизованный пользователь. Я хочу сохранить эти клики в памяти на сервере, чтобы пользователь не пропустил их, и после 10 кликов предоставить пользователю кнопку для сохранения их в базе данных.
Я... - 0 Ответы
- 14 Просмотры
-
Последнее сообщение Anonymous
-
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...