当前位置: 首页 > 知识库问答 >
问题:

MiniMax算法的一个非常有趣的问题。什么会导致这种行为?

法子昂
2023-03-14

我已经实现了极大极小算法(带有阿尔法-贝塔剪枝),但是它的行为方式很有趣。我的球员将创造一个巨大的领先优势,但当它是时候做出最后的,获胜的举动,它不采取这一举措,只是继续拖延游戏。

这是我的极小极大函数

// Game states are represented by Node objects (holds the move and the board in that state)
//ValueStep is just a pair holding the minimax value and a game move (step) 

private ValueStep minimax(Node gameState,int depth,int alpha,int beta) {

  //Node.MAXDEPTH is a constant
  if(depth == Node.MAXDEPTH || gameOver(gameState.board)) {
      return new ValueStep(gameState.heuristicValue(),gameState.step);
  }

  //this method definately works. child nodes are created with a move and an 
  //updated board and MAX value
  //which determines if they are the maximizing or minimizing players game states.
  gameState.children = gameState.findPossibleStates();

  if(state.MAX) { //maximizing player
      ValueStep best = null;

      for(Node child: gameState.children) {

          ValueStep vs = new ValueStep(minimax(child,depth+1,alpha,beta).value,child.move);

          //values updated here if needed
          if(best==null || vs.value > best.value) best = vs;

          if(vs.value > alpha) alpha = vs.value;

          if(alpha >= beta) break;
      }

      return best;

  } else { //minimizing player
      ValueStep best = null;

      for(Node child: gameState.children) {

          ValueStep vs = new ValueStep(minimax(child,depth+1,alfa,beta).value,child.move);

          if(best==null || vs.value < best.value) best = vs;

          if(vs.value < beta) beta = vs.value;

          if(alpha >= beta) break;
      }

      return best;
  }

}

起初,我认为问题出在我的评估功能上,但如果是,我找不到它。在这个游戏中,两个玩家都有一个分数,我的函数只是从分数差中计算启发式值。在这里:

public int heuristicValue() {

       //I calculate the score difference here in this state and save it in 
       //the variable scoreDiff. scoreDiff will be positive if I am winning 
       //here, negative if im loosing.

        //"this" is a Node object here. If the game is over here, special
        //heuristic values are returned, depending on who wins (or if its a 
        //draw) 
        if(gameOver(this.board)) {
            if(scoreDiff>0) {
                return Integer.MAX_VALUE;  
            } else if(scoreDiff==0) {
                return 0;
            } else {
                return Integer.MIN_VALUE;
            }
        }

        int value = 0;
        value += 100*scoreDiff; //caluclate the heuristic value using the score differerence. If its high, the value will be high as well 

      return value;
  }

我已经把我的代码“翻译”成了英语,所以可能会有错别字。我相当确定问题就在这里的某个地方,但是如果你需要一些其他代码,我会更新问题。同样,我的玩家可以创造优势,但由于某种原因,它不会做出最终的胜利举动。我感谢你的帮助!

共有1个答案

雷献
2023-03-14

假设你的最小极大玩家处于一个可以证明它可以保证胜利的位置。通常会有许多不同的方式,它仍然可以保证最终的胜利。有些动作可能是瞬间的胜利,有些动作可能会不必要地拖累游戏…只要不是一个非常愚蠢的举动突然让对手获胜(或平局),它们都是胜利,它们都有相同的游戏理论价值(Integer.MAX_VALUE在你的代码中)。

你的最小最大算法并不区分这些移动,只是简单地播放恰好是你的< code>gameState.children列表中的第一个移动。这可能是一个快速、肤浅的胜利,也可能是一个缓慢、非常深刻的胜利。

有两种简单的方法可以让您的Minimax算法优先考虑快速获胜而不是缓慢获胜:

  1. 最好的选择(因为它还有许多其他优点)是使用迭代深化。您可以查找详细信息,但基本思想是首先进行深度限制为 1 的 Minimax 搜索,然后进行深度限制为 2 的另一个搜索,然后深度限制为 3,依此类推。一旦您的搜索之一证明获胜,您就可以终止搜索并玩该获胜的举动。这将使您的算法始终更喜欢最短的胜利(因为首先找到这些胜利)。
  2. 或者,您可以修改启发式 Value() 函数以合并搜索深度。例如,您可以返回 Integer.MAX_VALUE - 获胜仓位的深度。这将使更快的胜利实际上有一个稍微大的评价。
 类似资料:
  • leetcode糖果问题,这种做法为什么可行? leetcode糖果问题 这个官方题解并没有证明,只是说了一下过程。我有以下几点疑问: left[..]是在仅符合左规则下分的糖果最少的分配方案吗?同样的right[...]是在仅符合右规则下分的糖果最少的分配方案吗? 为什么取仅符合左规则的值和仅符合右规则的值的最大值可以同时符合左右规则呢? 就算符合左右规则,为什么这种方案下分的糖果是最少的呢?

  • 我试图使用贪婪算法来计算在JavaScript中达到一定数量所需的最低硬币数量 返回结果将是一个数组,由每个级别的硬币数量组成 我决定做一个函数来解决这个问题,但它不起作用 calculateChange函数包含两个参数:硬币值数组和金额。 第一步是初始化一个sum变量,该变量显示已调度的更改量。我还将创建一个数组变量,该变量将保存某个硬币的分配次数。 为此,我将迭代coins数组并将所有值设置为

  • 我已经提出了几个解决方案,但我认为它们的效率不高,而且我很难计算它们的复杂性。 计划A)对于我随机选择的[1,N]范围内的每一个整数,我检查它是否被占用。如果是,我重新滚动直到我得到一个未被占用的整数。这对于N的高阶数来说变得低效,因为碰撞非常高。 计划B)每次迭代时,我遍历数组的所有值,那些我没有占用的我会写在一个列表中。之后,我洗牌列表(例如通过Fisher-Yates shuffle?)并任

  • 问题内容: 在回答了这个问题之后,我很困惑为什么这段代码中的整数溢出而不是负数。奇怪,为什么这么精确的数字?为什么是0? 输出: 问题答案: 仅当的起始值为偶数时,才会发生这种情况。 根据JLS§15.17.1: 如果整数乘法溢出,则结果是数学乘积 的低阶位 ,以某种足够大的二进制补码格式表示。结果,如果发生溢出,则结果的符号可能与两个操作数值的数学积的符号不同。 如果我们以二进制格式而不是十进制

  • 问题内容: 我已经为Employee类的父类是抽象的并且父类中的clone()方法是抽象的编写了此克隆方法。我想用此代码复制Employee对象的原始数据类型,而不是复制每个原始数据单独键入,但是此代码在我调用clone()方法的行中有问题。(此代码在Employee类中) 错误是:来自对象类型的方法clone()不可见。 但是我的Employee类在类层次结构中,可以访问Object类中受保护的

  • 机器人可以走三种不同长度的步:1厘米、2厘米、3厘米。编写一个递归算法,找出机器人可以通过的不同方式的数量“d”