蒙特卡洛树搜索(MCTS)实现简易五子棋AI
蒙特卡洛树搜索算法可以通过自我对弈模拟得到不同状态分支中获胜的概率,从而获得最优的策略。代码部分可以分为Node类和State类。Node类通过关联父节点和子节点实现树结构,同时保存每个节点的属性;State类描述游戏的规则并判断胜负。
模型结构参考了https://ai-boson.github.io/mcts/
先导入所需要的模块
import numpy as np
import random as rd
import copy
from collections import defaultdictVECTOR = 7 #棋盘的维度,五子棋一般是15*15,为了减少运算先使用7*7
SIMU_EPSDS = 5000 #自我对弈模拟的次数,越大代表自我对弈的次数越多,速度越慢
创建节点类
class Node():def __init__(self, state, parent=None, parent_action=None): self.state = stateself.parent = parentself.parent_action = parent_actionself.children = []self._untried_actions = Noneself._untried_actions = self.untried_actions()self._number_of_visits = 0self._results = defaultdict(int) self._results[1] = 0self._results[-1] = 0#q值代表当前节点胜利次数减去失败次数的差值def q(self): wins = self._results[1]loses = self._results[-1]return wins - loses#n值代表当前节点的访问次数def n(self): return self._number_of_visits#扩展子节点,即访问该节点的每个子节点 def expand(self): action = self._untried_actions.pop()next_state = self.state.play(action,0)child_node = Node(next_state, parent=self, parent_action=action)self.children.append(child_node)return child_nodedef untried_actions(self):untried_actions = copy.deepcopy(self.state.get_legal_actions())return untried_actions#生成树的逻辑是先判断该节点是否是最终状态,如果不是再判断是否完全扩展,如果不是则继续扩展该节点的子节点,否则,#从子结点中随机选择一个作为下一个要扩展节点def _tree_policy(self): current_node=selfwhile not current_node.is_terminal_node():if not current_node.is_fully_expanded():return current_node.expand()else:current_node=current_node.rd_child()return current_nodedef is_terminal_node(self):return self.state.is_game_over()def is_fully_expanded(self):return len(self._untried_actions) == 0#从所有的子节点(下一状态)中选择一个最优节点def best_child(self, c_param=0.1):current_state = self.state #UCT算法choices_weights = [(c.q() / c.n()) + c_param * np.sqrt((2*np.log(self.n()) / c.n())) for c in self.children] order = current_state.state[0]if order==1: #如果当前玩家是先手,则选取权重最大的子节点作为最优actionreturn self.children[np.argmax(choices_weights)] else: #如果当前玩家是后手,则选取权重最小的子节点(先手胜率最低的状态)作为最优actionreturn self.children[np.argmin(choices_weights)]def rd_child(self):current_state = self.statereturn rd.choice(self.children)#self.children[np.argmax(choices_weights)] #自我对弈模拟,从子结点中随机选取actiondef rollout(self):current_rollout_state = self.statewhile not current_rollout_state.is_game_over():possible_moves = current_rollout_state.get_legal_actions()action = self.rollout_policy(possible_moves)current_rollout_state = current_rollout_state.play(action,0)return current_rollout_state.game_result()def rollout_policy(self, possible_moves):return possible_moves[np.random.randint(len(possible_moves))] #rd.choice(possible_moves)#向上回溯,将该节点的胜负信息传到父节点def backpropagate(self, result):self._number_of_visits += 1.self._results[result] += 1.if self.parent:self.parent.backpropagate(result)#每个节点计算best action都要自我对弈(次数是SIMU_EPSDS)并记录结果,从中选出最优的子节点 def best_action(self):for i in range(SIMU_EPSDS):v=self._tree_policy()reward=v.rollout()v.backpropagate(reward)return self.best_child()
创建状态类
class State():def __init__(self,ini_state): #初始化时导入棋盘的初始状态self.state=ini_statedef play(self,action,is_expl):#player:1 - attack, -1 - defensiveorder = self.state[0]board = copy.deepcopy(self.state[1])x=action[0]y=action[1]board[x][y]=ordernew_state=[-order,board]return State(new_state)def is_game_over(self):return self.game_result()!=999#判断当前游戏结果,返回结果是1 - 先手赢,-1 - 后手赢,0 - 未分胜负,没有空余点,游戏和棋结束,999 - 未分胜负,继续游戏def game_result(self):#遍历判断纵向是否五连,前两行和倒数两行不用判断for i in range(2,VECTOR-2):for j in range(VECTOR):if self.state[1][i-2][j]==self.state[1][i-1][j]==self.state[1][i][j]==self.state[1][i+1][j]==self.state[1][i+2][j]!=0:return self.state[1][i][j]#遍历判断横向是否五连,前两列和倒数两列不用判断for i in range(VECTOR):for j in range(2,VECTOR-2):if self.state[1][i][j-2]==self.state[1][i][j-1]==self.state[1][i][j]==self.state[1][i][j+1]==self.state[1][i][j+1]!=0:return self.state[1][i][j] #遍历斜向是否五连,前两行、前两列、倒数两行、倒数两列不用判断for i in range(2,VECTOR-2):for j in range(2,VECTOR-2):if (self.state[1][i][j-2]==self.state[1][i][j-1]==self.state[1][i][j]==self.state[1][i][j+1]==self.state[1][i][j+1]!=0)\|\(self.state[1][i][j-2]==self.state[1][i][j-1]==self.state[1][i][j]==self.state[1][i][j+1]==self.state[1][i][j+1]!=0):return self.state[1][i][j]#若未分胜负,遍历是否还有空余落子点,若没有,结果是和棋结束游戏,返回0blank_count=0for i in range(VECTOR):for j in range(VECTOR):if (self.state[1][i][j]==0):blank_count+=1if blank_count==0:return 0else: #未分胜负胜负,游戏继续return 999 #获得当前棋盘中所有可落子的点def get_legal_actions(self): legal_actions=[] for i in range(VECTOR):for j in range(VECTOR):if self.state[1][i][j] == 0:legal_actions.append([i,j])return legal_actions
主函数,人机对弈模式,可选先后手
if __name__ == '__main__':#初始化状态state=np.zeros([VECTOR,VECTOR])order=1state=State([order,state])first='player' #'player' - 玩家先手 'ai' - 玩家后手while True:if first=='player':for i in state.state[1]:print(i)player_choice=[int(i) for i in input('input the loacation (x,y):').split(',')]state=state.play(player_choice,0)print('player:',player_choice)state=State([state.state[0],state.state[1]])for i in state.state[1]: print(i)tree=Node(state)ai_choice=tree.best_action().parent_actionstate=state.play(ai_choice,0)state=State([state.state[0],state.state[1]])print('ai:',ai_choice)else:state=State([state.state[0],state.state[1]])tree=Node(state)ai_choice=tree.best_action().state.state[1][-1]state=state.play(ai_choice,0)print('ai:',ai_choice)for i in state.state[1]:print(i)player_choice=[int(i) for i in input('input the loacation (x,y):').split(',')]state=state.play(player_choice,0)print('player:',player_choice)for i in state.state[1]:print(i)
暂时没有添加游戏结束后选项,游戏结束时会报错,while循环自动终止
蒙特卡洛树搜索(MCTS)实现简易五子棋AI相关推荐
- 蒙特卡洛搜索树python_python实现的基于蒙特卡洛树搜索(MCTS)与UCT RAVE的五子棋游戏...
更新 2017.2.23有更新,见文末. MCTS与UCT 下面的内容引用自徐心和与徐长明的论文<计算机博弈原理与方法学概述>: 蒙特卡洛模拟对局就是从某一棋局出发,随机走棋.有人形象地比 ...
- 面向初学者的蒙特卡洛树搜索MCTS详解及其实现
目录 0. 序言 1. 蒙特卡洛算法的前身今世 2. 蒙特卡洛搜索算法的原理 2.1 Exploration and Exploitation(探索与利用) 2.2 Upper Confidence ...
- 蒙特卡洛树搜索 MCTS
原文地址 http://mcts.ai/about/index.html 什么是 MCTS? 全称 Monte Carlo Tree Search,是一种人工智能问题中做出最优决策的方法,一般是在组合 ...
- 强化学习(八):Dyna架构与蒙特卡洛树搜索MCTS
强化学习(八):Dyna架构与蒙特卡洛树搜索MCTS 在基于表格型强化学习方法中,比较常见的方法有动态规划法.蒙特卡洛法,时序差分法,多步引导法等.其中动态规划法是一种基于模型的方法(Model- ...
- python实现的基于蒙特卡洛树搜索(MCTS)与UCT RAVE的五子棋游戏
转自: http://www.cnblogs.com/xmwd/p/python_game_based_on_MCTS_and_UCT_RAVE.html 更新 2017.2.23有更新,见文末 ...
- 蒙特卡洛树搜索 MCTS 入门
引言 你如果是第一次听到蒙特卡洛,可能会认为这是一个人名.那么你就大错特错,蒙特卡洛不是一个人名,而是一个地方,还一个赌场名!!!但是这不是我们的重点. 我们今天的主题就是入门蒙特卡洛树搜索, ...
- 蒙特卡洛树搜索(MCTS)的实例代码
另一篇博客对代码的讲解 原理: 在当前树节点(设为A)状态下,如果所有子节点都展开了,则按UCT算法选择最优节点作为当前节点,循环下去,直到该节点有未展开的子节点,则从未展开的子节点里瞎选一个并展开它 ...
- 围棋AI,蒙特卡洛树搜索
目录 1 蒙特卡罗方法(Monte Carlo method) 2. 蒙特卡洛树搜索(Monte Carlo Tree Search,MCTS) 3 Upper Confidence Bounds(U ...
- 蒙特卡洛树搜索(MCTS)详解
蒙特卡洛树搜索(MCTS)详解 蒙特卡洛树搜索是一种经典的树搜索算法,名镇一时的 AlphaGo 的技术背景就是结合蒙特卡洛树搜索和深度策略价值网络,因此击败了当时的围棋世界冠军.它对于求解这种大规模 ...
最新文章
- 新一代企业内部故障报修软件功能实现
- 三个技巧,将Docker镜像体积减小90%
- HDU 2896 病毒侵袭 AC自动机
- Mybatis中的缓存
- php cookie expires,php cookie类(设置、获取、删除cookie值)
- Boost:prefer的使用测试程序
- 配置文件configSections节点使用实例 。
- 折半查找和二叉排序树的时间性能_leecode刷题----二分搜索与二叉查找(排序)树...
- javaweb c3p0连接oracle12c
- uni-app开发:tabar组件与顶部导航栏(功能开发篇)
- Android中Handler的使用方法——在子线程中更新界面
- [转载] python自带sqlite库_Python内置库SQlite3使用指南
- jquery 自定义事件
- 80%的Oracle JDK用户正在寻找免费的替代品!!!
- wordpress获取home_wordpress各种获取路径和URl地址的函数总结
- 手把手教你使用Python写贪吃蛇游戏(pygame)
- SCADA电力系统基础业务知识
- matlab 平滑曲线连接_如何使用Affinity Designer for mac编辑矢量曲线和形状
- threejs学习之透视相机与正交相机
- matlab将图像油画,photoshop图像滤镜——油画算法(含matlab与C代码)