这里头歌平台上两题都能过。由于本人的python非常渣,代码可能有点繁琐,没有体现python的简洁,可以改进的地方自行改造

MinMax算法

对弈游戏时,假定两人都足够聪明,下一步都是对自己最有益、对对手最坏。那么针对这种情况,在A要下下一步时,存在一个针对A的对局势的判别函数,A肯定会向函数值大的下,而对手B势必会下在函数值下的地方。

1、题目描述

给出一个井字棋的棋盘状态,下一步为‘x’开始走步,给出‘x’下一步最佳走步列表。

2、踩坑

  • 首先这里的’x’和‘o’都是小写
  • 其次出现无法胜利(根节点无法得到1),答案应该为空集。
  • 最后个人走的一点小坑:那就是建立节点的时候没有设置children为空列表,也就是
    GameNode(map, val=0, deepID=0, parent=None, children=[])

3、主要想法

递归建树,同时在建树过程中调用minmax中min_value和max_value函数求出每个节点的value值。get_value函数主要针对叶子节点(没有子节点的节点)求值(也就是判断谁赢的问题)。is_terminal函数主要时判断是否为叶子节点(也就是下满了和出现三子连线的情况)。

4、 测试主函数

自己可以在钟意的编译器里将头歌代码写好后加上下面这段代码,然后就可以调试了
(ps:一定要用头歌的原题代码框架)

if __name__ == '__main__':# 读取棋盘状态,下一步执 xmap = [['x','o','x','\r'],['x','o','o','\r'],['_','_','_','\r']]# 创建一个根结点root = GameNode(map, val=0, deepID=0, parent=None, children=[])# 创建一颗博弈树game_tree = GameTree(root)game_tree.buildTree(game_tree.root)# 创建一个MinMax算法解决方案的对象min_max = MinMax(game_tree)# 调用MinMax算法,获取最优行动best_move = min_max.minmax(game_tree.root)# 打印最优行动for id_, move in enumerate(sorted(best_move)):print('best move way:')for i in range(3):for j in range(3):print(move[i][j])print('')

5、代码

