我尝试使用minimax算法在C ++中编写简单版本的tic-tac-toe,但在尝试确定得分最佳的位置时遇到了问题。 minEval(最小值的返回分数),maxEval(返回最大分数)和playMove(确定要播放的位置然后播放移动)功能如下所示。
int maxEval(int board[9]) {
if (checkDraw(board)) {
return 0;
}
else if (checkWin(board)) {
return -1000;
}
int finalScore = -1000;
for (int i = 0; i < 9; i++) {
if (board[i] == 0) {
board[i] = 1;
int score = minEval(board);
if (score > finalScore) {
finalScore = score;
}
board[i] = 0;
}
}
return finalScore;
}
int minEval(int board[9]) {
if (checkDraw(board)) {
return 0;
}
else if (checkWin(board)) {
return 1000;
}
int finalScore = 1000;
for (int i = 0; i < 9; i++) {
if (board[i] == 0) {
board[i] = -1;
int score = maxEval(board);
if (score < finalScore) {
finalScore = score;
}
board[i] = 0;
}
}
return finalScore;
}
void playMove(int board[9], int player) {
int finalScore = player * -1000;
int position;
for (int i = 0; i < 9; i++) {
if (board[i] == 0) {
board[i] = player;
int score;
if (player == 1) {
score = maxEval(board);
}
else {
score = minEval(board);
}
if (player == 1 && score >= finalScore) {
finalScore = score;
position = i;
}
else if (player == -1 && score <= finalScore) {
finalScore = score;
position = i;
}
board[i] = 0;
}
}
board[position] = player;
}
当我测试不同位置以查看minEval和maxEval是否正确评估位置时,函数会返回正确的分数(最大胜利为1000,最小胜利为-1000,平局为0)。但是,当我使用playMove功能进行AI播放时,它会播放非常可疑的动作,并且几乎总是会进行“不正确”的动作。 这是我制作节目游戏的一个例子(自己):
我怀疑我设置位置的方式有问题,但我试图做出改变无济于事。关于评估函数有什么问题的任何建议?感谢。
以下是整个代码的链接:http://ideone.com/6791d4
答案 0 :(得分:0)
我会检查发现的变化而不仅仅是分数。你是在找到任何获胜的变种,还是对手最好的变种?
e.g。修改您的最小/最大Eval代码,以便将选择的移动添加到数组中。
顺便说一句,如果将最小/最大Eval例程合并为一个,可能更容易看到发生了什么。
警告未经审查的代码
int minmaxEval(int board[9], int player, int moves[9], int move) {
if (checkDraw(board)) {
return 0;
}
int finalScore = player * -1000;
if (checkWin(board)) {
return finalScore;
}
for (int i = 0; i < 9; i++) {
if (board[i] == 0) {
board[i] = player;
int score = minmaxEval(board, -player, moves, move+1);
if ( (player > 0 && score > finalScore) ||
(player < 0 && score < finalScore) ) {
finalScore = score;
moves[move] = i;
}
board[i] = 0;
}
}
return finalScore;
}
如果你在你的顶级常规中打印出移动[],你应该看到给出该分数的变化。不匹配会告知您对算法的理解,例如:当它找到胜利时它会停止。
一般来说,重要的是要有一种方法来仔细检查你的代码正在做你期望的。研究单元测试和测试驱动开发。
答案 1 :(得分:0)
感谢您的见解,我解决了这个问题。 playMove函数中存在一个错误,其中我使maxEval和minEval不匹配,这导致AI无法进行获胜或平局。因此,更正的代码是:
void playMove(int board[9], int player) {
int finalScore = player * -1000;
int position;
for (int i = 0; i < 9; i++) {
if (board[i] == 0) {
board[i] = player;
int score;
if (player == 1) {
score = minEval(board); //Previously Mismatched
}
else {
score = maxEval(board); //Previously Mismatched
}
if (player == 1 && score >= finalScore) {
finalScore = score;
position = i;
}
else if (player == -1 && score <= finalScore) {
finalScore = score;
position = i;
}
board[i] = 0;
}
}
board[position] = player;
}