我正在尝试使用针对Java中n个网格大小的minimax算法来实现Tic-Tac-Toe游戏。
我已经完全从 geeksforgeeks 复制了该算法,但是在Javascript中并没有预期的结果,而且有些奇怪的事情超出了我的理解。
我正在调用函数computerTurn(moves)
以使计算机移动,并在其中调用函数getBestMove(gridArr, depth, isMax, moves)
以通过minimax算法获得最佳移动。
在这两个函数中,我首先检查网格中的空单元格,然后为其指定特定的转弯,然后在新网格中调用getBestMove函数。但是,有时网格的分配不会发生,并且会调用getBestMove
方法。
第二,当我用getBestMove
方法打印网格数组时,它总是只用两个元素打印同一数组,例如...
gridArr:-0:-[1,2,0],1:-[0,0,0],2:-[0,0,0]
...,并且每次下一个空单元格都返回为bestMove
。
起初,我以为同一数组已传递给每个getBestMove
函数,但是当我记录分数时,我是从evaluateScore(grid)
方法获得结果的(返回10表示获胜,- 10输了,平局输了0)也返回了10和-10。
请参见下面的代码。
无论如何,这需要在两个函数的每次迭代中发生,当检测到空单元格时,该函数将进行移动,即将转数分配给网格,然后将该网格传递给函数调用。
我将 1 用于'X',将 2 用于'0'和网格中的空单元格为0 。 GRID_LENGTH
是井字游戏的行大小,目前为3,grid是用于存储X和0的2d数组。在evaluateScore
函数中,WIN_LENGTH
是决定获胜状态的长度,在这种情况下为3
This is git repository, which creates the error(s) in question
谢谢大家!
function computerTurn(moves) {
let bestValue = -1000,
bestMove = [];
for (let row = 0; row < GRID_LENGTH; row++) {
for (let col = 0; col < GRID_LENGTH; col++) {
if (grid[row][col] == 0) {
// searching for empty cell
grid[row][col] = 2; // making move
moves++; // increment moves count
let moveValue = getBestMove(grid, 0, false, moves); // checking is this is the best move
moves--;
grid[row][col] = 0;
if (moveValue > bestValue) {
// updating values
bestMove[0] = row;
bestMove[1] = col;
bestValue = moveValue;
}
}
}
}
grid[bestMove[0]][bestMove[1]] = 2;
turn = 'X';
return bestMove;
}
function getBestMove(gridArr, depth, isMax, moves) {
let score = evaluateScore(gridArr);
let arr = gridArr;
if (score == 10 || score == -10) {
return score;
}
if (moves == totalMoves) {
return 0;
}
if (isMax) {
let best = -1000;
for (let i = 0; i < GRID_LENGTH; i++) {
for (let j = 0; j < GRID_LENGTH; j++) {
if (arr[i][j] == 0) {
arr[i][j] = 2;
moves++;
best = Math.max(best, getBestMove(arr, depth + 1, !isMax, moves));
arr[i][j] = 0;
moves--;
}
}
}
return best;
} else {
let best = 1000;
for (let i = 0; i < GRID_LENGTH; i++) {
for (let j = 0; j < GRID_LENGTH; j++) {
if (arr[i][j] == 0) {
arr[i][j] = 1;
moves++;
best = Math.min(best, getBestMove(arr, depth + 1, !isMax, moves));
arr[i][j] = 0;
moves--;
}
}
}
return best;
}
}
function evaluateScore(gridArr) {
let diff = GRID_LENGTH - WIN_LENGTH;
let len = WIN_LENGTH - 1;
for (let i = 0; i < GRID_LENGTH; i++) { // check win for different rows
if (diff == 0) {
let win = true;
for (let j = 0; j < len; j++) {
if (gridArr[i][j] != gridArr[i][j + 1]) {
win = false;
break;
}
}
if (win) {
if (gridArr[i][0] == 1) {
return -10;
} else if (gridArr[i][0] == 2) {
return 10;
}
}
} else {
for (let j = 0; j <= diff; j++) {
let count = 0;
for (let k = j; k < len; k++) {
if ((gridArr[i][k] != gridArr[i][k + 1])) {
count++;
}
if (count == len) {
if (gridArr[i][k] == 1) {
return -10;
} else if (gridArr[i][k] == 2) {
return 10;
}
}
}
}
}
}
for (let i = 0; i < GRID_LENGTH; i++) { // check win for different cols
if (diff == 0) {
let win = true;
for (let j = 0; j < len; j++) {
if (gridArr[j][i] != gridArr[j][i + 1]) {
win = false;
break;
}
}
if (win) {
if (gridArr[0][i] == 1) {
return -10;
} else if (gridArr[0][i] == 2) {
return 10;
}
}
} else {
for (let j = 0; j <= diff; j++) {
let count = 0;
for (let k = j; k < len; k++) {
if ((gridArr[k][i] != gridArr[k][i + 1])) {
count++;
}
if (count == len) {
if (gridArr[k][i] == 1) {
return -10;
} else if (gridArr[k][i] == 2) {
return 10;
}
}
}
}
}
}
let diagonalLength = GRID_LENGTH - WIN_LENGTH;
for (let i = 0; i <= diagonalLength; i++) { // diagonals from left to right
for (let j = 0; j <= diagonalLength; j++) {
let row = i,
col = j;
let win = true;
for (let k = 0; k < len; k++) {
if (gridArr[row][col] != gridArr[row + 1][col + 1]) {
win = false;
break;
}
row++;
col++;
}
if (win) {
if (gridArr[i][j] == 1) {
return -10;
} else if (gridArr[i][j] == 2) {
return 10;
}
}
}
}
let compLen = GRID_LENGTH - diagonalLength - 1;
for (let i = 0; i >= diagonalLength; i--) { // diagonals from right to left
for (let j = GRID_LENGTH - 1; j >= compLen; j--) {
let row = i,
col = j;
let win = true;
for (let k = 0; k < len; k++) {
if (gridArr[row][col] != gridArr[row + 1][col - 1]) {
win = false;
break;
}
row++;
col--;
}
if (win) {
if (gridArr[i][j] == 1) {
return -10;
} else if (gridArr[i][j] == 2) {
return 10;
}
}
}
}
return 0;
}