首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >MiniMax实现

MiniMax实现
EN

Stack Overflow用户
提问于 2013-04-25 18:06:23
回答 2查看 14.3K关注 0票数 1

我试图在Java中编写一个小AI算法来实现miniMax算法。

这个游戏的基础是两人游戏,两人轮流做一次移动,每个棋盘位置导致每个玩家都有一个分数。玩家X的位置的“质量”是通过从玩家X的分数中减去对手的分数来评价的。每一个移动由一个整数表示(即移动一由输入1,移动二通过输入2等)。

我理解miniMax应该使用递归实现。现在我有:

一个evaluate()方法,它以一个表示板状态的对象(即"BoardState“对象和一个名为"max”的布尔值)作为参数(签名将被计算(BoardState myBoard,布尔值max))。

当轮到X玩家的时候,马克斯是真的。给定一个棋盘位置,它将评估所有可能的移动,并返回对玩家X最有利的移动。如果是对手的回合,则max将为假,该方法将返回对X玩家最不利的移动(即:对y玩家最有利)。

然而,我在编写实际的miniMax方法时遇到了困难。我的总体结构应该是:

代码语言:javascript
运行
复制
public int miniMax(GameState myGameState, int depth)

因此,我提交了初始的gameState和“深度”,我想要它来查看。

我就会有这样的感觉:

代码语言:javascript
运行
复制
int finalMove = 0;
while(currentDepth < depth) {
    GameState tmp = myGameState.copy();
    int finalMove = evaluate(tmp, true or false);
    iniMax(tmp.makeMove(finalMove));

}
return finalMove;

这听起来像一个合理的实施吗?有什么建议吗?)

谢谢!

EN

回答 2

Stack Overflow用户

发布于 2013-04-27 01:56:11

那不管用。

详情:

  1. 它会导致无限循环。现在的深度永远不会增加
  2. 你对评估的定义似乎与大多数人不同。通常,评估函数将返回游戏状态的预测值。你对求值函数的定义不是和minimax函数的定义一样吗?
  3. miniMax和MiniMax不同吗?因为如果您的意思是递归,那么在调用下一个miniMax时需要传递深度-1。

极小值的概念是深度优先搜索。只计算叶节点(具有最大深度的节点或胜负节点),如果当前玩家是最大节点,则选择最大节点;如果当前玩家是最小节点,则选择最小节点。

我就是这样实现它的:

代码语言:javascript
运行
复制
function miniMax(node, depth)
    if(depth == 0) then --leaf node     
        local ret = evaluate(node.state)
        return ret
    else -- winning node
        local winner = whoWin(node.state)       
        if(winner == 1) then -- P1      
            return math.huge
        elseif(winner == -1) then -- P2         
            return math.huge*-1
        end 
    end

    local num_of_moves = getNumberOfMoves(node.state)   
    local v_t = nil
    local best_move_index = nil 
    if(getTurn(node.state) == 1) then -- maximizing player      
    local v = -math.huge 
        for i=0, num_of_moves-1 do                      
            local child_node = simulate(node.state, i)) -- simulate move number i
            v_t = miniMax(child_node, depth-1)
            if(v_t > v) then 
                v = v_t 
                best_move_index = i             
            end
        end             
        if(best_move_index == nil) then best_move_index = random(0, num_of_moves-1) end 
        return v, best_move_index
    else -- minimizing player
    local v = math.huge
        for i=0, num_of_moves-1 do          
            local child_node = simulate(node.state, i)
            v_t = miniMax(child_node, depth-1)
            if(v_t < v) then                
                v = v_t             
                best_move_index = i             
            end
        end
        if(best_move_index == nil) then best_move_index = random(0, num_of_moves-1) end
        return v, best_move_index                               
    end 
end

注:

  • 返回v,best_move_index意味着返回v和best_move_index的两个值(上面的代码在lua中,lua可以返回多个值)
  • 评估函数返回两个玩家相同的分数(即游戏状态A在角度上是23,P1是23,P2也是23)。
  • 只有当两名玩家交替运行时(没有一名玩家可以连续运行两步),你可以通过给对手一个动作来欺骗这个限制,如果另一个玩家需要移动两次,那就是移动传球(跳过他/她的回合)。
  • 这个极小值可以进一步优化(从最简单的一个排序):

代码语言:javascript
运行
复制
1. alpha-beta pruning 
2. iterative deepening
3. move ordering

票数 3
EN

Stack Overflow用户

发布于 2013-04-28 05:06:03

我在lua中实现了minimax。我希望它能帮助您从Java的角度了解如何处理算法,代码应该是非常相似的。它是为玩抽搐脚趾游戏而设计的。

代码语言:javascript
运行
复制
--caller is the player who is using the minimax function
--initial state is the board from which the player must make a move
local function minimax(caller,inital_state)
    local bestState = {}; --we use this to store the game state the the player will create
      --this recurse function is really the 'minimax' algorithim 
    local function recurse(state,depth)
        --childPlayer is the person who will have their turn in the current state's children
        local ChildPlayer = getTurn(state)
        --parentPlayer is the person who is looking at their children
        local ParentPlayer = getPreviousTurn(state)
        --this represents the worst case scenario for a player
        local alpha =  - (ChildPlayer == caller and 1 or -1 );
        --we check for terminal conditions (leaf nodes) and return the appropriate objective value
        if win(state) then
            --return +,- inf depending on who called the 'minimax'
            return ParentPlayer == caller and 1 or -1;
        elseif tie(state) then 
            --if it's a tie then the value is 0 (neither win or loss)
            return  0;
        else
            --this will return a list of child states FROM the current state
            children = getChildrenStates(state,ChildPlayer)
            --enumerate over each child
            for _,child in ipairs(children) do
                --find out the child's objective value
                beta = recurse(child,depth+1);
                if ChildPlayer == caller then 
                    --We want to maximize
                    if beta >= alpha then 
                        alpha = beta
                        --if the depth is 0 then we can add the child state as the bestState (this will because the caller of minimax will always want to choose the GREATEST value on the root node)
                        if depth == 0 then
                            bestState = child;
                        end 
                    end 
                --we want to MINIMIZE
                elseif beta <= alpha then 
                    alpha = beta;
                end 
            end 
        end
         --return a non-terminal nodes value (propagates values up the tree)
        return alpha;           
    end
     --start the 'minimax' function by calling recurse on the initial state
    recurse(inital_state,0);
     --return the best move
    return bestState;
end 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16221686

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档