井字游戏随机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

L1-L2正则化的不同系数

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

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

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

f1_score metric in lightgbm

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

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

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

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

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

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

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

发表回复

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