This is my minimax method which implements alpha beta pruning and 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;
}
}
As a test game, in my main method I place an X somewhere(X is the player), and then call newminimax499 to see where I should place O(the computer):
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();
}
}
The method returns the position where the computer should play it's O(in this scenario it's 6), so I place O as instructed, play an X for myself, call newminimax499 and run the code again to see where O wants to play and so on and so forth.
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();
}
After this particular run I get the result
Score: 10 Position: 7
Which is good. However, in my GUI this isn't how newminimax gets called. Over there the board doesn't get reset every time a new X or O is placed. If I were to put it in a main method like in the previous examples it would look something like this(keep in mind that it's the exact same sequence of input):
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();
}
Now, when the method is called this way(which is how it's called in the GUI) it returns:
Score: 0 Position: 5
Which means that instead of taking the winning move, it blocked the opponent. After playing a few games this way it became clear that the PC actually loses. So why is it that these 2 ways of calling newminimax499 return different results?
This is how it looks on the GUI:
Note: All methods needed to run the program can be found in this post.