C++ 井字极小极大

C++ Tic tac toe minimax

我正在尝试创建一个 C++ 无与伦比的井字游戏 AI。看了几个关于这个主题的视频后,我想我已经明白了。屏幕上会弹出一条错误消息“表达式:矢量下标超出范围”。我相信错误来自 availableMoves() 函数。但是我不知道为什么。 游戏本身运行良好。任何帮助将不胜感激。

<pre>#include <iostream> #include <vector> #include <ctime> bool in(std::vector<int> v, int element) { for (int i = 0; i < v.size(); i++) { if (element == v[i]) { return true; } } return false; } class Board { private: char board[3][3] = { {'1', '2', '3'}, {'4', '5', '6'}, {'7', '8', '9'} }; public: void displayBoard() { std::cout << "___________________" << std::endl; for (int i = 0; i < 3; i++) { std::cout << "| "; for (int j = 0; j < 3; j++) { std::cout << board[i][j] << " | "; } std::cout << std::endl; } std::cout << "___________________" << std::endl; } std::vector<int> availableMoves() { std::vector<int> moves; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (board[i][j] != 'X' && board[i][j] != 'O') { moves.push_back(i * 3 + j); } } } return moves; } void move(int choice, char mark) { int y = choice / 3; int x = choice - y * 3; board[y][x] = mark; } void revert(int choice) { int y = choice / 3; int x = choice - y * 3; board[y][x] = (char)choice + 48; } int checkWin() { for (int i = 0; i < 3; i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2]) { if (board[i][0] == 'X') { return 1; } else if (board[i][0] == 'O') { return -1; } } } for (int i = 0; i < 3; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i]) { if (board[0][i] == 'X') { return 1; } else if (board[0][i] == 'O') { return -1; } } } if (board[0][0] == board[1][1] && board[1][1] == board[2][2]) { if (board[0][0] == 'X') { return 1; } else if (board[0][0] == 'O') { return -1; } } if (board[0][2] == board[1][1] && board[1][1] == board[2][0]) { if (board[0][2] == 'X') { return 1; } else if (board[0][2] == 'O') { return -1; } } return 0; } int evaluate() { return (checkWin() * -1) * (availableMoves().size() + 1); } Board& operator=(Board& b) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { board[i][j] = b.board[i][j]; } } return (*this); } }; class TicTacToe { private: Board board; int turn; int searches = 0; public: TicTacToe() { std::srand(time(0)); turn = std::rand() % 2; } int minimax(int depth, Board curBoard, bool is_max) { searches++; if (depth == 0 || curBoard.checkWin() != 0) { return board.evaluate(); } if (is_max) { int max_eval = -2147483647; for (int i = 0; i < curBoard.availableMoves().size(); i++) { curBoard.move(curBoard.availableMoves()[i], 'O'); depth -= 1; int eval = minimax(depth, curBoard, false); curBoard.revert(curBoard.availableMoves()[i]); if (eval > max_eval) { max_eval = eval; } } return max_eval; } if (!is_max) { int min_eval = 2147483647; for (int i = 0; i < curBoard.availableMoves().size(); i++) { curBoard.move(curBoard.availableMoves()[i], 'X'); depth -= 1; int eval = minimax(depth, curBoard, true); curBoard.revert(curBoard.availableMoves()[i]); if (eval < min_eval) { min_eval = eval; } } return min_eval; } } void game() { while (board.checkWin() == 0 && board.availableMoves().size() != 0) { board.displayBoard(); if (turn % 2 == 0) { std::cout << std::endl; int choice; std::cout << "Enter Your Move: "; std::cin >> choice; choice -= 1; while (!in(board.availableMoves(), choice)) { std::cout << "Enter A Valid Move: "; std::cin >> choice; } board.move(choice, 'X'); std::cout << std::endl; turn++; } board.displayBoard(); if (board.checkWin() != 0) { break; } if (turn % 2 == 1) { int ai = minimax(9 - (turn % 2), board, true); std::cout << searches; std::cin.get(); turn++; } } if (board.checkWin() == 1) { std::cout << "You Won" << std::endl; } else if (board.checkWin() == -1) { std::cout << "You Lost" << std::endl; } else { std::cout << "Tie" << std::endl; } std::cout << "Would You Like To Play Again Y/N: "; char playAgain; std::cin >> playAgain; if (playAgain == 'Y') { Board newBoard; board = newBoard; game(); } } }; int main() { TicTacToe ticTacToe; ticTacToe.game(); }

你知道如何debug吗?如果没有,你绝对应该学习这个,它非常有帮助。但这是我发现的一些事情。

问题不在availableMoves(),而在minimax(),更准确地说是在程序调用curBoard. revert(curBoard. availableMoves()[i]).

的第215行
void revert(int choice)
{
    int y = choice / 3;
    int x = choice - y * 3;
    board[y][x] = (char)choice + 48;
}

for (int i = 0; i < curBoard.availableMoves().size(); i++)
        {
            curBoard.move(curBoard.availableMoves()[i], 'X');
            depth -= 1;
            int eval = minimax(depth, curBoard, true);
            curBoard.revert(curBoard.availableMoves()[i]);
            if (eval < min_eval)
            {
                min_eval = eval;
            }
        }

错误发生在函数revert中,但我不确定为什么。也许 availableMoves 也 returns 有问题。变量 i 在 for 循环中永久为 0。所以有可能向量 moves 的位置 0 有问题,revert 无法处理。尝试自己调试,也许你会发现问题。