我正在开发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;
}
答案 0 :(得分:3)
您可以从每个国王的位置开始,垂直,水平和对角扫描骑士移动,以寻找适当的对手来控制国王,这将导致扫描小于所有可能的移动。< / p>
答案 1 :(得分:2)
我在这里看到的潜在瓶颈。
每个for循环都会经历每个迭代。找到国王后以及找到攻击它的碎片后就休息。
此外,您如何计算移动量?这也会影响性能。如果您每转一次计算可能移动+零件位置的列表,并仅在某处保留该位置的引用,就可以避免进行大量昂贵的重新计算。
还有其他潜在的运行时瓶颈,但是如果不了解有关移动计算算法甚至国际象棋程序设计方式的更多细节,就不可能知道。
作为进一步参考,Chess Programming wiki上有很多关于国际象棋编程的精彩文章。您可能会发现checks上的页面也很有用,因为存在多种检查检测方法。由于其直观性,我个人更喜欢(并且已经使用)使用attack and defend maps动态计算支票,并且我相信Chess.js会执行类似的操作。
答案 2 :(得分:1)
我很确定已经有一个(最佳)算法。尽管我将建议我必须解决的方法。如果您想尽快检测到支票,我相信明智的做法是预先计算并将工作划分为董事会的单元。您可能想知道“我如何实现这一目标?”,每当一件物品移动时,它将标志着该物品威胁的领域如何?
我们假设这是我们的Cell类:
public class Cell{
private ArrayList<Piece> whiteThreats = new ArrayList<>();
private ArrayList<Piece> blackThreats = new ArrayList<>();
...
}
上面的类将有2个ArrayList
,其中包含威胁单元格的碎片。多个碎片可以威胁一个牢房,并且对双方都有威胁(白色和黑色)。现在,每次移动都应执行两个动作:
找到受到当前棋子威胁的牢房,并从它们的列表中删除引用。
查找并标记现在构成威胁的新单元格,并为其列表添加引用。
这样做,每个部件都应该立即知道该单元格是否安全,这可以通过检查ArrayList
(对于适当的颜色)是否为空来轻松地进行验证。如果对手团队的ArrayList
内部有至少一个物体(这意味着大小大于零),则意味着对手团队威胁了该单元格。这样国王现在就可以检测到O(1)时间的支票了。
答案 3 :(得分:0)
不是您所遇到问题的答案,但在此处添加一个空格可以防止您在此阶段检查不必要的内容。我猜想最耗时的部分是在每件作品上都调用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;
}
}