确定 minimax tic-tac-toe 中的正确位置
Determining the right position in minimax tic-tac-toe
我尝试使用 minimax 算法在 C++ 中编写一个简单版本的井字游戏,但是 运行 在尝试确定得分最高的位置时遇到了问题。 minEval (Returns score for min), maxEval(returns score for max) 和 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 是否正确评估位置时,函数 return 正确得分(1000 表示最大赢,-1000 表示最小赢,0 表示平局)。但是,当我使用 playMove 函数让 AI 下棋时,它下的棋步非常可疑,几乎总是走 "incorrect" 步棋。
这是我让程序玩的游戏示例(与自身一起玩):
我怀疑是我把position设置成i的方式有问题,但我尝试修改也无济于事。关于评估功能有什么问题的任何建议?谢谢
这是整个代码的 link:http://ideone.com/6791d4
我会检查发现的变化,而不仅仅是分数。您是找到任何获胜的变化,还是找到对手最好的变化?
例如修改您的 min/max Eval 代码,将选择的移动也添加到数组中。
顺便说一句,如果将 min/max 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;
}
如果您在顶级例程中打印出 moves[],您应该会看到给出该分数的变化。那里的不匹配会告知您对算法的理解,例如当它找到胜利时它是否停止。
一般来说,重要的是要有一种方法来仔细检查您的代码是否按照您的预期进行。研究单元测试和测试驱动开发。
感谢您的指点,我解决了问题。 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;
}
我尝试使用 minimax 算法在 C++ 中编写一个简单版本的井字游戏,但是 运行 在尝试确定得分最高的位置时遇到了问题。 minEval (Returns score for min), maxEval(returns score for max) 和 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 是否正确评估位置时,函数 return 正确得分(1000 表示最大赢,-1000 表示最小赢,0 表示平局)。但是,当我使用 playMove 函数让 AI 下棋时,它下的棋步非常可疑,几乎总是走 "incorrect" 步棋。 这是我让程序玩的游戏示例(与自身一起玩):
我怀疑是我把position设置成i的方式有问题,但我尝试修改也无济于事。关于评估功能有什么问题的任何建议?谢谢
这是整个代码的 link:http://ideone.com/6791d4
我会检查发现的变化,而不仅仅是分数。您是找到任何获胜的变化,还是找到对手最好的变化?
例如修改您的 min/max Eval 代码,将选择的移动也添加到数组中。
顺便说一句,如果将 min/max 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;
}
如果您在顶级例程中打印出 moves[],您应该会看到给出该分数的变化。那里的不匹配会告知您对算法的理解,例如当它找到胜利时它是否停止。
一般来说,重要的是要有一种方法来仔细检查您的代码是否按照您的预期进行。研究单元测试和测试驱动开发。
感谢您的指点,我解决了问题。 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;
}