# -*- coding:utf-8 -*-import copy     # 注意对象的深拷贝和浅拷贝的使用!!!class GameNode:'''博弈树结点数据结构成员变量:map - list[[]] 二维列表,三子棋盘状态val - int  该棋盘状态对执x棋子的评估值,1表示胜利,-1表示失败,0表示平局deepID - int 博弈树的层次深度,根节点deepID=0parent - GameNode,父结点children - list[GameNode] 子结点列表'''def __init__(self, map, val=0, deepID=0, parent=None, children=[]):self.map = mapself.val = valself.deepID = deepIDself.parent = parentself.children = childrenclass GameTree:'''博弈树结点数据结构成员变量:root - GameNode 博弈树根结点成员函数:buildTree - 创建博弈树'''def __init__(self, root):self.root = root                # GameNode 博弈树根结点def buildTree(self, root):'''递归法创建博弈树参数:root - GameNode 初始为博弈树根结点'''#请在这里补充代码,完成本关任务#********** Begin **********###创建root的子节点###fuc用来调用判断是否最终状态的函数mm=MinMax(False)if mm.isTerminal(root):root.val=mm.get_value(root)return ##递归遍历创造新的节点li=root.mapval=0for i in range(3):for j in range(3):if li[i][j]=='x' or li[i][j]=='o':continuenewLi=copy.deepcopy(li)newLi[i][j]='o' if root.deepID%2>0 else 'x'newNode=GameNode(map=newLi,parent=root,deepID=(root.deepID+1),children=[],val=0)root.children.append(newNode)self.buildTree(newNode)if root.deepID%2>0:root.val=mm.min_value(root)else:root.val=mm.max_value(root)#********** End **********#class MinMax:'''博弈树结点数据结构成员变量:game_tree - GameTree 博弈树成员函数:minmax - 极大极小值算法,计算最优行动max_val - 计算最大值min_val - 计算最小值get_val - 计算某棋盘状态中:执x棋子的评估值,1表示胜利,-1表示失败,0表示平局isTerminal - 判断某状态是否为最终状态:无空闲棋可走'''def __init__(self, game_tree):self.game_tree = game_tree      # GameTree 博弈树def minmax(self, node):'''极大极小值算法,计算最优行动参数:node - GameNode 博弈树结点返回值:clf - list[map] 最优行动,即x棋子的下一个棋盘状态GameNode.map其中,map - list[[]] 二维列表,三子棋盘状态'''#请在这里补充代码,完成本关任务#********** Begin **********#val=node.valresult=[]if val>0:for i in node.children:if i.val==val:result.append(i.map)return result#********** End **********#def max_value(self, node):'''计算最大值参数:node - GameNode 博弈树结点返回值:clf - int 子结点中的最大的评估值'''#请在这里补充代码,完成本关任务#********** Begin **********#li=node.childrenmax=-1for i in node.children:max=i.val if i.val>max else maxreturn max#********** End **********#def min_value(self, node):'''计算最小值参数:node - GameNode 博弈树结点返回值:clf - int 子结点中的最小的评估值'''#请在这里补充代码,完成本关任务#********** Begin **********#li=node.childrenmin=1for i in node.children:min=i.val if i.val<min else minreturn min#********** End **********#def get_value(self, node):'''计算某棋盘状态中:执x棋子的评估值,1表示胜利,-1表示失败,0表示平局参数:node - GameNode 博弈树结点返回值:clf - int 执x棋子的评估值,1表示胜利,-1表示失败,0表示平局'''#请在这里补充代码,完成本关任务#********** Begin **********#li=node.mapisEndI=1isEndJ=1##判断行列上是否存在直线for i in range(3):isEndI=0 if li[i][0]=='_' else 1isEndJ=0 if li[0][i]=='_' else 1for j in range(3):if li[i][j]=='_' or (isEndI>0 and li[i][j]!=li[i][0]):isEndI=0if li[j][i]=='_' or (isEndJ>0 and li[j][i]!=li[0][i]):isEndJ=0if isEndI+isEndJ<1:breakif isEndI>0:return 1 if li[i][0]=='x' else -1if isEndJ>0:return 1 if li[0][i]=='x' else -1##判断斜线上是否存在直线isEndR=0 if li[0][0]=='_' else 1isEndL=0 if li[2][0]=='_' else 1for i in range(3):if li[i][i]=='_' or (isEndR>0 and li[i][i]!=li[0][0]):isEndR=0if li[2-i][i]=='_' or (isEndL>0 and li[2-i][i]!=li[2][0]):isEndL=0if isEndR+isEndL<0:breakif isEndR>0:return 1 if li[0][0]=='x' else -1if isEndL>0:return 1 if li[2][0]=='x' else -1return 0#********** End **********#def isTerminal(self, node):'''判断某状态是否为最终状态:无空闲棋可走(无子结点)参数:node - GameNode 博弈树结点返回值:clf - bool 是最终状态,返回True,否则返回False'''#请在这里补充代码,完成本关任务#********** Begin **********# li=node.map##判断是否还有空位isFull=1for i in range(3):for j in range(3):if li[i][j]=='_':isFull=0breakif isFull==0:breakif isFull>0:return TrueisEndI=1isEndJ=1##判断行列上是否存在直线for i in range(3):isEndI=1isEndJ=1for j in range(3):if li[i][j]=='_' or (isEndI>0 and li[i][j]!=li[i][0]):isEndI=0if li[j][i]=='_' or (isEndJ>0 and li[j][i]!=li[0][i]):isEndJ=0if isEndI+isEndJ<1:breakif isEndI+isEndJ>0:return True##判断斜线上是否存在直线isEndR=1isEndL=1for i in range(3):if li[i][i]=='_' or (isEndR>0 and li[i][i]!=li[0][0]):isEndR=0if li[2-i][i]=='_' or (isEndL>0 and li[2-i][i]!=li[0][2]):isEndL=0if isEndR+isEndL<0:breakif isEndR+isEndL>1:return Truereturn False#********** End **********#

Alpha-Beta剪枝算法

在MinMax算法基础上,如果A行步的时候,已经知道下在一个特定位置,评估函数的值有多大,那么下一步行步选择的>=当前评估函数值。同理可得预测B行步时。
alpha剪枝:若任意极小值层节点的beta值小于或者等于它任一先辈极大值层节点的alpha值时候,可以中止该节点的搜索,最终该节点的倒退值确定为这个beta值
beta剪枝:若若任意极大值层节点的alpha值大于或者等于它任一先辈极大值层节点的beta值时候,可以中止该节点的搜索,最终该节点的倒退值确定为这个alpha值

1、题目描述

设置剪枝函数,减少决策树的搜索时间

2、主要想法

因为没有设置TreeNode记录深度的属性,所以采用max_value和min_value相互调用的设置,可以实现切换。
而max_value中拿到子节点的min_value返回值,判断是否更新下界为返回值(当前的子节点的评估值更大),然后判断下界是否超过上届(该节点的值比已经扫描过的兄弟节点小)则直接结束搜索,将当前节点的value设置为下界,返回当前节点的value。
而min_value中拿到子节点的max_value返回值,判断是否更新上界为返回值(当前的子节点的评估值更小),然后判断上界是否小于下届(该节点的值比已经扫描过的兄弟节点大)则直接结束搜索,将当前节点的value设置为上界,返回当前节点的value。

