【发布时间】: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 不同。
-
井字游戏不需要深度限制器。您只需要一个赢/输基本案例。