【问题标题】:Determining the right position in minimax tic-tac-toe确定 minimax tic-tac-toe 中的正确位置
【发布时间】:2015-12-18 00:50:03
【问题描述】:

我尝试使用极小极大算法在 C++ 中编写一个简单版本的井字游戏,但在尝试确定得分最高的位置时遇到了问题。 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 玩游戏时,它会玩非常可疑的动作,并且几乎总是做出“不正确”的动作。 这是我让程序玩的游戏示例(与它自己一起玩):

我怀疑我将位置设置为 i 的方式有问题,但我尝试进行更改无济于事。关于评估功能有什么问题的任何建议?谢谢。

这里是整个代码的链接:http://ideone.com/6791d4

【问题讨论】:

  • 您的代码目前存在编译错误,请更正
  • 我的电脑上有一个头文件,所以我忘了在顶部添加定义,对此感到抱歉。我现在修好了,谢谢你的意见。
  • 我有几点建议:
  • @RichardSt-Cyr 我很想听听他们的意见!
  • 很抱歉。按 Enter 太快了。我有一些建议: 在 minEval 和 maxEval 中,您应该在检查平局之前评估您是否有赢家。如果第 9 步是获胜的一步,您将在检查是否获胜之前宣布平局。在评估中,如果游戏获胜,您没有任何条件停止。如果你可以评论你的代码来解释它应该做什么,我也许可以给你更多。

标签: c++ tic-tac-toe minimax


【解决方案1】:

我会检查发现的变化,而不仅仅是分数。您是在寻找任何获胜的变体,还是对手发挥得最好的变体?

例如修改您的最小/最大 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[],您应该会看到给出该分数的变化。那里的不匹配将告知您对算法的理解,例如当它找到胜利时它会停止吗?

一般来说,有一种方法可以仔细检查您的代码是否符合您的预期,这一点很重要。研究单元测试和测试驱动开发。

【讨论】:

  • 我的 min 和 max 函数没有找到获胜的举动,而只是告诉你位置是输还是赢,而返回的位置根本不是获胜的变化,看起来完全随机而且肯定会输。我一定会尝试实施您关于将 min 和 max 组合为一种方法的建议,并测试数组中的移动。我会回到这个线程并告诉你会发生什么。非常感谢您的意见!
【解决方案2】:

感谢您的见解,我解决了这个问题。 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;
}

【讨论】:

    猜你喜欢
    • 2017-08-30
    • 1970-01-01
    • 2019-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多