如何编写国际象棋相持规则的代码?

发布于 2024-12-13 03:28:58 字数 72 浏览 0 评论 0原文

我正在尝试编写一个国际象棋游戏,但发现我找不到解决方案来找到僵局。我试图用谷歌搜索,但找不到任何东西。有没有众所周知的算法之类的?

I'm trying to write a chess game and find that I cannot find solutions to find a stalemate situation. I'm trying to google, but can't find anything. Is there a well-known algorithm or something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半步萧音过轻尘 2024-12-20 03:28:58

您的移动生成器将是两种不同设计之一;

  • 要么它在生成移动时检查合法性
  • ,要么生成所有可能的移动并随后删除那些非法的移动。

前者更好,因为它不需要后期处理。

僵局状态就是没有合法的移动并且移动方的国王不受控制的情况。将死条件是指没有合法的移动,但移动方的国王处于受制状态。

换句话说,如果你已经弄清楚如何检测将死和将死,那么你就已经具备了检测僵局所需的一切。

Your move generator will be one of two different designs;

  • either it checks for legality while generating the moves
  • or you generate all possible moves and remove those that are illegal afterwards.

The former is better as it doesn't need post-processing.

A stalemate condition is simply one where there are no legal moves and the moving-side's king is not in check. A checkmate condition is one where there are no legal moves but the moving-side's king is in check.

In other words if you've figured out how to detect check and checkmate, you've already got everything necessary to detect stalemate.

榆西 2024-12-20 03:28:58

这是一个开源代码,包含经典国际象棋游戏的所有规则:
https://github.com/cjortegon/basic-chess

您可以在之后立即运行该项目克隆项目(Android、iOS、桌面和 Web),或者您可以使用主要逻辑,如下所示:https://github.com/ cjortegon/basic-chess/tree/master/libgdx/core/src/com/mountainreacher/chess/model

我的解决方案首先基于 3 矩算法时刻是当玩家从棋盘上选择一个棋子时,然后选择该棋子的目的地时,最后当该棋子到达该位置时(考虑到这是一个动画游戏,如果不是,可以合并步骤2和3) 。

以下代码已用 Java 实现。从模型类的属性来看:

boolean turn;
GenericPiece selected, conquest;
ClassicBoard board;
List<int[]> possibleMovements;
int checkType;

第一个方法将处理时刻 1、2 和特殊的“征服”时刻(仅适用于棋子):

public boolean onCellClick(int row, int column) {
    if (row == -1 && conquest != null) {
        checkType = 0;
        conquest.changeFigure(column);
        return true;
    } else if (selected != null) {
        if (possibleMovements != null) {
            for (int[] move : possibleMovements) {
                if (move[0] == row && move[1] == column) {
                    // Move the PieceActor to the desired position
                    if (selected.moveTo(row, column)) {
                        turn = !turn;
                    }
                    break;
                }
            }
        }
        selected = null;
        possibleMovements = null;
        return true;
    } else {
        selected = board.getSelected(turn ? Piece.WHITE_TEAM : Piece.BLACK_TEAM, row, column);
        if (selected != null) {
            possibleMovements = new ArrayList<>();
            possibleMovements.addAll(((GenericPiece) selected).getMoves(board, false));
            // Checking the movements
            board.checkPossibleMovements(selected, possibleMovements);
            if (possibleMovements.size() == 0) {
                possibleMovements = null;
                selected = null;
                return false;
            } else {
                return true;
            }
        }
    }
    return false;
}

以下方法将处理第三个时刻(当动画结束时):

public void movedPiece(Piece piece) {
    Gdx.app.log(TAG, "movedPiece(" + piece.getType() + ")");

    // Killing the enemy
    Piece killed = board.getSelectedNotInTeam(piece.getTeam(),
            piece.getRow(), piece.getColumn());
    if (killed != null) {
        killed.setAvailable(false);
    }

    // Checking hacks
    GenericPiece[] threat = board.kingIsInDanger();
    if (threat != null) {
        checkType = board.hasAvailableMoves(threat[0].getTeam()) ? CHECK : CHECK_MATE;
    } else {
        checkType = NO_CHECK;
    }

    // Checking castling
    if (piece.getFigure() == Piece.ROOK && ((GenericPiece) piece).getMovesCount() == 1) {
        Piece king = board.getSelected(piece.getTeam(),
                piece.getRow(), piece.getColumn() + 1);
        if (king != null && king.getFigure() == Piece.KING && ((GenericPiece) king).getMovesCount() == 0) {
            // Left Rook
            if (board.getSelected(piece.getRow(), piece.getColumn() - 1) == null) {
                king.moveTo(piece.getRow(), piece.getColumn() - 1);
            }
        } else {
            king = board.getSelected(piece.getTeam(),
                    piece.getRow(), piece.getColumn() - 1);
            if (king != null && king.getFigure() == Piece.KING && ((GenericPiece) king).getMovesCount() == 0) {
                // Right Rook
                if (board.getSelected(piece.getRow(), piece.getColumn() + 1) == null) {
                    king.moveTo(piece.getRow(), piece.getColumn() + 1);
                }
            }
        }
    }

    // Conquest
    else if (piece.getFigure() == Piece.PAWN && (piece.getRow() == 0 || piece.getRow() == board.getRows() - 1)) {
        conquest = (GenericPiece) piece;
        checkType = CONQUEST;
    }
}

该代码涵盖经典国际象棋的所有规则,包括:规则的棋子移动、易位、将棋、将死和棋子的征服。

Here is an Open-source code with all the rules for the classic Chess game:
https://github.com/cjortegon/basic-chess

You can run the project right after cloning the project (Android, iOS, Desktop and Web), or you can use the main logic, which is here: https://github.com/cjortegon/basic-chess/tree/master/libgdx/core/src/com/mountainreacher/chess/model

I based my solution on a 3-moments algorithm, first moment is when the player selects a piece from the board, then when the destination of this piece has been chosen and finally when the piece reaches that position (considering that it is an animated game, if not, you can merge step 2 and 3).

The following code has been implemented in Java. From the properties of the model class:

boolean turn;
GenericPiece selected, conquest;
ClassicBoard board;
List<int[]> possibleMovements;
int checkType;

The first method will handle moments 1, 2 and the special 'conquest' moment (applied to pawn piece only):

public boolean onCellClick(int row, int column) {
    if (row == -1 && conquest != null) {
        checkType = 0;
        conquest.changeFigure(column);
        return true;
    } else if (selected != null) {
        if (possibleMovements != null) {
            for (int[] move : possibleMovements) {
                if (move[0] == row && move[1] == column) {
                    // Move the PieceActor to the desired position
                    if (selected.moveTo(row, column)) {
                        turn = !turn;
                    }
                    break;
                }
            }
        }
        selected = null;
        possibleMovements = null;
        return true;
    } else {
        selected = board.getSelected(turn ? Piece.WHITE_TEAM : Piece.BLACK_TEAM, row, column);
        if (selected != null) {
            possibleMovements = new ArrayList<>();
            possibleMovements.addAll(((GenericPiece) selected).getMoves(board, false));
            // Checking the movements
            board.checkPossibleMovements(selected, possibleMovements);
            if (possibleMovements.size() == 0) {
                possibleMovements = null;
                selected = null;
                return false;
            } else {
                return true;
            }
        }
    }
    return false;
}

And the following method will handle the 3rd moment (when animation finishes):

public void movedPiece(Piece piece) {
    Gdx.app.log(TAG, "movedPiece(" + piece.getType() + ")");

    // Killing the enemy
    Piece killed = board.getSelectedNotInTeam(piece.getTeam(),
            piece.getRow(), piece.getColumn());
    if (killed != null) {
        killed.setAvailable(false);
    }

    // Checking hacks
    GenericPiece[] threat = board.kingIsInDanger();
    if (threat != null) {
        checkType = board.hasAvailableMoves(threat[0].getTeam()) ? CHECK : CHECK_MATE;
    } else {
        checkType = NO_CHECK;
    }

    // Checking castling
    if (piece.getFigure() == Piece.ROOK && ((GenericPiece) piece).getMovesCount() == 1) {
        Piece king = board.getSelected(piece.getTeam(),
                piece.getRow(), piece.getColumn() + 1);
        if (king != null && king.getFigure() == Piece.KING && ((GenericPiece) king).getMovesCount() == 0) {
            // Left Rook
            if (board.getSelected(piece.getRow(), piece.getColumn() - 1) == null) {
                king.moveTo(piece.getRow(), piece.getColumn() - 1);
            }
        } else {
            king = board.getSelected(piece.getTeam(),
                    piece.getRow(), piece.getColumn() - 1);
            if (king != null && king.getFigure() == Piece.KING && ((GenericPiece) king).getMovesCount() == 0) {
                // Right Rook
                if (board.getSelected(piece.getRow(), piece.getColumn() + 1) == null) {
                    king.moveTo(piece.getRow(), piece.getColumn() + 1);
                }
            }
        }
    }

    // Conquest
    else if (piece.getFigure() == Piece.PAWN && (piece.getRow() == 0 || piece.getRow() == board.getRows() - 1)) {
        conquest = (GenericPiece) piece;
        checkType = CONQUEST;
    }
}

That code covers all the rules from the classic chess, including: regular piece movements, castling, check, check-mate and conquests of pawns.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文