java - 使用 Alpha-Beta 剪枝在 MinMax 中实现树

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

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

我编写了以下方法:

-方法

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

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

-方法

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

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

-方法

public void undo(){
     ...
}

恢复板之前的状态。

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

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

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剪枝?

最佳答案

这是我过去编写的 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 。它没有经过 super 优化,因为试图使其尽可能可读

已添加:因此请删除当前,因为它并不是真正需要的。为搜索窗口添加两个参数并添加剪枝:

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)

关于java - 使用 Alpha-Beta 剪枝在 MinMax 中实现树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28464919/

相关文章:

Java 2d 数组与图 block 的坐标错误

java - 适用于 500 多个航路点/节点的最短路径算法(例如 Dijkstra 算法)?

algorithm - 如何显示Alpha Beta Pruning算法结果?

javascript - Minimax Alpha Beta Pruning Algorithm 解决 Tic Tac Toe(10x10 棋盘)需要花费太多时间

Java:使用 HashMap 作为稀疏 vector

java - 为什么 IntelliJ 的检查员会突出显示这段代码?

java - 如何使用日历获取当前时间?

artificial-intelligence - 学习分层强化任务的结构

machine-learning - 神经网络误差随每个训练示例而振荡

java - 如何通过 alpha beta 剪枝实现迭代加深