当前位置: 首页 > 知识库问答 >
问题:

用Alpha-Beta剪枝实现最小最大树

从智志
2023-03-14

我想为一个类似跳棋的游戏实现一个人工智能

我写了以下方法:

-方法

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

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

-方法

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

将移动应用于棋盘,如果有棋子被杀则返回1

-方法

public void undo(){
     ...
}

以恢复板的先前状态。

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

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

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

共有1个答案

阎自怡
2023-03-14

这是我过去写的一个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;

只有DynamateMovesE价值定位MoveForwards/返回是特定的。您可以在此处找到完整的代码。它不是超级优化的,因为它试图使其尽可能具有可读性

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

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

 类似资料:
  • 我正在尝试为一个游戏创建一个AI播放器,使用带有alpha-beta修剪的minimax算法。我在正确地执行它时遇到了一些困难。我有两个功能要使用,一个用于评估给定玩家(返回一些分数)getBoardScore的当前棋盘状态,另一个用于返回每个可能移动(从给定玩家的给定棋盘状态)GetPossibleBoard创建的所有可能棋盘状态。 我的AI通过最初调用alphaBeta,将其传递到当前的板状态

  • 抱歉,这是我的笔记。 在最后一天,我一直在阅读极大极小树和阿尔法数据修剪,为我的项目做准备。这是c语言中奥赛罗的实现。 我阅读了大量关于它的资料,我知道它被问了很多。在我开始我的评估功能之前,我想充分了解这一点。 在随附的图像中,我无法弄清楚函数和究竟会做什么,任何输入将不胜感激。 如果任何人有任何提示或事情,我应该注意在实现这个和我的奥赛罗评估功能,我愿意采取任何帮助,我可以找到。

  • 我正在为游戏开发AI,我想使用MinMax算法和Alpha-Beta修剪。 我对它的工作原理有一个粗略的想法,但我仍然无法从头开始编写代码,所以我花了最近两天的时间在网上寻找某种伪代码。 我的问题是,我在网上找到的每个伪代码似乎都是基于找到最佳移动的值,而我需要返回最佳移动本身而不是数字。 我现在的代码是基于这个伪代码(源代码) 如您所见,这段代码返回一个数字,我想这是使一切正常工作所必需的(因为

  • 我很难让Alpha-beta修剪正常工作。我有一个函数Minimax算法,我试着去适应,但没有用。我在维基百科上用了这个例子 目前,该算法似乎在大多数情况下都按预期运行,但不管怎样,它都会选择第一个测试节点。 这可能是因为缺乏理解,但我已经花了数小时阅读了这篇文章。让我困惑的是,在零和博弈中,算法如何知道当达到深度极限时哪个节点是最佳选择;在哪一点上,我们还不能确定哪位球员会从这样的举动中受益最大

  • 本篇将简要介绍α-β剪枝,这是一种基于剪枝( α-βcut-off)的深度优先搜索(depth-first search)。 一、什么是α剪枝? (1)将走棋方定为MAX方,因为它选择着法时总是对其子节点的评估值取极大值,即选择对自己最为有利的着法; (2)将应对方定为MIN方,因为它走棋时需要对其子节点的评估值取极小值,即选择对走棋方最为不利的、最有钳制作用的着法。 (3)在对博弈树(博弈树是指

  • 我在为象棋游戏制作一个人工智能。 到目前为止,我已经成功实现了Alpha-Beta剪枝Minimax算法,它看起来是这样的(来自维基百科): 由于这花费了太多的时间复杂性(逐一遍历所有的树),我遇到了一种叫做“历史启发式”的东西。 原始论文中的算法: 所以基本上,这个想法是跟踪一个散列表或者一个字典来记录以前的“移动”。 现在我很困惑这个“移动”在这里意味着什么。我不确定它是字面上指的单一移动还是