我的目标是编写一个性能尚可的国际象棋引擎,在下面的局面中,引擎应该能够轻松找到两步将死的解法,因为它的搜索深度为4-5步。
AI的第一步是移动车到a2以困住白方国王,白方国王移动到f1,但AI并没有选择将死,而是将车移动到c2。
var initial_depth = depth; var bestMove = null; var nodes = 0; var ret = await minimax(position, depth, alpha, beta, maximizingPlayer); console.log("nodes visited: " + nodes); return ret; async function minimax(position, depth, alpha, beta, maximizingPlayer) { nodes++; if (maximizingPlayer) { var validMoves = await getValidMoves(position, ArrtoFEN(position) + " w"); } else { var validMoves = await getValidMoves(position, ArrtoFEN(position) + " b"); } if (validMoves.length < 1 || depth == 0) { var eval = await getEval(position); return [eval, null]; } if (maximizingPlayer) { var maxEval = Number.NEGATIVE_INFINITY; for (var i = 0; i < validMoves.length; i++) { var move = validMoves[i]; var testbrd = makeMove(move, position) //not the actual code. shortend for Readability var eval = await minimax(testbrd, depth - 1, alpha, beta, false); if (eval[0] > maxEval) { maxEval = eval[0]; if (initial_depth == depth) { bestMove = move; console.log("current bestmove: " + bestMove); } } alpha = Math.max(alpha, eval[0]); if (beta <= alpha) { break; } } return [maxEval, bestMove]; } else { var minEval = Number.POSITIVE_INFINITY; for (var i = 0; i < validMoves.length; i++) { var move = validMoves[i]; var testbrd = makeMove(move, position)//not the actual code. shortend for Readability var eval = await minimax(testbrd, depth - 1, alpha, beta, true); if (eval[0] < minEval) { minEval = eval[0]; if (initial_depth == depth) { bestMove = move; console.log("current bestmove: " + bestMove); } } beta = Math.min(beta, eval[0]); if (beta <= alpha) { break; } } return [minEval, bestMove]; } }}
回答:
这是因为AI认为任何移动都能获胜,而你的代码中没有条件告诉引擎一步将死比五步将死更好。如果在搜索结束时发现没有合法移动并且处于被将死的状态,那么你就被将死了。在这种情况下,你需要返回一个将死分数(一个很大的负值)并加上从这一步开始的步数。这样,你就能让引擎在更少的步数内将死,而不是在更多的步数内将死。
我建议你改用Negamax算法而不是极小极大算法。这样可以大大减少代码量,并且更容易调试。