如何解决javaScript中的minimax算法无法按预期工作,并返回错误的动作
我正在尝试使用minimax算法在javaScript中制作井字游戏,但似乎我做错了什么,并且minimax算法没有检测到最佳动作。这是代码:
const board = ["X",null,"X","O","O"];
/*
X _ _
_ _ X
X O O
*/
// duplicate passed board and return the new board state
const makeAIMove = (currentBoard,square,player) => {
const nextBoard = [...currentBoard];
nextBoard[square] = player;
return nextBoard;
};
// find empty squares
const emptySquares = (sqBoard) =>
sqBoard
.map((sq,idx) => (sq === null ? idx : null))
.filter((sq) => sq !== null);
// check if no empty squares are available
const isFinished = (sqBoard) => (emptySquares(sqBoard).length ? false : true);
// check winner
const checkWinner = (sqBoard) => {
const winConditions = [
[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,7],[2,5,];
for (const winCondition of winConditions) {
[a,b,c] = winCondition;
if (sqBoard[a] && sqBoard[a] === sqBoard[b] && sqBoard[a] === sqBoard[c])
return sqBoard[a];
}
return false;
};
// minimax algorithm
const minimax = (sqBoard,depth,isMaximizer) => {
// terminal checker
const theWinner = checkWinner(sqBoard);
// we have a winner
if (theWinner) {
return theWinner === "X" ? -10 : 10;
}
// it's a tie
if (isFinished(sqBoard)) {
return 0;
}
let bestScore;
if (isMaximizer) {
bestScore = -1000;
emptySquares(sqBoard).forEach((square) => {
// make a sample move
let nextBoard = makeAIMove(sqBoard,"O");
// recursion
let score = minimax(nextBoard,depth + 1,false);
bestScore = Math.max(bestScore,score);
});
} else {
bestScore = 1000;
emptySquares(sqBoard).forEach((square) => {
let nextBoard = makeAIMove(sqBoard,"X");
let score = minimax(nextBoard,true);
bestScore = Math.min(bestScore,score);
});
}
return bestScore;
};
// find the best move
const nextBestMove = (sqBoard) => {
let nextMoveArray = [];
let remainedSquares = emptySquares(sqBoard);
remainedSquares.forEach((square) => {
let nextBoard = makeAIMove(sqBoard,"O");
let theScore = minimax(nextBoard,true);
nextMoveArray.push({
sq: square,sc: theScore,});
});
nextMoveSorted = nextMoveArray.sort((a,b) => (a.sc < b.sc ? 1 : -1));
return nextMoveSorted[0].sq;
};
console.log(nextBestMove(board));
在上述情况下,最好的举动是通过在板[3]上加一个“ O”来阻止X获胜,但它总是会检测到另一个得分更高的举动。
谁能帮助我了解我的代码出了什么问题?
谢谢。
解决方法
从您的代码中,我了解到X是最小化者,O是最大化者。但是然后我看到了这段代码:
let nextBoard = makeAIMove(sqBoard,square,"O");
let theScore = minimax(nextBoard,true);
因此,在O移动之后,您可以将minimax
设置为true来调用isMaximizer
。但这会使minimax
进行另一次O动作,而O已经开始。您希望获得X的最佳答复,因此您应在此处传递false
:
let theScore = minimax(nextBoard,false);
现在,这将为每个这样的调用返回-10(因此O的每一步),因为O的游戏已经处于丢失状态,无论它做什么,X都会获胜。如果O在3处移动,那么X会在两次攻击中进行2。
如果要区分快赢和慢赢,则应在每次回溯时调整分数。
例如,您可以将return bestScore
语句替换为返回一个更接近零的单位的值。例如-10变成-9,5变成4,而0仍然是0:
return bestScore - Math.sign(bestScore);
进行此更改后,O的得分为-7(仍处于输球状态),将以3分出局,而另一个则将所有得分都移至-9(从X移开立即失去)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。