我在Unity3D(C#)中开发一个带有AI的四连棋游戏。我使用了这个(德语)伪代码来实现MiniMax算法。
AI的表现仍然很差。它试图连成四子,尽管只有三个空位。AI总是按行进行操作,并且仅在必要时才进行阻挡。不幸的是,它有时也不会进行阻挡。
问题出在哪里?我遗漏了什么?
如果下一步没有赢或输的情况,如何让AI进行随机移动?
这是我的源代码:
minimaxDepth = 4
函数调用:Max (minimaxDepth, fieldCopy);
int Max (int depth, int[,] fieldCopy){ int maxValue = -9999; int moveValue; bool winAI = false; bool winHuman = false; bool isStoneBelow = false; for (int y = 0; y < 6; y++) { for (int x = 0; x < 7; x++) { if (y > 0) { //下面有棋子吗? if (fieldCopy [x, y - 1] == 1 || fieldCopy [x, y - 1] == 2) { isStoneBelow = true; } else { isStoneBelow = false; } } else { isStoneBelow = true; } //可能的移动? if (fieldCopy [x, y] != 1 && fieldCopy [x, y] != 2 && isStoneBelow == true) { isStoneBelow = false; fieldCopy [x, y] = 2; //模拟移动 winAI = false; winHuman = false; //有赢家吗? if (CheckWin (x, y, 2, fieldCopy)) { winAI = true; winHuman = false; } //没有更多的可能移动? if (depth <= 1 || winAI == true) { moveValue = evaluationFunction (winAI, winHuman); //评估移动 } else { moveValue = Min (depth - 1, fieldCopy); } fieldCopy [x, y] = 0; //重置模拟移动 if (moveValue > maxValue) { maxValue = moveValue; if (depth == minimaxDepth) { aiMoveX = x; // 下一步移动 } } } } } return maxValue;}int Min (int depth, int[,] fieldCopy){ int minValue = 9999; int moveValue; bool winAI = false; bool winHuman = false; bool isStoneBelow = false; bool loopBreak = false; for (int y = 0; y < 6; y++) { for (int x = 0; x < 7; x++) { if (y > 0) { //下面有棋子吗? if (fieldCopy [x, y - 1] == 1 || fieldCopy [x, y - 1] == 2) { isStoneBelow = true; } else { isStoneBelow = false; } } else { isStoneBelow = true; } //可能的移动? if (fieldCopy [x, y] != 1 && fieldCopy [x, y] != 2 && isStoneBelow == true) { isStoneBelow = false; fieldCopy [x, y] = 1; //模拟移动 winHuman = false; winAI = false; //有赢家吗? if (CheckWin (x, y, 1, fieldCopy)) { winHuman = true; winAI = false; } //没有更多的可能移动? if (depth <= 1 || winHuman == true) { moveValue = evaluationFunction (winAI, winHuman); //评估移动 } else { moveValue = Max (depth - 1, fieldCopy); } fieldCopy [x, y] = 0; //重置模拟移动 if (moveValue < minValue) { minValue = moveValue; } } } } return minValue;}int evaluationFunction (bool winAI, bool winHuman){ if (winAI) { return 1; } else if (winHuman) { return -1; } else { return 0; }}
谢谢你的帮助!
回答:
我认为问题出在你的评估函数上。你不应该仅仅评估是否有玩家赢了,而应该评估他们在游戏中的状态。一个可能的考虑是评估每个玩家最长的连续棋子链的长度。这可以准确地显示每个玩家离赢有多远,而不是在玩家即将赢但尚未赢时返回相同的值。
为了清晰起见,这里是伪代码:
int evaluationFunction (int depth){ // max_ai_chain 和 max_human_chain 是全局变量, // 应该在每次放置棋子时更新 if (depth % 2 == 0) // 假设AI在偶数深度计算(你提到你的深度是4) { return max_ai_chain; } else { return max_human_chain; }}