0

I'm trying to do the MinMax for the tic tac toe (Always computer win) but I can't get it to work. All the successors simply return 0 (draw) as score and so the computer always chooses to move in the natural direction of the matrix.

PS: Matrix (class) is the board where they play, that contains an array of 9 positions.

| X | O | X | O | ... | like this.

Global Variable that handles the Tic Tac Toe board is called Main and is an instance of Matrix.

public void minMax(Matrix p) {
  Matrix bestvalue = maxValue(p);
  print(bestvalue);
  System.out.println(bestvalue.getScore());
  main = searchSucessorWithScore(p, bestvalue.getScore());
}

public Matrix maxValue(Matrix p) {
  if(endState(p)) { p.setScore(utility(p)); return p; } //always sets score to       0 but the method utility is correct...
  Matrix bestmove = new Matrix();
  bestmove.setScore(Integer.MIN_VALUE);
  LinkedList<Matrix> list = addSucessors(p, plays.PLAY_X);
  for(Matrix s : list) {
    Matrix move = minValue(s);
    if(move.getScore() > bestmove.getScore()) {
       bestmove = move;
    }
  }
  return bestmove;
}

public Matrix minValue(Matrix p) {
  if(endState(p)) { p.setScore(utility(p)); return p;}
  Matrix bestmove = new Matrix();
  bestmove.setScore(Integer.MAX_VALUE);
  LinkedList<Matrix> list = addSucessors(p, plays.PLAY_O);
  for(Matrix s : list) {
    Matrix move = maxValue(s);
    if(move.getScore() < bestmove.getScore()) { // <
      bestmove = move;
    }
  }
  return bestmove;
}

Auxiliar methods:

public LinkedList<Matrix> addSucessors(Matrix k, plays l) {
  LinkedList<Matrix> list = new LinkedList<Matrix>();
  for(int i=0; i<9; i++) {
  if(k.getRow(i).equals(plays.BLANK)) {
    Matrix p = k.clone();
    p.setRow(i, l);
    list.add(p);
  }
  }
return list;
}

/* RETURNS 0 FOR DRAW, 1 FOR PC WIN, -1 FOR USER WIN */
public int utility(Matrix p) {
  for(int i=0; i<9; i=i+3) {
    if(main.getRow(i).equals(plays.PLAY_X) && main.getRow(i+1).equals(plays.PLAY_X) && main.getRow(i+2).equals(plays.PLAY_X)) return 1;
    if(main.getRow(i).equals(plays.PLAY_O) && main.getRow(i+1).equals(plays.PLAY_O) && main.getRow(i+2).equals(plays.PLAY_O)) return -1;
  }
  for(int i=0; i<3; i++) {
    if(main.getRow(i).equals(plays.PLAY_X) && main.getRow(i+3).equals(plays.PLAY_X) && main.getRow(i+6).equals(plays.PLAY_X)) return 1;
    if(main.getRow(i).equals(plays.PLAY_O) && main.getRow(i+3).equals(plays.PLAY_O) && main.getRow(i+6).equals(plays.PLAY_O)) return -1;
  }
    if(main.getRow(0).equals(plays.PLAY_X) && main.getRow(4).equals(plays.PLAY_X) && main.getRow(8).equals(plays.PLAY_X)) return 1;
    if(main.getRow(2).equals(plays.PLAY_X) && main.getRow(4).equals(plays.PLAY_X) && main.getRow(6).equals(plays.PLAY_X)) return 1;
    if(main.getRow(0).equals(plays.PLAY_O) && main.getRow(4).equals(plays.PLAY_O) &&   main.getRow(8).equals(plays.PLAY_O)) return -1;
    if(main.getRow(2).equals(plays.PLAY_O) && main.getRow(4).equals(plays.PLAY_O) && main.getRow(6).equals(plays.PLAY_O)) return -1;
return 0;
}

public Matrix searchSucessorWithScore(Matrix p, Integer v) {
  for(Matrix s : addSucessors(p, plays.PLAY_X) {
  if(s.getScore() == v) return s;
  }
return null;
}

The method utility is correct, but inside recursion only returns 0 even for matrix's where there's a winner.

Help :D

Pedro Barros
  • 183
  • 1
  • 11
  • I've recently played around with game theory algorithms and implemented 'Tic Tac Toe' and 'Connect Four'. Have a look at https://github.com/winterer/GameTheory – isnot2bad Apr 08 '15 at 19:58
  • and you post the `setScore()` code to make sure that's correct? – dkatzel Apr 08 '15 at 20:00
  • It's correct. It's part of the class Matrix and just does: this.score = score; – Pedro Barros Apr 08 '15 at 20:01
  • well then how does this code ` p.setScore(utility(p));` always set the score to 0 if `utility()` is correct (so you say) – dkatzel Apr 08 '15 at 20:03
  • Because if I print the value of utility(p) and use a random p I made and test with the ones it fails during the algorithm. Utility always prints the correct result. Inside recursion, magic happens... – Pedro Barros Apr 08 '15 at 20:17
  • What do you see if you print out the contents of the matrix inside the utility function in the full program? – Peter de Rivaz Apr 08 '15 at 20:37
  • Shouldn't TicTacToe always end in a draw when both sides play optimally? –  Apr 09 '15 at 08:39
  • Yes, it should. I found the mistake in the utility, now it prints the correct result. What happens now is: whenever I play and computer understands he has no chance of winning he returns the final state, and ends. Still, he plays by the natural order of the cells. It's almost there, but not working yet. Any ideas? – Pedro Barros Apr 09 '15 at 09:12
  • Solved it. In case someone is wondering, the problem was the list where I was checking the score to pick a move, didn't had the score values because I was only saving them inside of the functions max and min. So I declared a global list that saved the moves and scores. – Pedro Barros Apr 09 '15 at 10:37

1 Answers1

0

There is not enough code posted to correctly assess, but this almost never works.

Integer v s.getScore() == v

You should be using Integer.intValue()

Palcente
  • 625
  • 2
  • 7
  • 21
  • good catch. It probably does work in this case since scores should only be -1, 0 and 1 which the JVM caches so boxed/unboxed Integers with those values should always be the same exact reference unless you use `new Integer(1)` – dkatzel Apr 08 '15 at 20:34