- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
编辑:如果您想看看是否能让 AI 表现得更好,请上传完整的源代码:https://www.dropbox.com/s/ous72hidygbnqv6/MCTS_TTT.rar
编辑:搜索搜索空间并找到导致损失的移动。但是由于 UCT 算法,导致损失的移动并不经常被访问。
为了了解 MCTS(蒙特卡洛树搜索),我使用该算法为经典的井字游戏制作了 AI。我使用以下设计实现了该算法:
树策略基于 UCT,默认策略是执行随机移动直到游戏结束。我在实现过程中观察到,计算机有时会做出错误的举动,因为它无法“看到”特定的举动会直接导致损失。
例如: 请注意行动 6(红色方 block )的值(value)如何略高于蓝色方 block ,因此计算机标记了这个位置。我认为这是因为游戏策略是基于随机移动的,因此人类很有可能不会在蓝色框中输入“2”。如果玩家没有在蓝色框中输入 2,则计算机将获胜。
我的问题
1) 这是 MCTS 的已知问题还是实现失败的结果?
2) 可能的解决方案是什么?我正在考虑在选择阶段限制移动,但我不确定 :-)
核心MCTS的代码:
//THE EXECUTING FUNCTION
public unsafe byte GetBestMove(Game game, int player, TreeView tv)
{
//Setup root and initial variables
Node root = new Node(null, 0, Opponent(player));
int startPlayer = player;
helper.CopyBytes(root.state, game.board);
//four phases: descent, roll-out, update and growth done iteratively X times
//-----------------------------------------------------------------------------------------------------
for (int iteration = 0; iteration < 1000; iteration++)
{
Node current = Selection(root, game);
int value = Rollout(current, game, startPlayer);
Update(current, value);
}
//Restore game state and return move with highest value
helper.CopyBytes(game.board, root.state);
//Draw tree
DrawTree(tv, root);
//return root.children.Aggregate((i1, i2) => i1.visits > i2.visits ? i1 : i2).action;
return BestChildUCB(root, 0).action;
}
//#1. Select a node if 1: we have more valid feasible moves or 2: it is terminal
public Node Selection(Node current, Game game)
{
while (!game.IsTerminal(current.state))
{
List<byte> validMoves = game.GetValidMoves(current.state);
if (validMoves.Count > current.children.Count)
return Expand(current, game);
else
current = BestChildUCB(current, 1.44);
}
return current;
}
//#1. Helper
public Node BestChildUCB(Node current, double C)
{
Node bestChild = null;
double best = double.NegativeInfinity;
foreach (Node child in current.children)
{
double UCB1 = ((double)child.value / (double)child.visits) + C * Math.Sqrt((2.0 * Math.Log((double)current.visits)) / (double)child.visits);
if (UCB1 > best)
{
bestChild = child;
best = UCB1;
}
}
return bestChild;
}
//#2. Expand a node by creating a new move and returning the node
public Node Expand(Node current, Game game)
{
//Copy current state to the game
helper.CopyBytes(game.board, current.state);
List<byte> validMoves = game.GetValidMoves(current.state);
for (int i = 0; i < validMoves.Count; i++)
{
//We already have evaluated this move
if (current.children.Exists(a => a.action == validMoves[i]))
continue;
int playerActing = Opponent(current.PlayerTookAction);
Node node = new Node(current, validMoves[i], playerActing);
current.children.Add(node);
//Do the move in the game and save it to the child node
game.Mark(playerActing, validMoves[i]);
helper.CopyBytes(node.state, game.board);
//Return to the previous game state
helper.CopyBytes(game.board, current.state);
return node;
}
throw new Exception("Error");
}
//#3. Roll-out. Simulate a game with a given policy and return the value
public int Rollout(Node current, Game game, int startPlayer)
{
Random r = new Random(1337);
helper.CopyBytes(game.board, current.state);
int player = Opponent(current.PlayerTookAction);
//Do the policy until a winner is found for the first (change?) node added
while (game.GetWinner() == 0)
{
//Random
List<byte> moves = game.GetValidMoves();
byte move = moves[r.Next(0, moves.Count)];
game.Mark(player, move);
player = Opponent(player);
}
if (game.GetWinner() == startPlayer)
return 1;
return 0;
}
//#4. Update
public unsafe void Update(Node current, int value)
{
do
{
current.visits++;
current.value += value;
current = current.parent;
}
while (current != null);
}
最佳答案
我认为您的回答不应标记为已接受。对于 Tic-Tac-Toe,搜索空间相对较小,应该在合理的迭代次数内找到最佳 Action 。
看起来您的更新函数(反向传播)向不同树级别的节点添加了相同数量的奖励。这是不正确的,因为当前玩家在不同的树级别上是不同的。
我建议您从这个示例中看一下 UCT 方法中的反向传播: http://mcts.ai/code/python.html
您应该根据先前玩家在特定级别(示例中的 node.playerJustMoved)计算的奖励来更新节点的总奖励。
关于c# - 蒙特卡洛树搜索 : Implementation for Tic-Tac-Toe,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23803186/
我是初学者,所以我的代码很乱。我还没有完整地评论这个游戏,所以如果你需要澄清一些变量,我可以给你。 (顺便说一句,这是一个要求制作井字游戏的c++项目) 我的主要问题是,我将如何重复我的棋盘(每次有人
本文实例讲述了Python实现的井字棋(Tic Tac Toe)游戏。分享给大家供大家参考,具体如下: 说明 用python实现了井字棋,整个框架是本人自己构思的,自认为比较满意。另外,90%+
这个教程,我们将展示如何用python创建一个井字游戏。 其中我们将使用函数、数组、if条件语句、while循环语句和错误捕获等。 首先我们需要创建两个函数,第一个函数用来显示游戏板:
我正在尝试从命令行(使用终端)以相反的顺序搜索大文件。我找到了 tac 命令:http://clifgriffin.com/2008/11/25/tac-and-reverse-grep/ tac 是
在阅读时,我遇到了“中级语言”和“3AC”这两个术语。 据我了解,IL 是源代码编译过程中的中间“步骤”。更具体地说,我正在阅读有关字节码(Java)和 C 的内容。 我解释它的方式(如果错了请纠正我
我正在为C的Tic Tac Toe代码编写一个简单的游戏。我已经完成了大部分代码,但是我希望AI永不丢失。 我已经阅读了有关minimax算法的信息,但我不理解。如何使用此算法使计算机获胜或平局,但永
我正在尝试使用reactjs创建一个简单的井字棋应用程序,其中有两种模式:经典和图像,在经典模式下我可以选择显示 X 和 O,在图像模式下,我可以选择两个显示下面提到的两个图像。我的文件结构是: sr
我想将普通的三地址代码文件转换为 Java 字节码。已经有一些与此主题相关的问题,但没有得到解答 properly或question远远超出了我正在寻找的范围。 以《龙书》中的编译器前端生成的这段代码
我试图解决 Schwartz 的“学习 Perl”中的一个练习,这时我在编写的代码中偶然发现了意外的输出。我想知道我做错了什么。 Qn:实现一个类似于 unix 实用程序的简单 tac。 我的解决方案
我有一份非常通用的工作,不同的参数作为来自不同文件的上下文参数传递。但我仍然需要“硬编码”上下文文件名并在 TAC (Talend Administration Console) 中创建多个作业以供执
我现在想用我的代码做两件事。1) 检查获胜者2) 不让双方玩家在同一个位置进入eg.如果player1已经在board[0][0]='X'处输入了value,player2再次进入board[0][0
我有一个扭曲的 tac 文件 (twisted_service.py),其中包含代码: from twisted.application import service # application.py
我是 UNIX 编码的新手,我有一个文件需要逐行反向读取。该文件在 {} 中有代码段。然后我需要使用这个反向文件作为输入来运行一个 awk 脚本。我正在让我们的支持人员安装 tac,但在他们安装之前,
感谢这里人们的帮助,我成功地禁用了点击 div 并在已经使用 $(".pos").addClass('already-played'); 选择它们时覆盖它们; 以及 CSS 中的这个: .已经播放{
我有一个井字棋游戏,其中用户(x)玩CPU(o)。游戏开始时,CPU 将 (o) 放置在中心,并在用户之后移动到随机位置。游戏设置为循环,但一旦出现获胜者,它就会重置,并且不会显示“你赢/输的横幅”。
我试图在没有人工智能的情况下实现井字棋游戏。不知怎的,我的点击功能会自动触发。您能帮我理解为什么点击功能会自动触发吗?这是 HTML 代码片段。 Tic Tac Toe Gam
我正在制作一个井字游戏程序。我计划将 minimax 与它一起使用。我制作了一棵树,其中包含所有可能的游戏序列的空间,并且我正在寻找一种方法来填充它。我目前有这种类型: typedef struct
我在完成这项学校作业时遇到了问题。我想实现一种方法,其中代码显示 //call method to check for Winner,在每轮后检查获胜者。 我不确定该怎么做。我尝试过各种不同的方法。然
我正在尝试遵循本教程: https://www.youtube.com/watch?v=Db3cC5iPrOM 2:59 我听不懂他在说什么。 我不明白为什么他在构造函数(public static
问题很简单。我有一个 IMEI,我想从中检索 TAC。我该怎么做?如果我只有 IMEI,是否有办法识别 TAC 应该有多少位数字?是否需要明确知道设备的生产年份才能知道? 最佳答案 从头开始读取 8
我是一名优秀的程序员,十分优秀!