这是我的minimax方法,它实现了alpha beta修剪和memoization:
public int[] newminimax499(int a, int b){
int bestPos=-1;
int alpha= a;
int beta= b;
int currentScore;
//boardShow();
String stateString = "";
for (int i=0; i<state.length; i++)
stateString += state[i];
int[] oldAnswer = oldAnswers.get(stateString);
if (oldAnswer != null)
return oldAnswer;
if(isGameOver2()!='N'){
int[] answer = {score(), bestPos};
oldAnswers.put (stateString, answer);
return answer;
}
else{
for(int x:getAvailableMoves()){
if(turn=='O'){ //O is maximizer
setO(x);
//System.out.println(stateID++);
currentScore = newminimax499(alpha, beta)[0];
//revert(x);
if(currentScore>alpha){
alpha=currentScore;
bestPos=x;
}
/*if(alpha>=beta){
break;
}*/
}
else { //X is minimizer
setX(x);
//System.out.println(stateID++);
currentScore = newminimax499(alpha, beta)[0];
//revert(x);
if(currentScore<beta){
beta=currentScore;
bestPos=x;
}
/*if(alpha>=beta)
break;*/
}
revert(x);
if(alpha>=beta)
break;
}
}
if(turn=='O'){
int[] answer = {alpha, bestPos};
oldAnswers.put (stateString, answer);
return answer;
}
else {
int[] answer = {beta, bestPos};
oldAnswers.put (stateString, answer);
return answer;
}
}
作为测试游戏,在我的主要方法中,我将X放置在某处(X是播放器),然后调用newminimax499以查看我应该放置O(计算机)的位置:
public static void main(String[] args) {
State3 s=new State3(3);
int [] result=new int[2];
s.setX(4);
result=s.newminimax499(Integer.MIN_VALUE, Integer.MAX_VALUE);
System.out.println("Score: "+result[0]+" Position: "+ result[1]);
System.out.println("Run time: " + (endTime-startTime));
s.boardShow();
}
}
该方法返回计算机应该播放它的位置(在这种情况下它是6),所以我按照指示放置O,为自己播放X,调用newminimax499并运行代码再看看O想要玩的地方等等。
public static void main(String[] args) {
State3 s=new State3(3);
int [] result=new int[2];
s.setX(4);
s.setO(6);//Position returned from previous code run
s.setX(2);
s.setO(8);//Position returned from previous code run
s.setX(3);
result=s.newminimax499(Integer.MIN_VALUE, Integer.MAX_VALUE);
System.out.println("Score: "+result[0]+" Position: "+ result[1]);
System.out.println("Run time: " + (endTime-startTime));
s.boardShow();
}
在此特定运行后,我得到结果
Score: 10 Position: 7
哪个好。但是,在我的GUI中,这并不是如何调用newminimax。在那里,每次放置新的X或O时,电路板都不会复位。如果我将它放在像前面示例中那样的主方法中,它将看起来像这样(请记住它是完全相同的输入序列):
public static void main(String[] args) {
State3 s=new State3(3);
int [] result=new int[2];
s.setX(4); //Player makes his move
result=s.newminimax499(Integer.MIN_VALUE, Integer.MAX_VALUE);//Where should pc play?
s.setO(result[1]);//PC makes his move
s.setX(2);//Player makes his move
result=s.newminimax499(Integer.MIN_VALUE, Integer.MAX_VALUE);//Where should PC make his move?
s.setO(result[1]);//PC makes his move
s.setX(3);//Player makes his move
result=s.newminimax499(Integer.MIN_VALUE, Integer.MAX_VALUE);
System.out.println("Score: "+result[0]+" Position: "+ result[1]);
System.out.println("Run time: " + (endTime-startTime));
s.boardShow();
}
现在,当以这种方式调用该方法时(它在GUI中调用它的方式),它返回:
Score: 0 Position: 5
这意味着它没有取得胜利的举动,而是阻挡了对手。以这种方式玩了几场游戏后,很明显PC真的输了。那么为什么这两种调用newminimax499的方式会返回不同的结果呢?
这就是它在GUI上的外观:
注意:运行程序所需的所有方法都可以在post中找到。
答案 0 :(得分:1)
这里遇到的问题与使用换位表和alpha beta的国际象棋相同。我必须与你相矛盾,因为它们是不相容的!
正如我之前多次提出的建议,请在尝试实施之前阅读相应的国际象棋程序维基文章!
为了使memo和AB协同工作,你必须为备忘录表中的每个位置保存一个标志,以区分alpha-cut-nodes,beta-cut-nodes和精确节点。
相信我,我从经验中知道他们一起工作;)
答案 1 :(得分:0)
在玩了很多想法之后我终于找到了答案,所以不妨发布它。这里讨论的方法newminimax499正试图实现memoization和alpha beta修剪。出于某种原因,似乎这两个实用程序是不兼容的(或者至少我对这两个实用程序的实现使它们不兼容)。删除与memoization相关的部分后,该方法成为纯alpha beta修剪minimax算法,工作正常,看起来像这样:
public int[] newminimax499(int alpha, int beta){
int bestPos=-1;
int currentScore;
if(isGameOver2()!='N'){
int[] answer = {score(), bestPos};
return answer;
}
else{
for(int x:getAvailableMoves()){
if(turn=='O'){ //O is maximizer
setO(x);
//System.out.println(stateID++);
currentScore = newminimax499(alpha, beta)[0];
if(currentScore>alpha){
alpha=currentScore;
bestPos=x;
}
}
else { //X is minimizer
setX(x);
//System.out.println(stateID++);
currentScore = newminimax499(alpha, beta)[0];
if(currentScore<beta){
beta=currentScore;
bestPos=x;
}
}
revert(x);
if(alpha>=beta)
break;
}
if(turn=='O'){
int[] answer = {alpha, bestPos};
return answer;
}
else {
int[] answer = {beta, bestPos};
return answer;
}
}
}
此方法现在不仅可以工作(不过你在main方法中调用),但它也比带有memoization的minimax快得多。此方法仅需7秒即可在4x4游戏中计算第二步。实现memoization的minimax在大约23秒内计算它。