我创建了一个checkress游戏,我希望计算机计算最佳移动。 这是我到目前为止所做的:
public BoardS calcNextMove(BoardS bs)
{
ArrayList<BoardS>options = calcPossibleOptions(bs);
int max = -1;
int temp;
int bestMove = 0;
for(int k=0;k<options.size();k++)
{
temp = calculateNextMove2(options.get(k));
if(max<temp)
{
max = temp;
bestMove = k;
}
}
return options.get(bestMove);
}
public int calculateNextMove2(BoardS bs)
{
int res = soWhoWon(bs);
if(res == 2) //pc won(which is good so we return 1)
return 1;
if(res == 1)
return 0;
ArrayList<BoardS>options = calcPossibleOptions(bs);
int sum = 0;
for(int k=0;k<options.size();k++)
{
sum += calculateNextMove2(options.get(k));
}
return sum;
}
我一直在
线程“AWT-EventQueue-0”中的异常java.lang.StackOverflowError
calcPossibleOptions效果很好,它是一个返回所有可能选项的数组的函数。
BoardS是一个代表游戏板的clas。
我想我必须提高效率,怎么做?
答案 0 :(得分:0)
你需要找到MinMax的替代品,即使最有可能使用alpha-beta修剪,因为电路板太大会导致太多可能的移动和反向移动。这会导致堆栈溢出。
我很惊讶地看到为Tic-Tac-Toe制作完整的决策树并没有让我自己溢出,但我担心我对人工智能规划或其他解决这些问题的算法不够了解,除此之外帮助你。
答案 1 :(得分:0)
“calculateNextMove2()”的递归运行得太深,这就是为什么你得到一个StackOverFlow。如果你期望游戏运行到最后(除非相对接近实际的胜利),这可能需要很长时间。像国际象棋一样(我有更多的经验)一个引擎可能会走20步之前,你可能会用它到目前为止发现的东西。如果你从国际象棋游戏开始运行它......它可以在当前的技术上运行100年(并且仍然无法说出获胜的第一步是什么)。也许只是尝试10或20个深度? (这仍将击败大多数人 - 并且仍然可能被归类为“最佳动作”)。与国际象棋一样,你很难评估一个位置是好还是坏的工作(通常计算为物质优势和位置优势的组合)。这是棘手的部分。注意:Project Chinook已经完成了你想要实现的目标 - 它已经“击败”了Checkers的游戏(国际象棋没有这样的东西存在编辑:Magnus Carslen已经为所有意图和目的“贬低”游戏:D)。
见:Alpha-beta pruning (这可能会有所帮助)
这里还有一篇关于这个主题的(旧)论文:
Graham Owen 1997 Search Algorithms and Game Playing (可能有用)
同时请注意,返回导致“胜利”的第一步是“天真” - 因为它可能是一个完全不可思议的移动线,如果他们不参加非常特别的比赛,对手将获得优势 - 例如为傻瓜交配伴侣或学者在国际象棋中交配...(快速但非常轻微)