我正在为我的黑白棋游戏带 react.js研究 Minimax 算法,但它给出了 RangeError

问题描述

我正在为我的黑白棋游戏开发 Minimax 算法,以便我有一个强大的 AI 对手来面对玩家。但是我遇到了这个错误:“RangeError: Maximum call stack size exceeded”

我能做些什么来修复它?

这是代码(我不会用伪代码解释它,因为我的问题不是关于函数不起作用):

人工智能算法:

function minimaxAI(){
        const squares = history[history.length - 1].slice()
        let bestscore = -Infinity
        let bestMove = null
        // Perform minimax algorithm for each valid move and pick the best score
        const AI = (ourPlayer === "white") ? "black" : "white"
        const AIValidMoves = checkSquaresForSides()[(AI === "black") ? 0 : 1 ]
        console.log(AIValidMoves)
        for (var aimove=0;aimove<AIValidMoves.length;aimove++){
            const crds = AIValidMoves[aimove].turned
            crds.unshift(AIValidMoves[aimove].coordinates)
            const newBoard = handleMove(crds,squares)
            const score = minimax(newBoard,5,(AI === "black") ? false : true)
            if (score > bestscore) {
                bestscore = score
                bestMove = crds
            }
        }
        const handling = bestMove
        const upcomingAI = handleMove(handling)
        setHistory(upcomingAI)
        setStepNumber(upcomingAI.length - 1)
    }

极小极大算法:

function minimax(board,depth,isMaximizing){
        const AI = (ourPlayer === "white") ? "BLACK" : "WHITE"
        let result = setWinnerAndTurn(true)
        // Retrieve the filled squares of the current board
        let currentStones = 0
        history[history.length - 1].slice().map((row,y) =>
            row.map((square,x) =>
                currentStones += (square) ? 1 : 0
            )
        );
        let newStones = 0
        // Retrieve the filled squares of the updated board
        board.map((row,x) =>
                newStones += (square) ? 1 : 0
            )
        );
        console.log(currentStones)
        console.log(newStones)
        if (result.winner || newStones - currentStones === depth) {
            // Get the evaluated version of the last move
            let score = (result.winner === AI) ? Infinity : -Infinity
            return score
        }
        if (isMaximizing){
            // Play the optimal move for the opposing player
            let bestscore = -Infinity
            let bestMove = null
            const selection = (AI === "BLACK") ? 0 : 1 
            const AIValidMoves = checkSquaresForSides()[selection]
            console.log(AIValidMoves)
            for (var aimove=0;aimove<AIValidMoves.length;aimove++){
                const crds = AIValidMoves[aimove].turned
                crds.unshift(AIValidMoves[aimove].coordinates)
                const newBoard = handleMove(crds,board)
                const score = minimax(newBoard,10,(selection === 0) ? false : true)
                if (score > bestscore) {
                    bestscore = score
                    bestMove = crds
                }
            }
            return bestscore
        } else {
            // Play the optimal move for the maximizing player
            let bestscore = Infinity
            let bestMove = null
            const selection = (AI === "BLACK") ? 1 : 0 
            const AIValidMoves = checkSquaresForSides()[selection]
            console.log(AIValidMoves)
            for (var aimove=0;aimove<AIValidMoves.length;aimove++){
                const crds = AIValidMoves[aimove].turned
                crds.unshift(AIValidMoves[aimove].coordinates)
                const newBoard = handleMove(crds,(selection === 1) ? false : true)
                if (score < bestscore) {
                    bestscore = score
                    bestMove = crds
                }
            }
            return bestscore
        }
    }

解决方法

顺便说一下,我在 1 小时前解决了这个问题(现在发布)。我忘记在向树根方向迈出的每一步都减少深度值。只是改变了这些部分:

第一个:

if (result.winner) {
    // Get the evaluated version of the last move
    let score = (result.winner === AI) ? Infinity : -Infinity
    return score
} else if (depth === 0) {
    return 0
}

第二:

const score = minimax(newBoard,depth - 1,(selection === 1) ? false : true)

否则函数会卡在不定式移动中

此外,您可以删除此内容:

let currentStones = 0
history[history.length - 1].slice().map((row,y) =>
    row.map((square,x) =>
    currentStones += (square) ? 1 : 0
    )
);
let newStones = 0
// Retrieve the filled squares of the updated board
board.map((row,x) =>
        newStones += (square) ? 1 : 0
    )
);