五子棋AI算法简易实现(六)

电脑AI篇


(3)Minimax算法(极小极大值搜索算法)

这是五子棋AI进行下子位置判断的基本方法,是整个AI最核心的算法。

A minimax algorithm is a recursive algorithm for choosing the next move in an n-player game, usually a two-player game. A value is associated with each position or state of the game. This value is computed by means of a position evaluation function and it indicates how good it would be for a player to reach that position. The player then makes the move that maximizes the minimum value of the position resulting from the opponent’s possible following moves. If it is A’s turn to move, A gives a value to each of their legal moves. —– from wikipedia

维基百科对Minimax算法的解释总结一下就是:

游戏中的每一个状态,类比棋类游戏就是玩家每下一步棋,都会产生一个值。这个值是由评估函数根据一定的方法对棋盘上同一方下棋的位置,产生的棋型等情况做出相应评估后产生的,它表示玩家在当前位置下棋所能带来的收益的大小(局势的好坏)。玩家所走的每一步,要最大化对手可能的后续移动所产生的不同位置对应的最小值(对你而言)。通俗点来说,就是在你下了当前这步棋,轮到你的对手时,你的对手会想方设法减弱你这步棋所产生的优势,而你需要做的,就是使得对手削减你的优势的程度越小越好,这使得你能够保持你的局面优势。

因此我们可以得出以下结论:

电脑走棋的层我们称为 MAX 层,这一层电脑要保证自己利益最大化,那么就需要选分最高的节点。

玩家走棋的层我们称为 MIN 层,这一层玩家要保证自己的利益最大化,那么就会选分最低的节点。

我也盗个图说明一下原理:
这里写图片描述
此图中甲是电脑,乙是玩家,那么在甲层(MAX层)的时候,总是选其中值最大的节点,乙层(MIN层)的时候,总是选其中最小的节点。而每一个节点的分数,都是由此节点的子节点所决定的,因此我们对博弈树只能进行深度优先搜索而无法进行广度优先搜索。

下面这个动图是我从维基百科上摘抄下来的,大家有时间可以看看,加深一下理解
极大极小值算法

代码实现:

const MIN = Number.NEGATIVE_INFINITY;
const MAX = Number.POSITIVE_INFINITY;

var pointCounter = 0;

//board 当前棋盘, deep 思考步数
var FunctionMaxMin = function(board, color, deep) {
    var best = MIN;
    //console.log(board);
    var boardTemp = StepGenerator.copyAndWrapBoard(board);
    var points = StepGenerator.generateAllNextPossibleMove(boardTemp, color);
    //console.log(points);
    var bestPoints = [];
    //console.log(points);
    for(var i = 0; i < points.length; i++){
        var now_point = points[i];
        boardTemp[now_point[0]+2][now_point[1]+2] = color;         //下子的颜色

        var value = min(boardTemp, Math.abs(color-1), deep-1);

        pointCounter++;

        if(value == best){
            bestPoints.push(now_point);
        }
        else if(value > best){
            best = value;
            bestPoints = [];
            bestPoints.push(now_point);
        }
        else{
            console.log('ignore');
        }
        boardTemp[now_point[0]+2][now_point[1]+2] = 'e'; 
    }
    console.log("搜索节点数:"+pointCounter);
    var result = bestPoints[Math.floor(Math.random() * bestPoints.length)];
    if(result == undefined)
        return [];
    return [result[0]+1, result[1]+1];
}

//max函数
var max = function(board, color, deep){
    var v = ModuleEvaluate.evaluate(board);
    if(deep <= 0 || ModuleWinnerCheck.checkWinnerInAiController(board, color))
        return v;

    var best = MIN;
    var points = StepGenerator.generateAllNextPossibleMove(board, color);

    for( var i = 0; i < points.length; i++){

        pointCounter++;

        var p = points[i];
        board[p[0]+2][p[1]+2] = color;
        var v = min(board, Math.abs(color-1), deep-1);
        board[p[0]+2][p[1]+2] = 'e';
        if(v > best)
            best = v;
    }

    return best;
};

//min函数
var min = function(board, color, deep){
    var v = ModuleEvaluate.evaluate(board);
    if(deep <= 0 || ModuleWinnerCheck.checkWinnerInAiController(board, color))
        return v;

    var best = MAX;
    var points = StepGenerator.generateAllNextPossibleMove(board, color);

    for( var i = 0; i < points.length; i++){

        pointCounter++;

        var p = points[i];
        board[p[0]+2][p[1]+2] = color;
        var v = max(board, Math.abs(color-1), deep-1);
        board[p[0]+2][p[1]+2] = 'e';
        if(v < best)
            best = v;
    }

    return best;
};

下一篇博客将介绍AlphaBeta剪枝算法的实现。

项目地址:https://github.com/huangzhutao/Gomoku.git,相关源码可在上面查看
欢迎大家对我叙述和代码中出现的不足之处进行批评指正

  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZTao-z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值