我在创建井字游戏的无敌AI时遇到了困难。
我一直在谷歌搜索并使用The Coding Train的教程 – 然而,AI似乎仍然在随机选择方格。尽管它选择方格的背后肯定有逻辑,但我无法弄清楚这个逻辑是什么!
这是我的codepen – https://codepen.io/kath-ldn/pen/oNLZqrp,我已经在下面复制了相关的代码片段。
如果有人能看一下,我将不胜感激。我已经卡了好几天了,无法找出问题所在。
//functions to assess winning combosfunction equals3(a, b, c) { return a === b && b === c && a !== "";}function checkWinner(){ let winner = null; if (equals3(gameBoard[0], gameBoard[1], gameBoard[2])) { winner = gameBoard[0]; }; if (equals3(gameBoard[3], gameBoard[4], gameBoard[5])) { winner = gameBoard[3]; }; if (equals3(gameBoard[6], gameBoard[7], gameBoard[8])) { winner = gameBoard[6]; }; if (equals3(gameBoard[0], gameBoard[3], gameBoard[6])) { winner = gameBoard[0]; }; if (equals3(gameBoard[1], gameBoard[4], gameBoard[7])) { winner = gameBoard[1]; }; if (equals3(gameBoard[2], gameBoard[5], gameBoard[8])) { winner = gameBoard[0]; }; if (equals3(gameBoard[0], gameBoard[4], gameBoard[8])) { winner = gameBoard[0]; }; if (equals3(gameBoard[2], gameBoard[4], gameBoard[6])) { winner = gameBoard[2]; }; let openSpots = 0; for (let i = 0; i < gameBoard.length; i++) { if (gameBoard[i] === "") { openSpots = openSpots + 1; }; }; if (winner === null && openSpots === 0) { return 'tie'; } else { return winner; };};let scores = { X: 10, O: -10, tie: 0};//function to create impossible-to-beat AI using minimax algorithmfunction bestMove() { let bestScore = -Infinity; let move; for (let i = 0; i < gameBoard.length; i++) { if (gameBoard[i] === "") { gameBoard[i] = AI; let score = minimax(gameBoard, 0, false); gameBoard[i] = ""; if (score > bestScore) { bestScore = score; move = i; } } } gameBoard[move] = AI;};//minimax functionfunction minimax(gameBoard, depth, isMaximizing){ let result = checkWinner(); if (result !== null) { return scores[result]; } if (isMaximizing) { let bestScore = -Infinity; for (let i = 0; i < gameBoard.length; i++) { if (gameBoard[i] === "") { gameBoard[i] = AI; let score = minimax(gameBoard, depth + 1, false); gameBoard[i] = ""; bestScore = Math.max(score, bestScore); } } return bestScore; } else { let bestScore = Infinity; for (let i = 0; i < gameBoard.length; i++) { if (gameBoard[i] === "") { gameBoard[i] = human; let score = minimax(gameBoard, depth + 1, true); gameBoard[i] = ""; bestScore = Math.min(score, bestScore); } } return bestScore; }};
回答:
你正在遍历整个棋盘并对每个方格调用minimax,这是不必要的,而且会非常慢。你只需要像这样调用一次即可:
move, score = minimax(gameBoard, 8, true)
我不确定是否需要,但我建议从checkWinner函数中返回0而不是返回’tie’字符串。否则,从例如1和’tie’中选择最大/最小值似乎很困难。
然后在你的minimax函数中,你需要更改一些东西来实际返回它找到的最佳移动。抱歉如果有任何编程语言问题,我习惯使用Python。我希望你明白我的意思:
//minimax functionfunction minimax(gameBoard, depth, isMaximizing){ let result = checkWinner(); if (result !== null) { return None, scores[result]; } if (isMaximizing) { let bestScore = -Infinity; for (let i = 0; i < gameBoard.length; i++) { if (gameBoard[i] === "") { gameBoard[i] = AI; let score = minimax(gameBoard, depth - 1, false)[1]; gameBoard[i] = ""; if score > bestScore: bestScore = score bestMove = gameBoard[i] } } return bestMove, bestScore; } else { let bestScore = Infinity; for (let i = 0; i < gameBoard.length; i++) { if (gameBoard[i] === "") { gameBoard[i] = human; let score = minimax(gameBoard, depth - 1, true)[1]; gameBoard[i] = ""; if score < bestScore: bestScore = score bestMove = gameBoard[i] } } return bestMove, bestScore; }};