【问题标题】:C++ Exception Minimax algorithm for TictactoeTictactoe 的 C++ 异常 Minimax 算法
【发布时间】:2015-12-14 03:43:35
【问题描述】:

我正在尝试制作一个简单的 AI 来玩tictactoe,但它不起作用;当板子填满时,我得到一个 'std::out_of_range'(暴力破解直到第一个分支的第一个最终节点),我完全没有找到解决方案。

如果我在 0,0 处下 X,它会在最佳移动返回时崩溃 return jogadas.at(melhorMov); // return best move 第 10 次迭代后。

(Windows MingW 的完整代码 here 如果您愿意)

(上面显示的游戏是暴力破解步骤,而不是实际游戏)

人工智能算法:

  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. 极小极大代码

    #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. 人工智能.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
    

【问题讨论】:

  • SO 不是代码调试服务。
  • 如果你建议,是的,我确实尝试调试代码,但我找不到修复它的方法,或者在逻辑中找到错误
  • 请明确指出抛出异常的代码行。
  • 如果我在 0,0 处玩 X,它会在返回最佳移动时崩溃 return jogadas.at(melhorMov); // return best move

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


【解决方案1】:

您的向量是空的(应该是空的,没有剩余的合法移动)。

在空向量上调用 at(0) 会引发异常,因为没有元素 0。

【讨论】:

  • 其实位置是0但是你是对的,我将初始条件设置为-1并验证了return和其他修改,它成功了,谢谢你的帮助
  • @Ollegn:我说的不是棋盘上的位置 (0, 0),而是向量中的索引 0。当向量为空时,0 不是合法索引。
  • 我在谈论向量,在 c++ 中,向量从 0 开始,然后继续 Notice that the first element has a position of 0 (not 1). Font
  • @Ollegn:你错过了我的意思。有效索引有i &lt; size()。当size() == 0 时,则0 不是有效索引。
  • @Ollegn:对。 0 不是问题,因为它太低了(索引从 0 开始而不是 1 是正确的)。这是一个问题,因为它太高了,当向量为空时。
猜你喜欢
  • 2021-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多