2

I have been working on a tic tac toe program in order to better understand how the minimax algorithm works. The following implementation is not working correctly, as the computer can loose the game. If the program is working correctly, than in theory this should be impossible...

Have I made a mistake with the implementation of the minimax, or the getting of the best move?

I have never implemented the algorithm before :s

Evaluation Function

public static int evaluate(char[] board, char turn) {
    if (isWinFor('x', board)) {
        return -1;
    } else if (isWinFor('o', board)) {
        return 1;
    } 
    return 0;
}

Minimax

public static int alphabeta(char[] board, int depth, char turn, int alpha, int beta) {
    if (depth == 0 || gameOver(board)) {
        return evaluate(board, turn);
    } else {
        for (int move : possibleMoves(board)) {
            makeMove(board, turn, move);
            turn = changeTurn(turn);
            int value = alphabeta(board, depth--, turn, alpha, beta);   
            makeMove(board, ' ', move);
            if (turn == 'o') {
                if (value > alpha) {
                    alpha = value;
                }
                if (alpha >= beta) {
                    return beta;
                }
            } else if (turn == 'x') {
                if (value < beta) {
                    beta = value;
                }
                if (beta <= alpha) {
                    return alpha;
                }
            }               
        }
        if (turn == 'o') {
            return  alpha;
        } else {
            return  beta;
        }             
    }
}

Find best move

public static void getBestMove(char[] board, char turn) {
    Random random  = new Random();
    int bestValue = -10000;
    List<Integer> choices = new ArrayList<Integer>();
    for (int move : possibleMoves(board)) {
        makeMove(board, turn, move);
        turn = changeTurn(turn);
        int value = alphabeta(board, 3, turn, -10000, 10000);   
        makeMove(board, ' ', move);
        if (value > bestValue) {
            bestValue = value;
            //start code edit
            choices.clear();
            //end code edit
            choices.add(move);
        } else if (value == bestValue) {
            choices.add(move);
        }
    }
    makeMove(board, turn, choices.get(random.nextInt(choices.size())));
}

Thank you.

user1334130
  • 1,131
  • 3
  • 18
  • 25

2 Answers2

0

It's simple: a perfect player has to search the whole tree to the maximum depth (except for cutoff nodes), but you limited your program to only 4 plies!

There is the mistake in find best move:

int value = alphabeta(board, 3, turn, -10000, 10000);        

just change it to

int value = alphabeta(board, 8, turn, -10000, 10000);
xXliolauXx
  • 1,273
  • 1
  • 11
  • 25
0

Apart from the previous answer, I am pretty sure that your GetBestMove is wrong: you are adding a choice whenever a move is better or equal to your current best one. but you are not actually clearing the list when the best value changes.That means that you will have loosing moves in your choices list.

xXliolauXx
  • 1,273
  • 1
  • 11
  • 25
  • That definitely made a difference. When value > bestValue, I added choices.clear() before I add the new move. Now when I play, if I place two 'x' in a row, the computer will now block me from winning (which it was not doing before), however, if I then line up another two 'x' in a row, it will not block a second time. In the second instance, it appears to favor placing two of its 'o' in a row, rather than blocking me, meaning I can still win. Is there an issue with the scores of the evaluation() function? – user1334130 Aug 30 '15 at 01:17
  • @user1334130 Try to debug, -is your choices list correct when the cp makes a mistake? -are the values correct? Then I can help you maybe. – xXliolauXx Aug 30 '15 at 09:34
  • Having a look at everything and playing a few games, what I can see is the following. If I am playing a game and have two 'x' in a row, the choices array will have the move stored to block me from winning, along with other moves as well (I imagine they must have been rated with the same score), meaning when the computer randomly chooses a move, it sometimes make a bad choice and looses. Ideally, if the computer must block me to prevent a win, this should be the only move available. Here is the tic tac toe code, http://pastebin.com/5RNmj5Pv and gui code http://pastebin.com/BvwYThMA – user1334130 Aug 30 '15 at 11:00
  • @user1334130 tthanks for the code. I haven't found a mistake so far. I would suggest to implement a function to load a position from a file, and then let the CP print all the evaluations for positions with 7 x/os already placed... you should be able to debug it that way... – xXliolauXx Aug 30 '15 at 14:39