【人工智能】Alpha-Beta剪枝算法

前言:在设计一款棋类博弈游戏的APP时,用到了Alpha-Beta剪枝算法,当时查尽资料仍对此算法不甚了解。网上大部分相关解析太过精简,萌新“初来乍看”不免云里雾里,故今日详细的将此算法叙述一番,希望对有需要的朋友有所帮助。至于博弈的相关概念网上资料很多,而且很详细,这里便不在赘余。

首先,我简单的介绍一下博弈树,这里由一个经典的例子引入:
在这里插入图片描述在这里插入图片描述
所以可得:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上图只计算了其中一部分,便可知完整博弈树的庞大复杂,为便于理解与计算,我们假设其完整的树如下图所示:
在这里插入图片描述
现在求此树的每层的值,需得保证己方获得的e(P)值最大,而对方的获得的e(P)值最小。
在这里插入图片描述
即可求出最佳走法:
在这里插入图片描述
以上便是博弈树,在这里我们就会发现一个问题,要把树中所有枝叶上的值求出来,计算量未免太大,有没有更好的办法呢?这里,我们引出了Alpha-Beta剪枝算法。下面我将以图示的办法展现其过程:
1.下图所示是一个只求出了三个估价值的四层博弈树。
在这里插入图片描述
2.我们可求出F点的估价值是4。
在这里插入图片描述
3.我们可知C点的估价值必定要大于等于4。
在这里插入图片描述
4.我们接着求N点的值,且可知G点的值必定要小于等于1。
在这里插入图片描述
5.由于C点的值必然大于等于4,且G点的值已经小于等于1,故G点的另一条树枝的值不用计算,因为算出来也用不上。

在这里插入图片描述
6.下面同理,得A的值必小于等于4,且D的值已经大于等于5,故D点的另一条树枝的值也不用计算。
在这里插入图片描述
7.同理将剩余节点也如此处理。
在这里插入图片描述
以上便是Alpha-Beta剪枝算法。
下面附上其Java语言实现方式(代码源自GitHub):

    private static MinimaxResult max(byte[][] chessBoard, int depth, int alpha, int beta, byte chessColor, int difficulty) {
        if (depth == 0) {
            return new MinimaxResult(evaluate(chessBoard, difficulty), null);
        }

        List<Move> legalMovesMe = Rule.getLegalMoves(chessBoard, chessColor);
        if (legalMovesMe.size() == 0) {
            if (Rule.getLegalMoves(chessBoard, (byte)-chessColor).size() == 0) {
                return new MinimaxResult(evaluate(chessBoard, difficulty), null);
            }
            return min(chessBoard, depth, alpha, beta, (byte)-chessColor, difficulty);
        }

        byte[][] tmp = new byte[8][8];
        Util.copyBinaryArray(chessBoard, tmp);
        int best = Integer.MIN_VALUE;
        Move move = null;

        for (int i = 0; i < legalMovesMe.size(); i++) {
            alpha = Math.max(best, alpha);
            if(alpha >= beta){
                break;
            }
            Rule.move(chessBoard, legalMovesMe.get(i), chessColor);
            int value = min(chessBoard, depth - 1, Math.max(best, alpha), beta, (byte)-chessColor, difficulty).mark;
            if (value > best) {
                best = value;
                move = legalMovesMe.get(i);
            }
            Util.copyBinaryArray(tmp, chessBoard);
        }
        return new MinimaxResult(best, move);
    }

    private static MinimaxResult min(byte[][] chessBoard, int depth, int alpha, int beta, byte chessColor, int difficulty) {
        if (depth == 0) {
            return new MinimaxResult(evaluate(chessBoard, difficulty), null);
        }

        List<Move> legalMovesMe = Rule.getLegalMoves(chessBoard, chessColor);
        if (legalMovesMe.size() == 0) {
            if (Rule.getLegalMoves(chessBoard, (byte)-chessColor).size() == 0) {
                return new MinimaxResult(evaluate(chessBoard, difficulty), null);
            }
            return max(chessBoard, depth, alpha, beta, (byte)-chessColor, difficulty);
        }

        byte[][] tmp = new byte[8][8];
        Util.copyBinaryArray(chessBoard, tmp);
        int best = Integer.MAX_VALUE;
        Move move = null;

        for (int i = 0; i < legalMovesMe.size(); i++) {
            beta = Math.min(best, beta);
            if(alpha >= beta){
                break;
            }
            Rule.move(chessBoard, legalMovesMe.get(i), chessColor);
            int value = max(chessBoard, depth - 1, alpha, Math.min(best, beta), (byte)-chessColor, difficulty).mark;
            if (value < best) {
                best = value;
                move = legalMovesMe.get(i);
            }
            Util.copyBinaryArray(tmp, chessBoard);
        }
        return new MinimaxResult(best, move);
    }

注明:本文章仅供学习参考之用,代码选自一款棋类博弈游戏。作者水平有限,不免有错漏之处,如有问题或建议,可留言告之。

  • 12
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值