📌  相关文章
📜  博弈论中的极小极大算法第一套(介绍)

📅  最后修改于: 2021-09-24 03:21:13             🧑  作者: Mango

Minimax 是一种回溯算法,用于决策制定和博弈论,以在假设您的对手也以最佳方式下棋的情况下为玩家找到最佳走法。广泛应用于二人回合制游戏,如井字游戏、西洋双陆棋、棋盘棋、国际象棋等。
在 Minimax 中,这两个玩家被称为最大化者和最小化者。最大化器试图获得尽可能高的分数,而最小化器则试图做相反的事情并获得尽可能低的分数。
每个董事会状态都有一个与之相关的值。在给定状态下,如果最大化者占上风,则棋盘的分数将趋于某个正值。如果最小化者在该棋盘状态中占上风,那么它往往会是一些负值。棋盘的值是通过一些启发式计算的,对于每种类型的游戏都是独一无二的。
例子:
考虑一个游戏,它有 4 个最终状态,到达最终状态的路径是从根到 4 个完美二叉树的叶子,如下所示。假设您是最大化玩家并且您有第一次移动的机会,即您在根部而您的对手在下一个级别。考虑到你的对手也打得最好,你作为一个最大化玩家会采取什么行动?

博弈论极小极大算法

由于这是一种基于回溯的算法,它会尝试所有可能的移动,然后回溯并做出决定。

  • 最大化器向左:现在轮到最小化器了。最小化器现在可以在 3 和 5 之间进行选择。作为最小化器,它肯定会在两者中选择最少的,即 3
  • 最大化器正确:现在轮到最小化器了。最小化者现在可以在 2 和 9 之间进行选择。他会选择 2,因为它是两个值中最小的。

作为最大化者,您将选择较大的值 3。因此,最大化者的最佳移动是向左移动,最佳值是 3。
现在游戏树如下所示:

博弈论极小极大算法1

上面的树显示了最大化器向左和向右移动时的两个可能的分数。
注意:即使右子树上的值为 9,最小化器也永远不会选择它。我们必须始终假设我们的对手发挥最佳。
下面是相同的实现。

C++
// A simple C++ program to find
// maximum score that
// maximizing player can get.
#include
using namespace std;
 
// Returns the optimal value a maximizer can obtain.
// depth is current depth in game tree.
// nodeIndex is index of current node in scores[].
// isMax is true if current move is
// of maximizer, else false
// scores[] stores leaves of Game tree.
// h is maximum height of Game tree
int minimax(int depth, int nodeIndex, bool isMax,
            int scores[], int h)
{
    // Terminating condition. i.e
    // leaf node is reached
    if (depth == h)
        return scores[nodeIndex];
 
    //  If current move is maximizer,
    // find the maximum attainable
    // value
    if (isMax)
       return max(minimax(depth+1, nodeIndex*2, false, scores, h),
            minimax(depth+1, nodeIndex*2 + 1, false, scores, h));
 
    // Else (If current move is Minimizer), find the minimum
    // attainable value
    else
        return min(minimax(depth+1, nodeIndex*2, true, scores, h),
            minimax(depth+1, nodeIndex*2 + 1, true, scores, h));
}
 
// A utility function to find Log n in base 2
int log2(int n)
{
  return (n==1)? 0 : 1 + log2(n/2);
}
 
// Driver code
int main()
{
    // The number of elements in scores must be
    // a power of 2.
    int scores[] = {3, 5, 2, 9, 12, 5, 23, 23};
    int n = sizeof(scores)/sizeof(scores[0]);
    int h = log2(n);
    int res = minimax(0, 0, true, scores, h);
    cout << "The optimal value is : " << res << endl;
    return 0;
}


Java
// A simple java program to find maximum score that
// maximizing player can get.
 
import java.io.*;
 
