【问题标题】:C# Minimax process terminated due to stackoverflowexceptionC# Minimax 进程因 stackoverflowexception 而终止
【发布时间】:2018-01-23 20:33:05
【问题描述】:

我一直在尝试用 C# 创建一个带有 minimax 功能的井字游戏。不幸的是,我在让 minimax 函数正常工作时遇到了问题。

    static double MiniMax(char[] gameState, int depth)
    {
        int bestMove = 0;
        double bestScore = -double.PositiveInfinity;
        if (maxDepth > 0)
        {
            for (int i = 0; i < 9; i++)
            {
                if (ValidMove(i, gameState))
                {
                    char[] clone = new char[board.Length];
                    board.CopyTo(clone, 0);
                    clone[i] = 'X';
                    double score = 0;
                    score += MinPlay(clone, maxDepth--);
                    if (score > bestScore)
                    {
                        bestMove = i;
                        bestScore = score;
                    }
                }
            }
        }
        return bestMove;
    }

    static double MinPlay(char[] gameState, int depth)
    {
        if (Win(gameState)) return -1;
        if (Draw(gameState)) return 0;
        double bestScore = double.PositiveInfinity;
        if (maxDepth > 0)
        {
            for (int i = 0; i < 9; i++)
            {
                if (ValidMove(i, gameState))
                {
                    char[] clone = new char[board.Length];
                    board.CopyTo(clone, 0);
                    clone[i] = 'O';
                    double score = 0;
                    score += MaxPlay(clone, maxDepth--);
                    if (score > bestScore)
                    {
                        bestScore = score;
                    }
                }
            }
        }
        return bestScore;
    }

    static double MaxPlay(char[] gameState, int depth)
    {
        if (Win(gameState)) return 1;
        if (Draw(gameState)) return 0;
        double bestScore = -double.PositiveInfinity;
        if (maxDepth > 0)
        {
            for (int i = 0; i < 9; i++)
            {
                if (ValidMove(i, gameState))
                {
                    char[] clone = new char[board.Length];
                    board.CopyTo(clone, 0);
                    clone[i] = 'X';
                    double score = 0;
                    score += MinPlay(clone, maxDepth--);
                    if (score > bestScore)
                    {
                        bestScore = score;
                    }
                }
            }
        }
        return bestScore;
    }

我使用此处的指南制作了这些功能:http://giocc.com/concise-implementation-of-minimax-through-higher-order-functions.html

运行程序时,一切正常,直到计算机必须轮到它。我收到错误“由于 StackOverflowException 而终止进程”。 我认为这是由无限递归引起的,但是在查看程序一段时间后,我不知道是什么原因造成的。

我已经编辑了代码,现在有了深度,并且 minplay 和 maxplay 循环在其中进行了有效移动检查。计算机现在采取行动,但由于某种原因,它只选择了第一个位置。如果玩家选择第一个位置作为他们的第一个移动计算机然后选择它旁边的位置,并且在下一回合它会在第一个位置上覆盖玩家。然后计算机停止移动。我不知道为什么会这样。

任何帮助将不胜感激!

【问题讨论】:

  • 我看到 MinPlay 调用 MaxPlay 而 MaxPlay 调用 MinPlay。
  • 你必须有一个深度值,否则它会运行很长时间。
  • MaxPlay 和 MinPlay 互相调用不是问题,因为当游戏板评估为赢/输时存在基本情况。问题是你没有通过做出“有效”的动作来改变游戏板。您只需要应用“x”或“o”来打开正方形。
  • 复制代码,不要输入。 depth 与 maxDepth 不同。
  • 井字游戏不需要深度限制器。您只需要一个赢/输基本案例。

标签: c# minimax


【解决方案1】:

将 MinPlay 和 MaxPlay 中的 for 循环更改为仅考虑空方格。看起来您也没有使用正在传入的 gameState。我不知道 board 是在哪里定义的。

for (int i = 0; i < 9; i++)
{ 
    if (ValidMove(i, gameState) {
        char[] clone = new char[gameState.Length];
        gameState.CopyTo(clone, 0);
        clone[i] = 'X';
        double score = MinPlay(clone);
        if (score > bestScore)
        {
            bestScore = score;
        }
    }
}
return bestScore;

编辑:

您将其更改为 score += 这是不正确的。 此外,您在 MinPlay 中的分数比较不正确。

    if (score < bestScore)
    {
        bestScore = score;
    }

【讨论】:

  • 我已将这些更改添加到我的代码中,但计算机总是选择第二个位置,然后选择第一个位置,然后停止移动。我开始认为我解决这个问题的方法存在更根本的问题。感谢所有的帮助。
  • 刚刚开始工作。原来我忘了重置最大深度。再次运行后,我意识到我不需要最大深度。
  • @jameshc 干得好!是的,井字游戏树非常小,您不必担心深度。
【解决方案2】:

这是因为MaxPlay 调用函数MinPlay 又调用函数MaxPlay 引起的,并且在每次连续调用后你没有做任何事情来改变游戏状态导致递归结束。您只需在“o”和“x”之间切换 clone[0],您的函数永远不会完成 for 循环的迭代。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-02
    • 2019-01-04
    • 1970-01-01
    • 1970-01-01
    • 2018-09-06
    • 1970-01-01
    • 2014-11-18
    相关资源
    最近更新 更多