### C++ 异常处理在井字游戏中的极小极大算法

我正在尝试为井字游戏创建一个简单的AI,但它不起作用;当棋盘填满时(强行搜索到第一个分支的最终节点),我会得到一个 ‘std::out_of_range’ 异常,我还没有找到解决方案。

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

(如果您愿意,可以在这里查看适用于Windows MingW的完整代码 这里

错误的图片

(上图显示的是强行搜索的步骤,而不是实际的游戏)

AI算法:

  1. 移动/启动AI

    void IA::movimenta(){ //启动AI移动操作    std::cout << "**Pensando**" << std::endl; //小提示信息    pensamentos = 0;                          //迭代计数器    cmp = campo.getcampo();                   //获取井字游戏棋盘的指针**    AiMove jogada = MelhorJogada(AIjogador);  //获取AI玩家的最佳移动    campo.joga(AIjogador,jogada.x,jogada.y);  //将最佳移动放置在棋盘上}
  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(){ //启动AI移动操作    std::cout << "**Pensando**" << std::endl; //小提示信息    pensamentos = 0;                          //迭代计数器    cmp = campo.getcampo();                   //获取井字游戏棋盘的指针**    AiMove jogada = MelhorJogada(AIjogador);  //获取AI玩家的最佳移动    campo.joga(AIjogador,jogada.x,jogada.y);  //将最佳移动放置在棋盘上}AiMove IA::MelhorJogada(field::jogador jogador){ //通过可能的移动进行强行搜索并寻找最佳移动    field::jogador vic = campo.checaJ(); //检查是否有人赢得游戏(最终节点)    if(vic == AIjogador){                //如果AI玩家赢了        return AiMove(15);             //增加15分    } else if(vic == jogador){           //如果人类玩家赢了        return AiMove(-15);            //增加-15分    } else if(vic == field::NINGJ){      //如果是平局(棋盘已满无赢家)        return AiMove(0);               //得分0    }                                  //如果以上都不是,游戏仍在进行中    std::vector<AiMove> jogadas;        //移动向量,我感觉它应该是静态的,但这会导致很多错误和无意义的移动(或根本没有移动)    AiMove jogada;                      //本次迭代的移动    pensamentos++;                      //增加计数器    cout << pensamentos << endl;        //打印计数器    for (int y = 0; y < 3; ++y) {       //遍历棋盘的每一行        for (int x = 0; x < 3; ++x) {            if(cmp[x][y] == field::NADA){  //如果是空格                jogada.x = x;              //获取空格的x,y坐标                jogada.y = y;                campo.jogaJ(jogador,jogada.x,jogada.y); //进行移动                printacamp(cmp);           //在屏幕上打印                if(jogador == AIjogador){  //如果是AI(最大值)下一步是人类                    jogada.pontos = MelhorJogada(HUjogador).pontos;                }else{                     //如果是人类(最小值)下一步是AI                    jogada.pontos = MelhorJogada(AIjogador).pontos;                }                jogadas.push_back(jogada); //存储最终节点的得分                campo.jogaJ(field::NADAJ,jogada.x,jogada.y); //删除测试移动            }        }    }    int melhorMov = 0;                  //最佳移动是0    if(jogador == AIjogador){           //如果是AI回合(最大值)        int melhorPon = -1000000;       //最佳得分 = -∞        for (int var = 0; var < jogadas.size(); ++var) { //子分支的最佳移动/得分            if(jogadas.at(var).pontos > melhorPon){                melhorMov = var;                melhorPon = jogadas.at(var).pontos;            }        }    } else {                            //如果是人类(最小值)        int melhorPon = 1000000;        //最佳得分 = +∞        for (int var = 0; var < jogadas.size(); ++var) { //子分支的最佳移动/得分            if(jogadas.at(var).pontos < melhorPon){                melhorMov = var;                melhorPon = jogadas.at(var).pontos;            }        }    }    return jogadas.at(melhorMov); // 返回最佳移动}
  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

回答:

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注