【问题标题】:Tree Implementation in MinMax with Alpha-Beta Pruning使用 Alpha-Beta 修剪在 MinMax 中实现树
【发布时间】:2015-04-12 10:44:55
【问题描述】:

我想为类似跳棋的游戏实现 AI(人工智能)

我写了以下方法:

-方法

   public List<Move> allMoves(){
       ...
    }

返回按权重排序的所有有效移动的列表,其中权重是根据移动的类型和位置计算的

-方法

public int apply(Move m){
       ...
}

将移动应用到棋盘上,如果某个棋子被杀死则返回 1

-方法

public void undo(){
     ...
}

恢复板子以前的状态。

这是一个零和游戏,因此 AI 应该最大化玩家颜色的棋子并最小化对手的棋子。

为此,最好的方法似乎是使用带有 alpha-beta 修剪的 min-max。 这有以下伪代码

function alphabeta(node, depth, α, β, maximizingPlayer)

           if depth = 0 or node is a terminal node
                return the heuristic value of node
            if maximizingPlayer
                v := -∞
                for each child of node
                    v := max(v, alphabeta(child, depth - 1, α, β, FALSE))
                    α := max(α, v)
                    if β ≤ α
                        break (* β cut-off *)
                return v
            else
                v := ∞
                for each child of node
                    v := min(v, alphabeta(child, depth - 1, α, β, TRUE))
                    β := min(β, v)
                    if β ≤ α
                        break (* α cut-off *)
                return v

    (* Initial call *)
    alphabeta(origin, depth, -∞, +∞, TRUE)

但我不明白如何适应我的问题。 有人可以帮助我吗?

编辑

我有这个 MinMax 但没有修剪

private Integer minimax(Board board, Integer depth, Color current, Boolean maximizingPlayer) {
    Integer bestValue;
    if (0 == depth)
        return ((current == selfColor) ? 1 : -1) * this.evaluateBoard(board, current);

    Integer val;
    if (maximizingPlayer) {
        bestValue = -INF;
        for (Move m : board.getPossibleMoves(current)) {
            board.apply(m);
            val = minimax(board, depth - 1, current, Boolean.FALSE);
            bestValue = Math.max(bestValue, val);
            board.revert(m);
        }
        return bestValue;
    } else {
        bestValue = INF;
        for (Move m : board.getPossibleMoves(current)) {
            board.apply(m);
            val = minimax(board, depth - 1, current, Boolean.TRUE);
            bestValue = Math.min(bestValue, val);
            board.revert(m);
        }
        return bestValue;
    }
}

the evaluate function

private Integer evaluateBoard(Board board, Color player) {
    return board.pawns(player) - board.pawns(player.other());
}

如何编辑以获得alpha beta pruning?

【问题讨论】:

    标签: java artificial-intelligence alpha-beta-pruning minmax


    【解决方案1】:

    这是我过去编写的 alpha beta 国际象棋程序的一些伪代码。好吧,跳棋或国际象棋 - 这部分没有太大区别:

      Const White      =      1;
            Black      =     -1;
    
            MaxInteger =  32767;
            MinInteger = -32768;
    
      Function AlphaBeta (Color, Alpha, Beta, 
                                 Depth, MaxDepth : Integer) : Integer; 
      var Value : Integer;
    
      begin
        if Depth = MaxDepth then 
           AlphaBeta := EvaluatePosition (Color)
    
        end else
        begin
           GenerateMoves(Color, MoveList);
    
           For Each Move in MoveList do
           begin
               MoveForward (Move);
    
                   Value := AlphaBeta (-Color, Beta, Alpha,
                                               Depth +1, MaxDepth);
    
                   if Color = White then
                      if Value > Alpha then Alpha := Value;
    
                   if Color = Black then
                      if Value < Alpha then Alpha := Value;
    
               MoveBack (Move);
    
                   if Color = White then
                      if Alpha >= Beta then Return Alpha;
    
                   if Color = Black then
                      if Alpha <= Beta then Return Alpha;
           end;
    
           AlphaBeta := Alpha;
        end;
      end;
    

    只有 GenerateMovesEvaluatePositionMoveForward/Back 是特定的。你可以找到完整的代码here。它不是超级优化的,因为它试图使其尽可能可读

    添加:所以删除current,因为它并不是真正需要的。为搜索窗口添加两个参数并添加剪枝:

    private Integer minimax(Board board, Integer depth, Boolean maximizingPlayer, 
                            Integer maxPlayerBestVal, Integer minPlayerBestVal) {
        Integer bestValue;
        if (0 == depth)
            return this.evaluateBoard(board);
    
        Integer val;
        if (maximizingPlayer) {
            bestValue = -INF;
            // current never changed in your case; so you better use the bool
            for (Move m : board.getPossibleMoves(maximizingPlayer))) {
                board.apply(m);
                val = minimax(board, depth - 1, Boolean.FALSE, 
                              minPlayerBestVal, maxPlayerBestVal); // swap here 
                bestValue = Math.max(bestValue, val);
                board.revert(m);
                if (bestValue >= minPlayerBestVal) // too good for the minPlayer
                    return bestValue;              // so cut here (pruning)
            }
            return bestValue;
    

    最后你需要用一个最大化的窗口调用算法:

    minimax(board, 3, true, Integer.MinInt, Integer.MaxInt);
    

    ... 意思是它的最大值。玩家轮流从可能的最差值开始 (Integer.MinInt)

    【讨论】:

    • 非常感谢您的回答...但我仍然不清楚如何在 Alpha Beta 递归结束时获得最佳计算移动...以及如何“修剪”
    • 修剪是由最后两个 if 语句完成的——没有更多的事情要做。评估当然有点棘手。我会(1)计算棋子,(2)看看他们前进了多远,(3)如果他们在通往边界的路上有任何对手棋子。只是一个建议.... ;)
    • 请看问题更新。谢谢你。我还不明白如何编辑 minMax 来添加这个该死的修剪:(
    • 我可以看到两个问题:首先,您需要一个 窗口 用于参数中的两个最佳值(最大播放器的最佳值和最小播放器的最佳值)。其次是:注意乘法评估;让我们假设负值对黑色有好处,正值对白色有好处。结果黑色试图最小化,白色试图最大化价值。 evaluateBoard(...) 如果白色具有更好的位置,则返回正值,如果黑色具有更好的位置,则返回负值。这样一来,一切都融合在一起...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2021-01-25
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    相关资源
    最近更新 更多