【问题标题】:Is there a way to speed up a "detect check" method in chess?有没有办法加快国际象棋中的“检测检查”方法?
【发布时间】:2018-12-25 18:33:29
【问题描述】:

我正在开发一个 JavaFX 国际象棋应用程序,并且我正在尝试实现一种方法来检测黑白国王是否在检查中。它可以工作,但即使我只在用户每次移动一块时调用它,它仍然极大地滞后于应用程序。它通过检测相反颜色的所有可能移动来工作,然后检查这些移动中是否有任何移动处于国王的位置。有没有什么方法可以做出更高效的方法?

private boolean getCheck(String colour) {
    ArrayList<int[]> totalMoves = new ArrayList<int[]>();
    ArrayList<int[]> pieceMoves = new ArrayList<int[]>();

    int kingRow = 0;
    int kingColumn = 0;

    if (colour.equals("BLACK")) {
        for (int i = 0; i < chessPieces.size(); i++) {
            if (chessPieces.get(i).getPiece().equals("BLACKKING")) {
                kingRow = chessPieces.get(i).getRow();
                kingColumn = chessPieces.get(i).getColumn();
            }
        }

        for (int i = 0; i < chessPieces.size(); i++) {
            if (chessPieces.get(i).getPiece().contains("WHITE")) {
                pieceMoves = showPossibleMoves(new int[]{
                        chessPieces.get(i).getColumn(),
                        chessPieces.get(i).getRow()
                    }, chessPieces);

                for (int j = 0; j < pieceMoves.size(); j++) {
                    if (pieceMoves.get(j)[1] == kingRow && pieceMoves.get(j)[0] == kingColumn) {
                        return true;
                    }
                }
            }
        }
    } else if (colour.equals("WHITE")) {
        for (int i = 0; i < chessPieces.size(); i++) {
            if (chessPieces.get(i).getPiece().equals("WHITEKING")) {
                kingRow = chessPieces.get(i).getRow();
                kingColumn = chessPieces.get(i).getColumn();
            }
        }

        for (int i = 0; i < chessPieces.size(); i++) {
            if (chessPieces.get(i).getPiece().contains("BLACK")) {
                pieceMoves = showPossibleMoves(new int[]{
                        chessPieces.get(i).getColumn(),
                        chessPieces.get(i).getRow()
                    }, chessPieces);

                for (int j = 0; j < pieceMoves.size(); j++) {
                    if (pieceMoves.get(j)[1] == kingRow && pieceMoves.get(j)[0] == kingColumn) {
                        return true;
                    }
                }
            }
        }
    }

    return false;
}

【问题讨论】:

  • 如果需要更多信息,请告诉我,例如 showPossibleMoves() 方法。

标签: java javafx


【解决方案1】:

你可以从每个国王的位置开始,扫描马的移动,垂直、水平和对角线,寻找合适的对手棋子来控制国王。这应该会导致比所有可能的移动更小的扫描。

【讨论】:

  • 太棒了!我刚刚实现了它,而且效果很好。谢谢! :D
【解决方案2】:

我在这里看到了几个潜在的瓶颈。

每个 for 循环都会经历每次迭代。在你找到国王之后休息,并且在你找到攻击它的棋子之后休息。

另外,你是如何计算移动的?这也可能影响性能。如果您每回合计算一次可能的移动 + 棋子位置列表,并简单地在某处保留对它的引用,您可以避免大量昂贵的重新计算。

还有其他潜在的运行时瓶颈,但如果不查看有关您的移动计算算法甚至您设计国际象棋程序的方式的更多详细信息,就不可能知道。

为了进一步参考,Chess Programming wiki 有很多关于国际象棋编程的精彩文章。您可能会发现checks 上的页面也很有用,因为有多种检查检测方法。我个人更喜欢(并且曾经使用过)使用 attack and defend maps 即时计算支票,因为它很直观,我相信 Chess.js 会做类似的事情。

【讨论】:

    【解决方案3】:

    我很确定已经有一个(最佳)算法可以解决这个问题。虽然我会建议我在必要时解决这个问题的方法。如果您想尽快检测到检查,我相信明智的做法是预先计算并将工作划分到电路板的单元中。您可能想知道“我怎样才能做到这一点?”,那么每次一块移动它标志着一块威胁的领土呢?

    假设这是我们的 Cell 类:

    public class Cell{
        private ArrayList<Piece> whiteThreats = new ArrayList<>(); 
        private ArrayList<Piece> blackThreats = new ArrayList<>();
        ...
    }
    

    上面的班级将有 2 个ArrayList 将持有威胁单元格的碎片。多块可以威胁一个细胞和两侧(白色和黑色)。现在每一个棋子移动应该执行两个动作:

    1. 找到受到当前 Piece 威胁的单元格并从其列表中删除引用。

    2. 找到并标记现在受到威胁的新单元格,并添加对其列表的引用。

    通过这样做,每个部件都应该立即知道单元格是否安全,这可以通过检查ArrayList(用于适当的颜色)是否为空来轻松验证。如果对方队伍的ArrayList 里面至少有一个物体(这意味着大小大于零),则意味着对方队伍威胁到这个单元格。所以国王现在可以在 O(1) 时间内检测到检查。

    【讨论】:

      【解决方案4】:

      不是您问题的答案,但在此处添加一个中断会阻止您在此阶段检查不必要的部分。我猜最耗时的部分是在每件作品上调用 showPossibleMoves。

                for (int i = 0; i < chessPieces.size(); i++) {
                      if (chessPieces.get(i).getPiece().equals("BLACKKING")) {
                          kingRow = chessPieces.get(i).getRow();
                          kingColumn = chessPieces.get(i).getColumn();
                          break;
                      }
                 }
      

      【讨论】:

      • 是的,这是主要问题,因为这也是我为每个单独的游戏片段获取可能移动的方式。它适用于一件作品,但不适用于 16 次迭代。尽管我没有意识到这就是 break 在 Java 中所做的。很有帮助,谢谢。
      猜你喜欢
      • 2022-06-17
      • 1970-01-01
      • 1970-01-01
      • 2013-05-24
      • 2011-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多