我正在尝试为井字游戏创建一个简单的AI,但它不起作用;当棋盘填满时(强行搜索到第一个分支的最终节点),我会得到一个 ‘std::out_of_range’ 异常,我还没有找到解决方案。
如果我在0,0位置下X棋子,它会在第10次迭代后在返回最佳移动的代码 return jogadas.at(melhorMov); // return best move
处崩溃。
(如果您愿意,可以在这里查看适用于Windows MingW的完整代码 这里)
(上图显示的是强行搜索的步骤,而不是实际的游戏)
AI算法:
-
移动/启动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); //将最佳移动放置在棋盘上}
-
极小极大算法代码
#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); // 返回最佳移动}
-
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
回答: