如何编写国际象棋僵局规则?

时间:2011-10-31 06:16:41

标签: chess

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

2 个答案:

答案 0 :(得分:9)

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

  • 要么在生成动作时检查合法性
  • 或者您生成所有可能的移动并删除之后非法的移动。

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

僵持状态只是一个没有合法动作且移动方的国王受到检查的情况。一个将死的情况是没有合法行动,但移动方的国王 正在检查中。

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

答案 1 :(得分:2)

这是一个开源代码,包含经典国际象棋游戏的所有规则: 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;
}

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

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;
    }
}

该代码涵盖了经典国际象棋的所有规则,包括:常规棋子移动,铸造,检查,检查配对和棋子征服。