3、测试主函数

if __name__ == '__main__':# 数据输入raw_list = ['A', ['B', ('E', 3), ('F', 12), ('G', 8)], ['C', ('H', 2), ('I', 100), ('J', 100)], ['D', ('K', 14), ('L', 5), ('M', 2)]]# 把数据还原成它本身或者是能够转化成的数据类型#raw_list = literal_eval(raw)# 创建一棵博弈树game_tree = GameTree()game_tree.root = GameNode(raw_list[0])game_tree.buildTree(raw_list, game_tree.root)# AlphaBeta 剪枝算法alpha_beta = AlphaBeta(game_tree)best_node = alpha_beta.minmax_with_alphabeta(alpha_beta.game_tree.root)# 输出最优结点及其评估值print(best_node.name, best_node.val)

4、代码

# -*- coding:utf-8 -*-import copy     # 注意对象的深拷贝和浅拷贝的使用!!!class GameNode:'''博弈树结点数据结构成员变量:name - string 结点名字val - int  结点值children - list[GameNode] 子结点列表'''def __init__(self, name='', val=0):self.name = name        # charself.val = val          # intself.children = []      # list of nodesclass GameTree:'''博弈树结点数据结构成员变量:root - GameNode 博弈树根结点成员函数:buildTree - 创建博弈树'''def __init__(self):self.root = None                # GameNode 博弈树根结点def buildTree(self, data_list, root):'''递归法创建博弈树参数:data_list - list[] like this ['A', ['B', ('E', 3), ('F', 12)], ['C', ('H', 2)], ['D', ('K', 14)]]root - GameNode'''#请在这里补充代码,完成本关任务#********** Begin **********#del data_list[0]for i in data_list:if isinstance(i,int):root.val=ielse:new_data_list=list(i)new_node=GameNode(name=new_data_list[0],val=0)self.buildTree(new_data_list,new_node)root.children.append(new_node)return root#********** End **********#class AlphaBeta:'''博弈树结点数据结构成员变量:game_tree - GameTree 博弈树成员函数:minmax_with_alphabeta - 带AlphaBeta剪枝的极大极小值算法,计算最优行动max_value - 计算最大值min_value - 计算最小值get_value - 返回结点的值isTerminal - 判断某结点是否为最终结点'''def __init__(self, game_tree):self.game_tree = game_tree      # GameTree 博弈树def minmax_with_alphabeta(self, node):'''带AlphaBeta剪枝的极大极小值算法,计算最优行动参数:node - GameNode 博弈树结点返回值:clf - GameNode 最优行动的结点'''#请在这里补充代码,完成本关任务#********** Begin **********#self.max_value(node,1000,-1000)for i in node.children:if i.val==node.val:return i#********** End **********#def max_value(self, node, alpha, beta):'''计算最大值参数:node - GameNode 博弈树结点alpha - int 剪枝区间下限值beta - int 剪枝区间上限值返回值:clf - int 子结点中的最大的评估值'''#请在这里补充代码,完成本关任务#********** Begin **********#if self.isTerminal(node):return node.valfor i in node.children:new_beta=self.min_value(i,alpha,beta)beta=new_beta if new_beta>beta else betaif alpha<beta:breaknode.val=betareturn beta#********** End **********#def min_value(self, node, alpha, beta):'''计算最小值参数:node - GameNode 博弈树结点alpha - int 剪枝区间下限值beta - int 剪枝区间上限值返回值:clf - int 子结点中的最小的评估值'''#请在这里补充代码,完成本关任务#********** Begin **********#if self.isTerminal(node):return node.valfor i in node.children:new_alpha=self.max_value(i,alpha,beta)alpha=new_alpha if new_alpha<alpha else alphaif alpha<beta:breaknode.val=alphareturn alpha#********** End **********#def get_value(self, node):'''返回结点的值参数:node - GameNode 博弈树结点返回值:clf - int 结点的值,即 node.val'''#请在这里补充代码,完成本关任务#********** Begin **********#return  node.val#********** End **********#def isTerminal(self, node):'''判断某结点是否为最终结点(无子结点)参数:node - GameNode 博弈树结点返回值:clf - bool 是最终状态,返回True,否则返回False'''#请在这里补充代码,完成本关任务#********** Begin **********#if len(node.children)>0:return Falsereturn True#********** End **********#

