井字游戏随机AI

我正在开发一个井字游戏,旨在学习不同的算法及其实现方法,并为计算机对手设计不同的AI实现。首先尝试的是最简单的实现方式,即让计算机每次随机选择一个空格。

这种方法在一定程度上是有效的,但问题在于运行时间。每当调用aiRandMove()方法时,选择移动所需的时间越来越长,以至于在棋盘上进行了5次移动(计算机和用户的总和)后,程序似乎会卡住(尽管技术上并非如此)。

经过进一步的调试,我意识到这是可以预期的,因为aiRandMove()方法随机选择X和Y坐标,然后测试该移动是否合法。随着可用空间越来越少,合法的移动也越来越少,因此随机生成器尝试生成合法移动的失败次数越来越多。

我的问题是,有没有办法修改这个函数,至少能减少函数执行的时间?据我从谷歌搜索和自己分析问题所知,我无法想到在不牺牲函数“随机性”的情况下优化它的方法。我考虑过保留计算机尝试过的移动数组,但这并不能解决问题,因为这不会影响rand()生成重复数字的次数。以下是与此问题相关的函数代码:

//处理AI随机移动的函数,需要一个棋盘对象来测试移动的合法性和一个玩家对象来执行移动
//两者都通过引用传递,因为需要保存棋盘状态和玩家的评估数组的变化
char aiRandMove(Player &ai, Board &game){
   int tryX;
   int tryY; //存储计算机尝试的移动的变量
   bool moveMade = false;
   char winner;
   while(!moveMade){
      srand(time(NULL));//为rand()随机化种子
      tryX = rand() % 3;
      tryY = rand() % 3; //坐标是X和Y之间的随机数
      cout << "尝试移动 " << tryX << ", " << tryY << endl;
      if(game.isLegalMove(tryX, tryY)){
         winner = game.makeMove(tryX, tryY, ai);
         moveMade = true;
      }
   }
   return winner;
}

我还尝试将种子函数移出while循环(最初将其放入while循环中是为了“增加随机性”,尽管这在逻辑上是错误的,这也没有改善结果)。

如果一切都失败了,我可能会将这个方法标记为“简单”,并且只进行随机移动,直到我能判断是否需要阻止或进行获胜移动。但也许还有其他随机函数可以帮助解决这个问题。任何想法和评论都非常欢迎!


回答:

你需要从方程中移除无效的移动,例如使用以下伪代码,使用数组收集有效的移动:

possibleMoves = []for each move in allMoves:    if move is valid:        add move to possibleMovesmove = possibleMoves[random (possibleMoves.length)]

这样可以避免每次尝试移动时多次调用随机函数,因为数组中的所有可能性都是有效的。

另一种方法是从possibleMoves数组开始游戏,并在使用后移除每个可能性。

你还需要了解,最好只对随机数生成器进行一次种子设置,然后只使用它生成的数字。每次尝试获取随机数时都用time(0)进行种子设置,会确保在一整秒内得到相同的数字。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

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