Java 在基于时间的解决方案中,消除国际象棋中无趣/输线的最佳方法?
我正在用Java创建一个国际象棋引擎作为练习,我知道由于速度问题,不建议使用它,但我只是为了练习 在使用Java 在基于时间的解决方案中,消除国际象棋中无趣/输线的最佳方法?,java,chess,minimax,Java,Chess,Minimax,我正在用Java创建一个国际象棋引擎作为练习,我知道由于速度问题,不建议使用它,但我只是为了练习 在使用alpha-beta修剪实现minimax后,我考虑实施一个时间限制来查找给定移动的分数 这是密码 private int minimax(MoveNode node, MoveNodeType nodeType, int alpha, int beta, Side side, int depth) throws Exception { // isInteresting
alpha-beta修剪实现minimax
后,我考虑实施一个时间限制来查找给定移动的分数
这是密码
private int minimax(MoveNode node, MoveNodeType nodeType, int alpha, int beta, Side side, int depth) throws Exception {
// isInterestingLine(prevscores, node, side);
if (depth <= 0) {
count++;
return node.evaluateBoard(side);
}
// Generate Child nodes if we haven't.
if (node.childNodes == null || node.childNodes.size() == 0) {
node.createSingleChild();
}
if (nodeType == MoveNodeType.MAX) {
int bestValue = -1000;
for (int i = 0; i < node.childNodes.size(); i++) {
if (node.childNodes.get(i) == null) continue;
int value = minimax(node.childNodes.get(i), MoveNodeType.MIN, alpha, beta, side, depth - 1);
bestValue = Math.max(bestValue, value);
alpha = Math.max(alpha, bestValue);
if (beta <= alpha) {
break;
}
node.createSingleChild();
}
// reCalculateScore();
return bestValue;
} else {
int bestValue = 1000;
for (int i = 0; i < node.childNodes.size(); i++) {
if (node.childNodes.get(i) == null) continue;
int value = minimax(node.childNodes.get(i), MoveNodeType.MAX, alpha, beta, side, depth - 1);
bestValue = Math.min(bestValue, value);
beta = Math.min(beta, bestValue);
if (beta <= alpha) {
break;
}
node.createSingleChild();
}
// reCalculateScore();
return bestValue;
}
}
这就是我执行时间限制的方式
long time = System.currentTimeMillis();
moveEvaluator.evaluateMove(move, board.clone());
while((System.currentTimeMillis() - time) < secToCalculate*1000 && !moveEvaluator.minmaxThread.isAlive()) {
}
System.out.println("Time completed! score = " + moveEvaluator.bestMoveScore + " move = " + move + " depth = " + moveEvaluator.searchDepth) ;
callback.callback(move, moveEvaluator.bestMoveScore);
但是,没有一个解决方案是完美和有效的,在第一个方案中,我们只是猜测,在第二个方案中,我们不止一次地计算一个节点
有更好的方法吗 每个国际象棋引擎使用的解决方案都是
不要搜索到一个固定的深度(在你的例子中是MAX_depth),你先搜索到一个深度,然后当这个搜索完成后,你再开始搜索两个深度,然后继续像这样增加深度,直到你没有时间为止。当您超时时,您可以播放上次完成搜索的移动
看起来很多时间都花在了较低深度的迭代上,这些迭代后来被更深入的搜索所取代,而且发送的时间完全丢失了,但实际上并非如此。由于搜索深度N比搜索深度N-1要长得多,因此,在较低深度搜索上花费的时间总是比在最后一次(较深)搜索上花费的时间少得多
如果您的引擎使用换位表,则来自上一次迭代的换位表中的数据将有助于后续迭代。alpha-beta算法的性能对搜索顺序非常敏感。当首先搜索最佳移动时,alpha-beta优于minimax节省的时间是最佳的。如果在搜索深度N之前搜索深度N-1,则换位表可能会包含对大多数位置的最佳移动的良好猜测,然后可以首先搜索这些位置
实际上,在使用换位表并基于上一次迭代在根位置排序移动的引擎中,使用迭代深化比不使用迭代深化更快。我的意思是,举例来说,先进行深度1搜索,然后进行深度2搜索,再进行深度3搜索,直到深度10搜索,比立即进行深度10搜索要快。此外,您还可以选择随时停止搜索,并且仍有移动游戏,=。每个国际象棋引擎使用的解决方案都是
不要搜索到一个固定的深度(在你的例子中是MAX_depth),你先搜索到一个深度,然后当这个搜索完成后,你再开始搜索两个深度,然后继续像这样增加深度,直到你没有时间为止。当您超时时,您可以播放上次完成搜索的移动
看起来很多时间都花在了较低深度的迭代上,这些迭代后来被更深入的搜索所取代,而且发送的时间完全丢失了,但实际上并非如此。由于搜索深度N比搜索深度N-1要长得多,因此,在较低深度搜索上花费的时间总是比在最后一次(较深)搜索上花费的时间少得多
如果您的引擎使用换位表,则来自上一次迭代的换位表中的数据将有助于后续迭代。alpha-beta算法的性能对搜索顺序非常敏感。当首先搜索最佳移动时,alpha-beta优于minimax节省的时间是最佳的。如果在搜索深度N之前搜索深度N-1,则换位表可能会包含对大多数位置的最佳移动的良好猜测,然后可以首先搜索这些位置
实际上,在使用换位表并基于上一次迭代在根位置排序移动的引擎中,使用迭代深化比不使用迭代深化更快。我的意思是,举例来说,先进行深度1搜索,然后进行深度2搜索,再进行深度3搜索,直到深度10搜索,比立即进行深度10搜索要快。此外,您还可以选择随时停止搜索,并且仍有移动游戏,=
long time = System.currentTimeMillis();
moveEvaluator.evaluateMove(move, board.clone());
while((System.currentTimeMillis() - time) < secToCalculate*1000 && !moveEvaluator.minmaxThread.isAlive()) {
}
System.out.println("Time completed! score = " + moveEvaluator.bestMoveScore + " move = " + move + " depth = " + moveEvaluator.searchDepth) ;
callback.callback(move, moveEvaluator.bestMoveScore);