1

I added these 3 variable to make operation of finding the winner in O(1) time.

private final int[] rowSum, colSum;
private int diagSum;
private int revDiagSum;

rowSum array contains sum of each row in n * n board, similary colSum contains column sums and diagSum and revDiagSum contains sum in diagonal and reverse diagonal.

Min-Max logic : // returns an array containing { x, y, score } // n is board.size here.

private int[] minMax(int player, final int n) {
    // At max level --> human's turn | At min level --> Computer's turn 
    // MIN == -1 | MAX == +1

    int best[] = null;
    if(player == MIN) {
        best = new int[] {-1, -1, Integer.MAX_VALUE};
    }
    else if(player == MAX) {
        best = new int[] {-1, -1, Integer.MIN_VALUE};
    }

    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            if(board.get(i, j) == 0) {

                int win = tryMove(i, j, player);

                int []score = null;
                if((win != 0) || board.filled()) {
                    // if this is the last move we can play in game, score is calculated.
                    score = new int[] {i, j, win};
                }
                else {
                    score = minMax(-1 * player, n);
                }

                undoMove(i, j, player);

                if(player == MIN) {
                    if(score[2] < best[2]) {
                        best[0] = i;
                        best[1] = j;
                        best[2] = score[2];
                    }
                }
                else if(player == MAX) {
                    if(score[2] > best[2]) {
                        best[0] = i;
                        best[1] = j;
                        best[2] = score[2];
                    }
                }
            }
        }
    }

    // return the optimal move(with score) player(=computer/human) can play by making a move.
    return best;
}

private int tryMove(int i, int j, int player) {
    int n = board.getSize();
    board.set(i, j, player);
    rowSum[i] += player;
    colSum[j] += player;
    if(i == j)
        diagSum += player;
    if(i + j == n - 1)
        revDiagSum += player;
    // if any of the sum == (+n / -n) means player won.
    if(rowSum[i] == Math.abs(n) || colSum[j] == Math.abs(n) || diagSum == Math.abs(n) || revDiagSum == Math.abs(n)) {
        return player;
    }
    return 0;
}

private int undoMove(int i, int j, int player) {
    int n = board.getSize();
    board.set(i, j, 0);
    rowSum[i] -= player ;
    colSum[j] -= player;
    if(i == j)
        diagSum -= player;
    if(i + j == n - 1)
        revDiagSum -= player;
    return 0;
}

I call the above Min-Max func() always like this :

int[] move = minMax(-1, n); // always consider computer as the min-player and human as max player.

Now the issue I am facing is, whenever I am running this Game, I ("Human") am able to beat the computer which should not happen in the ideal case as PC plays optimal moves everytime against us.

Tried debugging, but couldn't figure what's the issue here.

As per the logic, I am not able to suspect the issue in code.

Complete Code: https://github.com/tusharRawat821/Tic-Tac-Toe

Bug Fixed:

Below piece of code should be updated:

if(rowSum[i] == Math.abs(n) || colSum[j] == Math.abs(n) || diagSum == Math.abs(n) || revDiagSum == Math.abs(n)) {
....}

Corrected if condition :

    if(Math.abs(rowSum[i]) == n || Math.abs(colSum[j]) == n || Math.abs(diagSum) == n || Math.abs(revDiagSum) == n) {
....}
tusharRawat
  • 719
  • 10
  • 24

0 Answers0