3

我已经为类似国际象棋的游戏制作了一个 negamax 算法,我想知道如何使用最终的棋盘值结果。我知道 negamax 算法的最终回报代表了玩家采取最佳行动后棋盘的价值,但这并不是完全有用的信息。我需要知道那个动作什么,而不是它的价值。

这是代码:

public int negamax(Match match, int depth, int alpha, int beta, int color) {
    if(depth == 0) {
        return color*stateScore(match);
    }

    ArrayList<Match> matches = getChildren(match, color);

    if(matches.size() == 0) {
        return color*stateScore(match);
    }

    int bestValue = Integer.MIN_VALUE;

    for(int i = 0; i != matches.size(); i++) {
        int value = -negamax(matches.get(i), depth-1, -beta, -alpha, -color);

        if(value > bestValue) {
            bestValue = value;
        }

        if(value > alpha) {
            alpha = value;
        }

        if(alpha >= beta) {
            break;
        }
    }

    return bestValue;
}

public void getBestMove(Match match, int color) {

    int bestValue = negamax(match, 4, Integer.MIN_VALUE, Integer.MAX_VALUE, color);

    // What to do with bestValue???

}

我想在确定 bestValue 后重新评估当前匹配状态的孩子。然后我遍历它们并找出其中哪些孩子的 stateScore 等于 bestValue。但这行不通,因为无论如何他们中的很多人都会有相同的 stateScore,这是他们可以导致的结果......

4

1 回答 1

3

我可以看到您正在执行 qsearch 和 alpha-beta。你的算法是众所周知的,但你错过了一个关键部分。

让我勾勒出国际象棋搜索的基本算法,它甚至适用于 Stockfish(世界上最强大的引擎)。

search(Position p) {

    if (leaf node)
        qsearch(p)

    if (need to do move reduction)
        do_move_reduction_and_cut_off(p)

    moves = generate_moves(p)

    for_each(move in moves) {            
        p.move(move)
        v = -search(p, -beta, -alpha)
        p.undo(move)

        store the score and move into a hash table

        if (v > beta)
           cutoff break;           
    }

这只是一个非常简短的草图,但所有国际象棋算法都遵循它。对比一下你的版本,你有没有发现没有做 p.move(move) 和 p.undo(move)?

基本上,传统方法为给定位置生成移动列表。循环移动,播放并撤消它并搜索它。如果你这样做了,你就会确切地知道哪个动作会产生哪个分数。

还要注意将移动和得分存储到哈希表中的行。如果这样做,您可以轻松地从根节点重建整个主变体。

我不知道你的 Java 类 Match 里面到底有什么,但无论如何你的尝试很接近,但不是完全经典的搜索方式。请记住,您需要在搜索算法中提供一个位置对象,但您却给了它一个匹配对象,这是错误的。

于 2014-09-02T05:07:44.983 回答