You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java国际象棋机器人开发:如何判断棋子能否移动阻挡将军?

国际象棋机器人开发:将军阻挡判断问题

项目架构

  • Board:存储Square二维数组、所有Square和Piece实例,所有字段设为静态以减少getter方法;包含多个ArrayList:白方合法移动、黑方合法移动、白方所有移动、黑方所有移动、白方所有棋子、黑方所有棋子。
  • Square:存储Piece对象。
  • Piece及其子类:包含两个ArrayList:moveset(空棋盘下当前位置的所有理论可移动格子,用于处理牵制)和seen squares(不碰到己方棋子时的所有可达格子);King类包含boolean类型的inCheck字段。
  • Move:接收Piece和Square参数,通过play()方法处理实际移动逻辑、更新格子上的棋子等。

当前逻辑流程

每次移动后调用Board的vision()方法:

  1. 更新所有棋子的moveset和seen squares,设置King的inCheck状态;
  2. 将所有理论可行移动加入all moves集合;
  3. 筛选符合将军规则的合法移动,加入legal moves集合。

核心难点

将军状态下的合法移动判断:

  • 已实现逻辑:若King处于将军状态,King自身的移动合法;
  • 未解决问题:如何判断其他棋子的移动能否阻挡将军(需同时处理棋子牵制、双将等场景)。

已尝试方案

  • 尝试判断己方棋子是否能看到将军方棋子所在格子(方向正确,但未找到具体实现方式);
  • 尝试编写方法返回造成将军的棋子列表,但无实质性进展。

现有代码

vision()方法

public static void vision() {
    // updateBoardVision是所有Piece子类的重写方法,重新评估当前位置的所有理论可行移动及可达格子
    for (Piece p : whitePieces) {
        p.updateBoardVision();
    }

    for (Piece p : blackPieces) {
        p.updateBoardVision();
    }
    
    // 若白方棋子能看到黑王所在格子,标记黑王处于将军状态
    for (Piece p : whitePieces) {
        if (p.seenSquares.contains(Board.bK.square)) {
            Board.bK.setInCheck(true);
        }
    }
    
    // 反之,标记白王的将军状态
    for (Piece p : blackPieces) {
        if (p.seenSquares.contains(Board.wK.square)) {
            Board.wK.setInCheck(true);
        }
    }
    
    // 收集所有理论可行移动(暂不考虑将军规则)
    for (Piece p : whitePieces) {
        for (Square s : p.seenSquares) {
            Move m = new Move(p, s);
            allWhiteMoves.add(m);
        }
    }
    
    for (Piece p : blackPieces) {
        for (Square s : p.seenSquares) {
            Move m = new Move(p, s);
            allBlackMoves.add(m);
        }
    }
    
    // 先将所有移动标记为非法
    for (Move wm : allWhiteMoves) {
        wm.setValid(false);
    }
    
    for (Move bm : allBlackMoves) {
        bm.setValid(false);
    }
    
    for (Move aWhiteMove : allWhiteMoves) {
        // 白王处于将军状态时
        if (wK.isInCheck()) {
            // 王的移动合法
            if (aWhiteMove.getPiece().equals(wK)) {
                aWhiteMove.setValid(true);
            }
            
            // 此处未实现:判断己方棋子移动能否阻挡将军,及处理双将逻辑
            // 后续需为黑方实现同样逻辑
        }
    }
    
    // 收集最终合法移动
    for (Move r : allWhiteMoves) {
        if (r.isValid()) {
            whiteLegalMoves.add(r);
        }
    }
    
    for (Move s : allBlackMoves) {
        if (s.isValid()) {
            blackLegalMoves.add(s);
        }
    }
}

查找将军棋子的方法

// 返回造成白王将军的黑方棋子列表(支持多子同时将军)
public static ArrayList<Piece> findCheckPieceWhite() {
    ArrayList<Piece> checkPieces = new ArrayList();
    
    for (Piece p : blackPieces) {
        if (p.seenSquares.contains(wK.square)) {
            checkPieces.add(p);
        }
    }
    
    return checkPieces;
}

