I’ve implemented the minimax algorithm to this tic tac toe game, and it’s working well so far in terms of “Knowing how to win”. However, the computer still can’t figure out how to prevent me from winning it doesn’t see threats that I make it’s merely focused on himself winning.
[As an example, here the computer (X) tried to go for the first-row win, I (O) have placed my first move in the center then went for board0][2] cell preventing the computer’s win. Now I’m only one move away from winning but the computer instead of blocking my win tried going for the first column win.
Here’s the code pen too
In my evaluation function which returns values associated with each move, I’ve assigned values to threats in an attend to encourage the computer to account for threats as well and block them in result. However, it seems like it didn’t work out well.
// 'X' => +10; 'O' => -10;
function evaluate(board) {
// evaluating rows;
for (let i = 0; i < 3; i++) {
if (
board[i][0] == board[i][1] &&
board[i][1] == board[i][2]
) {
if (board[i][0] == AI) {
return +10;
} else if (board[i][0] == player) {
return -10;
}
};
};
// evaluating columns;
for (let j = 0; j < 3; j++) {
if (
board[0][j] == board[1][j] &&
board[1][j] == board[2][j]
) {
if (board[0][j] == AI) {
return +10;
} else if (board[0][j] == player) {
return -10;
}
}
};
// evaluating the diagonals;
if (
board[0][0] == board[1][1] &&
board[1][1] == board[2][2]
) {
if (board[0][0] == AI) {
return +10;
} else if (board[0][0] == player) {
return -10;
}
}
if (
board[0][2] == board[1][1] &&
board[1][1] == board[2][0]
) {
if (board[0][2] == AI) {
return +10;
} else if (board[0][2] == player) {
return -10;
}
}
// detecting row threats;
for (let i = 0; i < 3; i++) {
if (
(board[i][0] == player && board[i][1] == player && board[i][2] == '') ||
(board[i][0] == player && board[i][2] == player && board[i][1] == '') ||
(board[i][1] == player && board[i][2] == player && board[i][0] == '')
) { return -9; }
};
// detection column threats;
for (let j = 0; j < 3; j++) {
if (
(board[0][j] == player && board[1][j] == player && board[2][j] == '') ||
(board[0][j] == player && board[2][j] == player && board[1][j] == '') ||
(board[1][j] == player && board[2][j] == player && board[0][j] == '')
) { return -9; }
};
// detecting diagonal threats;
if ((board[0][0] == player && board[1][1] == player && board[2][2] == '') ||
(board[0][0] == player && board[2][2] == player && board[1][1] == '') ||
(board[1][1] == player && board[2][2] == player && board[0][0] == '')
) { return -9; };
if ((board[0][2] == player && board[1][1] == player && board[2][0] == '') ||
(board[0][2] == player && board[2][0] == player && board[1][1] == '') ||
(board[1][1] == player && board[2][0] == player && board[0][2] == '')
) { return -9; }
// if none then:
return 0;
};
3