代码之家  ›  专栏  ›  技术社区  ›  Lich

很难将Alpha-beta修剪实现为minimax算法

  •  0
  • Lich  · 技术社区  · 7 年前

    我很难让Alpha-beta修剪正常工作。 我有一个函数极小极大算法,我试着去适应,但没有用。我在上使用了该示例 Wikipedia

    目前,该算法似乎在大多数情况下都按预期运行,但不管怎样,它都会选择第一个测试节点。

    这可能是由于缺乏理解,但我已经花了几个小时阅读了这篇文章。让我困惑的是,在零和博弈中,算法如何知道当达到深度极限时哪个节点是最佳选择;在哪一点上,我们还不能确定哪位球员会从这一举动中受益最多,是吗?

    不管怎样,我的。cpp如下。无论是我原来的极大极小函数和任何帮助将不胜感激!

    AIMove ComputerInputComponent::FindBestMove() {
    
    const Graph<HexNode>* graph = HexgameCore::GetInstance().GetGraph();
    
    std::vector<AIMove> possibleMoves;
    
    FindPossibleMoves(*graph, possibleMoves);
    
    AIMove bestMove = AIMove();
    
    int alpha = INT_MIN;
    int beta = INT_MAX;
    int depth = 6;
    
    Node* currentNode;
    
    for (const AIMove &move : possibleMoves) {
    
        std::cout << move << std::endl;
    
        graph->SetNodeOwner(move.x, move.y, (NodeOwner)aiPlayer);
        int v = MiniMaxAlphaBeta(*graph, depth, alpha, beta, true);
        graph->SetNodeOwner(move.x, move.y, NodeOwner::None);
    
        if (v > alpha) {
            alpha = v;
            bestMove.x = move.x;
            bestMove.y = move.y;
        }
    }
    return bestMove;
    

    }

    template<typename T>
    

    int ComputerInputComponent::minimaxpalphabeta(常量图和图形、int深度、int alpha、int beta、bool isMaximiser){

    std::vector<AIMove> possibleMoves;
    FindPossibleMoves(graph, possibleMoves);
    
    if (lastTestedNode != nullptr) {
        Pathfinder pathFinder;
        bool pathFound = pathFinder.SearchForPath(lastTestedNode, graph.GetMaxX(), graph.GetMaxY());
        if (pathFound) {
            //std::cout << "pathfound-" << std::endl;
            if ((int)lastTestedNode->GetOwner() == aiPlayer) {
                std::cout << "cpuWin-" << std::endl;
                return 10;
            } 
            else if ((int)lastTestedNode->GetOwner() == humanPlayer) {
                std::cout << "playerWin-" << std::endl;
                return -10;
            }
        }
        else {
            if (depth == 0) {           
                //std::cout << "NoPath-" << std::endl;
                return 0;
            }
        }
    }
    
    
    if (isMaximiser) {// Max
        int v = -INT_MAX;
        for (const AIMove &move : possibleMoves) {
            graph.SetNodeOwner(move.x, move.y, (NodeOwner)aiPlayer);
            graph.FindNode(move.x, move.y, lastTestedNode);
            v = std::max(alpha, MiniMaxAlphaBeta(graph, depth - 1, alpha, beta, false));
            alpha = std::max(alpha, v);
            graph.SetNodeOwner(move.x, move.y, NodeOwner::None);
            if (beta <= alpha)
                break;
        }
        return v;
    }
    else if (!isMaximiser){ // Min
        //std::cout << "Human possiblMoves size  = " << possibleMoves.size() << std::endl;
        int v = INT_MAX;
        for (const AIMove &move : possibleMoves) {
            graph.SetNodeOwner(move.x, move.y, (NodeOwner)humanPlayer);
            v = std::min(beta, MiniMaxAlphaBeta(graph, depth - 1, alpha, beta, true));
            beta = std::min(beta, v);
            graph.SetNodeOwner(move.x, move.y, NodeOwner::None);
            if (beta <= alpha)
                break;
        }
        return v;
    }
    

    }

    1 回复  |  直到 7 年前
        1
  •  0
  •   seccpur    7 年前

    您的minimax递归调用和移动生成在逻辑上是正确的,只是您不应该在内部直接使用它来推断赢家。您的叶节点评估应该是强大的,这是关键,您的代码中似乎缺少这一点。此外,详细的叶节点功能会使AI决策速度过慢。

    这是递归MiniMax函数的伪代码。假设parent\u graph是评估最佳移动之前的状态,leaf\u graph是当前的离开节点状态。你必须在极大极小树中找到相对(不要与绝对)最好的分支。

    if (depth == 0) {           
            return EvaluateLeafNode(isMaximizing,parent_graph,leaf_graph);
        }
    

    EvaluateLeafNode函数可以如下读取:

    int EvaluateLeafNode(bool isMaximizing,Graph& parent_graph,Graph& leaf_graph)
    {
       int score = 0;
       int w = find_relative_white_deads(parent_graph,leaf_graph);
       int b = find_relative_black_deads(parent_graph,leaf_graph);
    
       if(isMaximizing)
          score += b;
       else
          score += w;
       return score;
    }