头歌MinMax算法和AlphaBeta算法相关推荐

  1. 最清晰易懂的MinMax算法和Alpha-Beta剪枝详解

    最清晰易懂的MinMax算法和Alpha-Beta剪枝详解 参考文章 http://web.cs.ucla.edu/~rosen/161/notes/alphabeta.html https://ww ...

  2. BF算法和KMP算法

    给定两个字符串S和T,在主串S中查找子串T的过程称为串匹配(string matching,也称模式匹配),T称为模式.这里将介绍处理串匹配问题的两种算法,BF算法和KMP算法. BF算法 (暴力匹配 ...

  3. 使用Apriori算法和FP-growth算法进行关联分析

    目录 1. 关联分析 2. Apriori原理 3. 使用Apriori算法来发现频繁集 4. 使用FP-growth算法来高效发现频繁项集 5. 示例:从新闻网站点击流中挖掘新闻报道 扩展阅读 系列 ...

  4. 关联规则挖掘算法: Aprior算法和Fpgrowth算法

      关联规则挖掘的目的是挖掘不同物品(item)之前的相关性,啤酒和尿布的故事就是一个典型的成功例子.关联规则挖掘思想简单高效,在广告推荐领域也有较多的应用,主要用于推荐模型落地前的流量探索以及构建规 ...

  5. 数据结构与算法—最小生成树(Prim算法和Kruskal算法算法详解)

    前言 在数据结构与算法的图论中,(生成)最小生成树算法是一种常用并且和生活贴切比较近的一种算法.但是可能很多人对概念不是很清楚.我们看下百度百科对于最小生成树定义: 一个有 n 个结点的连通图的生成树 ...

  6. Algorithm:C++语言实现之字符串相关算法(字符串的循环左移、字符串的全排列、带有同个字符的全排列、串匹配问题的BF算法和KMP算法)

    Algorithm:C++语言实现之字符串相关算法(字符串的循环左移.字符串的全排列.带有同个字符的全排列.串匹配问题的BF算法和KMP算法) 目录 一.字符串的算法 1.字符串的循环左移 2.字符串 ...

  7. 操作系统之存储管理——FIFO算法和LRU算法

    操作系统之进程调度--优先权法和轮转法(附上样例讲解) 操作系统之银行家算法-详解流程及案例数据 操作系统之多线程编程-读者优先/写者优先详解 操作系统之存储管理--FIFO算法和LRU算法 操作系统 ...

  8. 若S作主串,P作模式串,试分别写出利用BF算法和KMP算法的匹配过程。

    目   录 题目: 百度文库-答案: (1) (2) MOOC标准答案: (1) (2) mooc答案-截图: 数据结构(C语言版)-严蔚敏2007 题目: 设字符串S='aabaabaabaac', ...

  9. Prim算法和Kruskal算法

       Prim算法和Kruskal算法都能从连通图找出最小生成树.区别在于Prim算法是以某个顶点出发挨个找,而Kruskal是先排序边,每次选出最短距离的边再找. 一.Prim(普里姆算法)算法: ...

最新文章

  1. 对XX证券报关于物联网操作系统的几个问题的答复
  2. 针对天气预报集合数据的时间层次聚类和可视化
  3. linux 网卡无效 设置_windows使用xftp连接本机上的linux虚拟机
  4. linux shell 字符串 数组,bash shell函数返回数组字符串
  5. SpringCloud(第一部分)
  6. 【Python Web】flask1
  7. Weblogic 12c中修改SERVER NAME的方法
  8. 记录最近的一些遇到的前端面试题
  9. 如何使用CNN进行物体识别和分类_可能我们之前都想错了:CNN的图像分类策略其实出奇的简单呢!...
  10. Java BigDecimal longValueExact()方法与示例
  11. Java中的main()方法是强制性的吗?
  12. python 每月每周_R-Python:获取每月,每周的索引点
  13. Docker 基础技术之 Linux namespace 详解
  14. 孙鑫VC学习笔记:第十二讲 (一) 介绍常量指针、指针常量,文本、二进制文件
  15. 宏观经济判断指标-GDP、CPI、PPI、PMI
  16. ps--修饰人像的皮肤瑕疵的步骤
  17. codec engine代码阅读四---CE_DIR/examples/ti/sdo/ce/examles/codecs/videnc_copy
  18. 批量修改pdf文件名称(一)
  19. umount卸载磁盘提示target is busy. (目标忙) 的问题解决方案
  20. BUUCTF Rabbit加密

热门文章

  1. 爬取国家统计局2020年五级联动行政区划(精确)
  2. 判断圆和线相切java_通过直线与圆交点数,轻松判断直线与圆关系,相离、相交、相切...
  3. Drools WorkBench的简介与使用
  4. 使用深度学习制作机器人大脑图纸
  5. magento 赠品_免费赠品发布:Silent Beauty壁纸
  6. 网页上爬取数据(Java版)通俗易懂
  7. 计算机系统基础期末复习
  8. 炫酷手持滚动弹幕生成小工具微信小程序源码多样化模板
  9. 【Mysql OCP】MySQL OCP备考准备篇~~~~完结版
  10. 屋顶建模(中国古代建筑)