// 返回造成黑王将军的白方棋子列表
public static ArrayList<Piece> findCheckPieceBlack() {
    ArrayList<Piece> checkPieces = new ArrayList();
    
    for (Piece p : whitePieces) {
        if (p.seenSquares.contains(bK.square)) {
            checkPieces.add(p);
        }
    }
    
    return checkPieces;
}

解决思路与代码优化

1. 明确将军场景的合法应对规则

  • 单将:三种合法解法:王移动到安全位置、吃掉将军棋子、移动棋子阻挡将军(仅针对车、象、后这类远程棋子);
  • 双将:仅有一种合法解法:王移动到安全位置(无法同时阻挡或吃掉两个将军棋子)。

2. 核心逻辑实现

在vision()方法的将军处理部分,加入以下逻辑:

// 获取造成白王将军的黑方棋子列表
ArrayList<Piece> checkingPieces = findCheckPieceWhite();

// 处理单将场景
if (checkingPieces.size() == 1) {
    Piece checker = checkingPieces.get(0);
    Square kingSquare = wK.square;
    Square checkerSquare = checker.square;
    
    // 获取将军棋子与王之间的路径格子(仅远程棋子有可阻挡路径)
    List<Square> checkPath = getCheckPath(checkerSquare, kingSquare);
    
    for (Move aWhiteMove : allWhiteMoves) {
        Square targetSquare = aWhiteMove.getTargetSquare();
        
        // 情况1:移动棋子吃掉将军棋子
        if (targetSquare.equals(checkerSquare)) {
            if (isMoveSafeForKing(aWhiteMove)) {
                aWhiteMove.setValid(true);
            }
        }
        // 情况2:移动棋子阻挡将军(仅远程将军且路径存在)
        else if (!checkPath.isEmpty() && checkPath.contains(targetSquare)) {
            if (isMoveSafeForKing(aWhiteMove)) {
                aWhiteMove.setValid(true);
            }
        }
    }
}
// 双将场景:仅王的移动可能合法,已在上文处理
else if (checkingPieces.size() > 1) {
    // 无需额外操作,仅保留王的移动合法性
}

3. 辅助方法实现

获取将军路径的方法

// 获取远程将军棋子与被将军王之间的所有中间格子
public static List<Square> getCheckPath(Square from, Square to) {
    List<Square> path = new ArrayList<>();
    Piece checker = from.getPiece();
    
    // 非远程棋子(马、兵)无阻挡路径
    if (!(checker instanceof Rook || checker instanceof Bishop || checker instanceof Queen)) {
        return path;
    }
    
    int fromX = from.getX();
    int fromY = from.getY();
    int toX = to.getX();
    int toY = to.getY();
    
    // 横向路径(车/后)
    if (fromX == toX) {
        int step = (toY > fromY) ? 1 : -1;
        for (int y = fromY + step; y != toY; y += step) {
            path.add(Board.squares[fromX][y]);
        }
    }
    // 纵向路径(车/后)
    else if (fromY == toY) {
        int step = (toX > fromX) ? 1 : -1;
        for (int x = fromX + step; x != toX; x += step) {
            path.add(Board.squares[x][fromY]);
        }
    }
    // 斜线路径(象/后)
    else if (Math.abs(fromX - toX) == Math.abs(fromY - toY)) {
        int xStep = (toX > fromX) ? 1 : -1;
        int yStep = (toY > fromY) ? 1 : -1;
        int x = fromX + xStep;
        int y = fromY + yStep;
        while (x != toX && y != toY) {
            path.add(Board.squares[x][y]);
            x += xStep;
            y += yStep;
        }
    }
    
    return path;
}

验证移动是否让王脱离将军的方法

// 模拟移动后检查王是否处于安全状态
public static boolean isMoveSafeForKing(Move move) {
    // 保存当前棋盘状态
    Piece originalTargetPiece = move.getTargetSquare().getPiece();
    Square originalPieceSquare = move.getPiece().getSquare();
    
    // 模拟执行移动
    move.play();
    
    // 检查王是否仍处于将军状态
    boolean isSafe = !wK.isInCheck();
    
    // 恢复原棋盘状态
    move.getPiece().setSquare(originalPieceSquare);
    move.getTargetSquare().setPiece(originalTargetPiece);
    // 重新更新视野以恢复状态
    vision();
    
    return isSafe;
}

内容的提问来源于stack exchange,提问作者deprexit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 00:47:53