【问题标题】:Minimax algorithm: how to skip a turn?Minimax 算法:如何跳过一个转弯?
【发布时间】:2018-04-05 07:30:25
【问题描述】:

我正在使用带有井字游戏、黑白棋等的极小极大算法。

如何在算法中正确添加一个玩家跳过回合的可能性(当没有有​​效的移动时)?

01 function minimax(node, depth, maximizingPlayer)
02     if depth = 0 or node is a terminal node
03         return the heuristic value of node

04     if maximizingPlayer
05         bestValue := −∞
06         for each child of node
07             v := minimax(child, depth − 1, FALSE)
08             bestValue := max(bestValue, v)
09         return bestValue

10     else    (* minimizing player *)
11         bestValue := +∞
12         for each child of node
13             v := minimax(child, depth − 1, TRUE)
14             bestValue := min(bestValue, v)
15         return bestValue

谢谢。

【问题讨论】:

  • 应该在图中编码,而不是极小极大算法。
  • 这可能取决于游戏,但您通常不会在没有有效动作时输掉吗?这就是你的算法已经实现的。
  • 这取决于游戏。以下是黑白棋规则中的一句话:“玩家轮流轮流。如果一个玩家无法做出有效的移动,则将游戏传给另一个玩家。当两个玩家都无法移动时,游戏结束。”
  • 然后添加确定 node.Children 的代码,因为必须再次执行该步骤(对于其他玩家)。然后也可以解决“两个玩家”的问题。
  • 玩家没有移动的节点只有一个子节点,其棋盘状态不变。孩子还需要表明没有采取任何行动。该指示最初为 0。当没有移动时,它会增加,并在任一玩家移动时重置为 0。如果指示达到 2,则说明双方均未移动,游戏结束。

标签: minimax


【解决方案1】:

我为一个涉及传球的游戏实现了 Minimax。因此,pass 是用户可以执行的操作。在我的情况下,作为一名处于“通过”状态的玩家,你可以做一些“重新行动”,但这在这里无关紧要。

您可以将player->pass = true 添加为新状态并将其添加到树中,只要确保在将任何动作添加到树之前检查该玩家是否已经通过,然后跳过它。

然后您需要处理允许他们通过的次数。从现在开始,如果所有玩家都通过,游戏可以无限期地进行。这取决于游戏。在我的例子中,当一个玩家通过时,他们不能再做任何事情(除了我一开始提到的),然后当所有玩家都通过时,回合结束并且所有通过状态都被重置。

我的游戏中的一个例子:

std::list<GameState*> GameState::generateChildren(GameState& parent) {
  std::list<GameState*> children;
  PlayerBoard* currentBoard = parent.getCurrentPlayer();

  if (!currentBoard->pass) {
    GameState* childState = new GameState(parent);
    PlayerBoard *childBoard = childState->getCurrentPlayer();
    childBoard->pass = true;
    childBoard->nextPlayer();
    children.push_back(childState);

    //And then all your regular actions...
  }

  return children;
}

【讨论】:

    【解决方案2】:

    您可以编写一个函数GenerateValidMoves(node, player),它返回给定位置的玩家所有有效移动的列表。那么minimax程序的开始可以改写如下:

    function minimax(node, depth, maximizingPlayer)
        if depth == 0:
            return heuristicValueOfNode
        if generateValidMoves(node, currentPlayer) is empty:
            if generateValidMoves(node, opponentPlayer) is empty:
                return heuristicValueOfNode //here the game is finished since neither player can move
            return minimax(node, depth, not maximizingPlayer) //call minimax for the opponent
        if maximizingPlayer
            bestValue := −∞
            for each child of node
                v := minimax(child, depth − 1, FALSE)
                bestValue := max(bestValue, v)
            return bestValue
    
        else    (* minimizing player *)
            bestValue := +∞
            for each child of node
                v := minimax(child, depth − 1, TRUE)
                bestValue := min(bestValue, v)
            return bestValue
    

    【讨论】:

      猜你喜欢
      • 2011-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-09
      • 1970-01-01
      相关资源
      最近更新 更多