|
|
@ -60,11 +60,74 @@ class AI {
|
|
|
|
return available_moves[random_index];
|
|
|
|
return available_moves[random_index];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
minimax(matrix, depth, maximizingPlayer) {
|
|
|
|
|
|
|
|
const winner = this.check_winner(matrix);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (winner !== 0) {
|
|
|
|
|
|
|
|
return winner === this.player ? 10 - depth : depth - 10;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (matrix.is_full()) {
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (depth >= this.level) {
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const opponent = 3 - this.player;
|
|
|
|
|
|
|
|
const currentPlayer = maximizingPlayer ? this.player : opponent;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let bestScore = maximizingPlayer ? -Infinity : Infinity;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (let row = 0; row < 3; row++) {
|
|
|
|
|
|
|
|
for (let col = 0; col < 3; col++) {
|
|
|
|
|
|
|
|
if (matrix.cases[row][col] === 0) {
|
|
|
|
|
|
|
|
matrix.mark(row, col, currentPlayer);
|
|
|
|
|
|
|
|
const score = this.minimax(matrix, depth + 1, !maximizingPlayer);
|
|
|
|
|
|
|
|
matrix.cases[row][col] = 0;
|
|
|
|
|
|
|
|
matrix.marked_case--;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bestScore = maximizingPlayer ? Math.max(bestScore, score) : Math.min(bestScore, score);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return bestScore;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
check_winner(matrix) {
|
|
|
|
|
|
|
|
for (let player = 1; player <= 2; player++) {
|
|
|
|
|
|
|
|
if (matrix.check_win(player)) {
|
|
|
|
|
|
|
|
return player;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
move(matrix) {
|
|
|
|
move(matrix) {
|
|
|
|
return this.random_move(matrix);
|
|
|
|
let bestScore = -Infinity;
|
|
|
|
|
|
|
|
let bestMove = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (let row = 0; row < 3; row++) {
|
|
|
|
|
|
|
|
for (let col = 0; col < 3; col++) {
|
|
|
|
|
|
|
|
if (matrix.cases[row][col] === 0) {
|
|
|
|
|
|
|
|
matrix.mark(row, col, this.player);
|
|
|
|
|
|
|
|
const score = this.minimax(matrix, 1, false);
|
|
|
|
|
|
|
|
matrix.cases[row][col] = 0;
|
|
|
|
|
|
|
|
matrix.marked_case--;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (score > bestScore) {
|
|
|
|
|
|
|
|
bestScore = score;
|
|
|
|
|
|
|
|
bestMove = [row, col];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return bestMove;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class Game {
|
|
|
|
class Game {
|
|
|
|