2015-12-14 2 views
-2

Я пытаюсь сделать простой AI для игры в tictactoe, но он не работает; Я получаю «std :: out_of_range», когда доска заполняется (грубое форсирование до первых конечных узлов первой ветви), и я не нашел решения.C++ Exception Минимаксный алгоритм для Tictactoe

Если я играю в Х по 0,0, он падает на возврат лучшего хода return jogadas.at(melhorMov); // return best move после 10-й итерации.

(полный код для Windows, MingW here, если вы хотите)

Image of the error

(показанные игры выше, это шаги bruteforcing, а не фактическая игра)

AI алгоритм:

  1. Перемещение/запуск AI

    void IA::movimenta(){ //lauches the AI move action 
        std::cout << "**Pensando**" << std::endl; //little message 
        pensamentos = 0;       //counter of iterations 
        cmp = campo.getcampo();     //gets the pointer** to the tictactoe field 
        AiMove jogada = MelhorJogada(AIjogador); //gets the best move for the AIplayer 
        campo.joga(AIjogador,jogada.x,jogada.y); //puts the best move on the field 
    } 
    
  2. Minimax Код

    #include "ia.h" 
    #include <vector> 
    #include <iostream> 
    
    using namespace std; 
    
    IA::IA() 
    { 
    
    } 
    
    
    void IA::inicia(field &campo, field::jogador IAplayer){ 
        this->campo = campo; 
    
        this->AIjogador = IAplayer; 
        if(IAplayer == field::x){ 
         this->HUjogador = field::o; 
        }else{ 
         this->HUjogador = field::x; 
        } 
    
    } 
    
    
    void printacamp(field::campo **campo){ 
        cout << " 0 1 2" << endl; 
        for (int var = 0; var < 3; ++var) { 
         cout << var; 
         cout << "|"; 
         for (int var2 = 0; var2 < 3; ++var2) { 
    
          switch (campo[var][var2]) { 
          case field::NADA: 
           cout << " "; 
           break; 
          case field::x_c: 
           cout << "X"; 
           break; 
          case field::o_c: 
           cout << "O"; 
           break; 
          default: 
           break; 
          } 
    
          cout << "|"; 
         } 
         cout << endl; 
        } 
    } 
    
    void IA::movimenta(){ //lauches the AI move action 
        std::cout << "**Pensando**" << std::endl; //little message 
        pensamentos = 0;       //couter of iterations 
        cmp = campo.getcampo();     //gets the pointer** to the tictactoe field 
        AiMove jogada = MelhorJogada(AIjogador); //gets the best move for the AIplayer 
        campo.joga(AIjogador,jogada.x,jogada.y); //puts the best move on the field 
    } 
    
    AiMove IA::MelhorJogada(field::jogador jogador){ //bruteforce through the possible moves and searches for the best one 
        field::jogador vic = campo.checaJ(); // checks if someone wins the game (final node) 
        if(vic == AIjogador){    //if AIplayer wins 
         return AiMove(15);    //add 15 points 
        } else if(vic == jogador){   //if human wins 
         return AiMove(-15);   //add -15 points 
        } else if(vic == field::NINGJ){  //if its a tie (full board no winners) 
         return AiMove(0);    //score 0 
        }         //if none of those, the game is still in progress 
        std::vector<AiMove> jogadas;  //vector for moves, something tells me that it should be static but it gives alot of bugs and nosense moves (or no moves at all) 
        AiMove jogada;      //move for this iteration 
        pensamentos++;      //add counter 
        cout << pensamentos << endl;  //print counter 
        for (int y = 0; y < 3; ++y) {  //for each of the board 
         for (int x = 0; x < 3; ++x) { 
          if(cmp[x][y] == field::NADA){ // if its an empty space 
           jogada.x = x;    //gets the x,y of the empty space 
           jogada.y = y; 
           campo.jogaJ(jogador,jogada.x,jogada.y); //makes a move 
    
           printacamp(cmp);   //prints it on screen 
    
           if(jogador == AIjogador){ //if its max(AI) next is human 
            jogada.pontos = MelhorJogada(HUjogador).pontos; 
           }else{      //if its min(Human) next is AI 
            jogada.pontos = MelhorJogada(AIjogador).pontos; 
           } 
           jogadas.push_back(jogada); //store the score of the final node 
           campo.jogaJ(field::NADAJ,jogada.x,jogada.y); // delete the move made for testings 
          } 
         } 
        } 
        int melhorMov = 0;     // bestMove is 0 
        if(jogador == AIjogador){   // if AIturn(max) 
         int melhorPon = -1000000;  // best pontuation = -∞ 
         for (int var = 0; var < jogadas.size(); ++var) { //best move/points of the subbranches 
          if(jogadas.at(var).pontos > melhorPon){ 
           melhorMov = var; 
           melhorPon = jogadas.at(var).pontos; 
          } 
         } 
        } else {       //if human(min) 
         int melhorPon = 1000000;  //best pontution = +∞ 
         for (int var = 0; var < jogadas.size(); ++var) { //best move/points of the subbranches 
          if(jogadas.at(var).pontos < melhorPon){ 
           melhorMov = var; 
           melhorPon = jogadas.at(var).pontos; 
          } 
         } 
        } 
        return jogadas.at(melhorMov); // return best move 
    
    } 
    
  3. AI.h

    #pragma once 
    #ifndef IA_H 
    #define IA_H 
    #include "field.h" 
    #include <vector> 
    struct AiMove { 
        AiMove() {}; 
        AiMove(int Pontos) : pontos(Pontos) {} 
        int x; 
        int y; 
        int pontos; 
    }; 
    
    
    class IA 
    { 
    
    public: 
         IA(); 
         void inicia(field &camp, field::jogador IAplayer); 
         void movimenta(); 
    private: 
         field campo; 
         AiMove MelhorJogada(field::jogador HUjogador); 
         field::campo **cmp; 
         field::jogador HUjogador; 
         field::jogador AIjogador; 
         int pensamentos = 0; 
    
    }; 
    #endif // IA_H 
    
+1

SO не является услугой отладки кода. – ildjarn

+0

, если вы предлагаете, да, я попробовал debbuging код, но я не смог найти способ его исправить или найти ошибку в логике – Ollegn

+0

Пожалуйста, четко укажите строку кода, в которой генерируется исключение. –

ответ

1

Ваш вектор пуст (как это должно быть, там не осталось правовых движений).

Вызов at(0) на пустой вектор сгенерирует исключение, потому что нет ни одного элемента 0.

+0

действительно есть позиции в 0, но вы правы, я установил начальное условие на -1 и сделал проверку по возврату и другим изменениям, и это сработало, спасибо за вашу помощь – Ollegn

+0

@Ollegn: I ' m не говоря о позиции (0, 0) на доске, а индекс 0 в векторе. Когда вектор пуст, 0 не является юридическим индексом. –

+0

Im, говорящий о векторах, в векторах C++ начинается с 0 и выходит 'Обратите внимание, что первый элемент имеет позицию 0 (не 1).' [Font] (http://www.cplusplus.com/reference/vector/vector/at /) – Ollegn

Смежные вопросы