我正在尝试为四子棋(或连接4或连四)游戏实现MinMax算法。
我认为我已经理解了它的思路,应该建立一个可能的棋盘树到一定深度,评估它们并返回它们的分数,然后我们只需要取这些分数的最大值。
因此,aiChooseCol()通过调用MinMax()检查每个可能列的分数,并返回具有最高分数的列。
现在我不确定,这是调用MinMax()的正确方式吗?
检查temp = Math.Max(temp, 1000)是正确的吗?
我还没有制作启发式函数,但这应该至少识别出一个获胜的列并选择它,但目前它只是选择从左边开始的第一个空闲列...我无法弄清楚我做错了什么。
我认为我已经理解了它的思路,应该建立一个可能的棋盘树到一定深度,评估它们并返回它们的分数,然后我们只需要取这些分数的最大值。
因此,aiChooseCol()通过调用MinMax()检查每个可能列的分数,并返回具有最高分数的列。
现在我不确定,这是调用MinMax()的正确方式吗?
检查temp = Math.Max(temp, 1000)是正确的吗?
我还没有制作启发式函数,但这应该至少识别出一个获胜的列并选择它,但目前它只是选择从左边开始的第一个空闲列...我无法弄清楚我做错了什么。
private int AiChooseCol()
{
int best = -1000;
int col=0;
for (int i = 0; i < m_Board.Cols; i++)
{
if (m_Board.CheckIfColHasRoom(i))
{
m_Board.FillSignInBoardAccordingToCol(i, m_Sign);
int t = MinMax(5, m_Board, board.GetOtherPlayerSign(m_Sign));
if (t > best)
{
best = t;
col = i;
}
m_Board.RemoveTopCoinFromCol(i);
}
}
return col;
}
private int MinMax(int Depth, board Board, char PlayerSign)
{
int temp=0;
if (Depth <= 0)
{
// return from heurisitic function
return temp;
}
char otherPlayerSign = board.GetOtherPlayerSign(PlayerSign);
char checkBoard = Board.CheckBoardForWin();
if (checkBoard == PlayerSign)
{
return 1000;
}
else if (checkBoard == otherPlayerSign)
{
return -1000;
}
else if (!Board.CheckIfBoardIsNotFull())
{
return 0; // tie
}
if (PlayerSign == m_Sign) // maximizing Player is myself
{
temp = -1000;
for (int i = 0; i < Board.Cols; i++)
{
if (Board.FillSignInBoardAccordingToCol(i, PlayerSign)) // so we don't open another branch in a full column
{
var v = MinMax(Depth - 1, Board, otherPlayerSign);
temp = Math.Max(temp, v);
Board.RemoveTopCoinFromCol(i);
}
}
}
else
{
temp = 1000;
for (int i = 0; i < Board.Cols; i++)
{
if (Board.FillSignInBoardAccordingToCol(i, PlayerSign)) // so we don't open another branch in a full column
{
var v = MinMax(Depth - 1, Board, otherPlayerSign);
temp = Math.Min(temp, v);
Board.RemoveTopCoinFromCol(i);
}
}
}
return temp;
}
一些注释:
FillSignInBoardAccordingToCol()
返回一个布尔值表示是否成功。
board
类型有一个包含实际棋盘和玩家标记的 char[,]
数组。
这段代码位于 AI 玩家类中。
AiChooseCol
中,您没有将列i
传递给MinMax
,那么它如何知道您要求它评估哪一列? - juharrAiChooseCol
后仍无法正常工作。@juharr - shinzouelse
分支中取Min
值,而不是Max
。而且由于这是唯一的区别,所以你应该将if
-else
放在这部分代码周围。 - juharrMin
和Max
调用将前一个temp
与递归调用的返回值进行比较,而不是与最大和最小值进行比较。因此,您需要将其分配给变量var v = MinMax(...);
,然后执行temp = Math.Max(temp, v);
。并且temp
应该根据它是否为最大化玩家来初始化为1000
或-1000
。 - juharr