带有minimax算法的JavaScript中的井字游戏

时间:2019-03-30 12:23:02

标签: javascript

我正在尝试使用针对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;
}

0 个答案:

没有答案