class GFG {
   
 
// Returns the optimal value a maximizer can obtain.
// depth is current depth in game tree.
// nodeIndex is index of current node in scores[].
// isMax is true if current move is of maximizer, else false
// scores[] stores leaves of Game tree.
// h is maximum height of Game tree
 static int minimax(int depth, int nodeIndex, boolean  isMax,
            int scores[], int h)
{
    // Terminating condition. i.e leaf node is reached
    if (depth == h)
        return scores[nodeIndex];
 
    // If current move is maximizer, find the maximum attainable
    // value
    if (isMax)
    return Math.max(minimax(depth+1, nodeIndex*2, false, scores, h),
            minimax(depth+1, nodeIndex*2 + 1, false, scores, h));
 
    // Else (If current move is Minimizer), find the minimum
    // attainable value
    else
        return Math.min(minimax(depth+1, nodeIndex*2, true, scores, h),
            minimax(depth+1, nodeIndex*2 + 1, true, scores, h));
}
 
// A utility function to find Log n in base 2
 static int log2(int n)
{
return (n==1)? 0 : 1 + log2(n/2);
}
 
// Driver code
 
    public static void main (String[] args) {
            // The number of elements in scores must be
    // a power of 2.
    int scores[] = {3, 5, 2, 9, 12, 5, 23, 23};
    int n = scores.length;
    int h = log2(n);
    int res = minimax(0, 0, true, scores, h);
    System.out.println( "The optimal value is : "  +res);
         
    }
}
 
// This code is contributed by vt_m


C#
// A simple C# program to find maximum score that
// maximizing player can get.
using System;
 
public class GFG
{
     
// Returns the optimal value a maximizer can obtain.
// depth is current depth in game tree.
// nodeIndex is index of current node in scores[].
// isMax is true if current move is of maximizer, else false
// scores[] stores leaves of Game tree.
// h is maximum height of Game tree
static int minimax(int depth, int nodeIndex, bool isMax,
            int []scores, int h)
{
    // Terminating condition. i.e leaf node is reached
    if (depth == h)
        return scores[nodeIndex];
 
    // If current move is maximizer, find the maximum attainable
    // value
    if (isMax)
    return Math.Max(minimax(depth+1, nodeIndex*2, false, scores, h),
            minimax(depth+1, nodeIndex*2 + 1, false, scores, h));
 
    // Else (If current move is Minimizer), find the minimum
    // attainable value
    else
        return Math.Min(minimax(depth+1, nodeIndex*2, true, scores, h),
            minimax(depth+1, nodeIndex*2 + 1, true, scores, h));
}
 
// A utility function to find Log n in base 2
static int log2(int n)
{
    return (n==1)? 0 : 1 + log2(n/2);
}
 
// Driver code
static public void Main ()
{
 
    // The number of elements in scores must be
    // a power of 2.
    int []scores = {3, 5, 2, 9, 12, 5, 23, 23};
    int n = scores.Length;
    int h = log2(n);
    int res = minimax(0, 0, true, scores, h);
    Console.WriteLine( "The optimal value is : " +res);
     
}
}
 
// This code is contributed by ajit.


Python3
# A simple Python3 program to find
# maximum score that
# maximizing player can get
import math
 
def minimax (curDepth, nodeIndex,
             maxTurn, scores,
             targetDepth):
 
    # base case : targetDepth reached
    if (curDepth == targetDepth):
        return scores[nodeIndex]
     
    if (maxTurn):
        return max(minimax(curDepth + 1, nodeIndex * 2,
                    False, scores, targetDepth),
                   minimax(curDepth + 1, nodeIndex * 2 + 1,
                    False, scores, targetDepth))
     
    else:
        return min(minimax(curDepth + 1, nodeIndex * 2,
                     True, scores, targetDepth),
                   minimax(curDepth + 1, nodeIndex * 2 + 1,
                     True, scores, targetDepth))
     
# Driver code
scores = [3, 5, 2, 9, 12, 5, 23, 23]
 
treeDepth = math.log(len(scores), 2)
 
print("The optimal value is : ", end = "")
print(minimax(0, 0, True, scores, treeDepth))
 
# This code is contributed
# by rootshadow


Javascript


输出:

The optimal value is:  12

本文的思路是通过一个简单的例子来介绍Minimax。

  • 在上面的例子中,一个玩家只有两个选择。一般来说,可以有更多的选择。在这种情况下,我们需要重复所有可能的移动并找到最大值/最小值。例如,在 Tic-Tax-Toe 中,第一个玩家可以进行 9 种可能的移动。
  • 在上面的例子中,分数(游戏树的叶子)是给我们的。对于典型的游戏,我们需要推导出这些值

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程