作者热门文章
- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在使用对抗性搜索技术与 AI 对手一起编写 Connect4 游戏,但我遇到了一些障碍。我觉得我离解决方案不远了,但可能存在问题,我正在转换观点(例如:我的评估分数基于哪个参与者的观点),在某处缺少减号或类似的东西那。
问题是,在我尝试过的变体中,当玩家有三连胜时 AI 选择不阻止玩家,否则 AI 会玩完美的游戏,或者他更喜欢阻止玩家,即使他有机会赢得比赛。搜索深度是偶数还是奇数似乎也很重要,因为人工智能在 6 层搜索中是头昏眼花的,这很明显表明出了什么问题。
搜索
使用的算法是具有 alpha-beta 剪枝的 negamax,实现如下:
private int Negamax(int depth, int alpha, int beta, Player player)
{
Player winner;
if (Evaluator.IsLeafNode(game, out winner))
{
return winner == player ? (10000 / depth) : (-10000 / depth);
}
if (depth == Constants.RecursionDepth)
{
return Evaluator.Evaluate(game, depth, player);
}
foreach (var move in moves)
{
int row;
if (board.DoMove(move, player, out row))
{
var value = -Negamax(depth + 1, -beta, -alpha, (Player)1 - (int)player);
board.UndoMove(move, row, player);
if (value > alpha)
{
alpha = value;
if (player == Player.AI)
{
bestColumn = move;
}
}
if (alpha >= beta)
{
return alpha;
}
}
}
return alpha;
}
//c1r1
table[0][0] = new int[3];
table[0][0][0] = 21;
table[0][0][1] = 27;
table[0][0][2] = 61;
public bool DoMove(int column, Player p, out int row)
{
row = moves[column];
if (row >= 0)
{
Cells[column + row * Constants.Columns] = p;
moves[column]--;
var combinations = this.Game.PlayerCombinations[p];
foreach (int i in TerminalPositionsTable.Get(column,row))
{
combinations[i]++;
}
return true;
}
else
{
return false;
}
}
UndoMove
的做法当然是相反的。 .
Player.Human
,该表将在索引 21、27 和 61 处填充值 1。如果我在也是双赢组合 27 的一部分的单元格中执行另一个移动,则玩家组合表在索引 27 处增加到 2。
public static int Evaluate(Game game, int depth, Player player)
{
var combinations = game.PlayerCombinations[player];
int score = 0;
for (int i = 0; i < combinations.Length; i++)
{
switch (combinations[i])
{
case 1:
score += 1;
break;
case 2:
score += 5;
break;
case 3:
score += 15;
break;
}
}
return score;
}
aiScore - humanScore
的组合,或者只是总是从
Player.AI
的角度来看,诸如此类。但我已经走到了死胡同,我尝试过的每一个组合都有很大的缺陷。
最佳答案
这些东西让我的大脑受伤,所以我不确定这个答案是正确的,但是这里是。
在 negamax 中,分数总是相对于当前移动的玩家进行评估。如果是白棋,那么高分对白棋有利。如果是黑棋,那么高分对黑棋有利。因此,如果您有一个叶节点,那么分数是 +inf 还是 -inf 并不取决于该节点是白人获胜还是黑人获胜,而是取决于您当前正在评估的玩家是否获胜。替换这个:
return winner == Player.AI ? (10000 / depth) : (-10000 / depth);
return winner == player ? (10000 / depth) : (-10000 / depth);
return player == Player.AI ? score : -score;
return score;
关于c# - 对抗性搜索问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3169826/
我是一名优秀的程序员,十分优秀!