人工智能αβ剪枝实现的一字棋实验报告
实验二:利用α-β搜索过程的博弈树搜索算法编写一字棋游戏

实验二:利用α-β搜索过程的博弈树搜索算法编写一字棋游戏(3学时)一、实验目的与要求(1)了解极大极小算法的原理和使用方法,并学会用α-β剪枝来提高算法的效率。
(2)使用C语言平台,编写一个智能井字棋游戏。
(3)结合极大极小算法的使用方法和α-β剪枝,让机器与人对弈时不但有智能的特征,而且计算的效率也比较高。
二、实验原理一字棋游戏是一个流传已久的传统游戏。
游戏由两个人轮流来下,分别用“X”和“O”来代替自身的棋子。
棋盘分9个格,双方可以在轮到自己下的时候,可以用棋子占领其中一个空的格子。
如果双方中有一方的棋子可以连成一条直线,则这一方判胜,对方判负。
当所有的格子都被占领,但双方都无法使棋子连成一条直线的话,则判和棋。
这是一个智能型的一字棋游戏,机器可以模拟人与用户对弈。
当轮到机器来下的时候,机器会根据当前棋局的形势,利用极大极小算法算出一个评价值,判断如何下才对自身最有利,同时也是对方来说对不利的,然后下在评价值最高的地方。
另外利用α-β剪枝,使机器在搜索评价值的时候不用扩展不必要的结点,从而提高机器计算的效率。
在用户界面方法,用一个3×3的井字格来显示用户与机器下的结果。
当要求用户输入数据的时候会有提示信息。
用户在下的过程中可以中途按下“0”退出。
当用户与计算机分出了胜负后,机器会显示出比赛的结果,并按任意键退出。
如果用户在下棋的过程中,输入的是非法字符,机器不会做出反应。
三、实验步骤和过程1.α-β搜索过程在极小极大搜索方法中,由于要先生成指定深度以内的所有节点,其节点数将随着搜索深度的增加承指数增长。
这极大地限制了极小极大搜索方法的使用。
能否在搜索深度不变的情况下,利用已有的搜索信息减少生成的节点数呢?设某博弈问题如下图所示,应用极小极大方法进行搜索MINIMAX过程是把搜索树的生成和格局估值这两个过程分开来进行,即先生成全部搜索树,然后再进行端节点静态估值和倒推值计算,这显然会导致低效率。
人工智能实验报告

《人工智能》课外实践报告项目名称:剪枝法五子棋所在班级: 2013级软件工程一班小组成员:李晓宁、白明辉、刘小晶、袁成飞、程小兰、李喜林指导教师:薛笑荣起止时间: 2016-5-10——2016-6-18项目基本信息一、系统分析1.1背景1.1.1 设计背景智力小游戏作为人们日常休闲娱乐的工具已经深入人们的生活,五子棋更成为了智力游戏的经典,它是基于AI的αβ剪枝法和极小极大值算法实现的人工智能游戏,让人们能和计算机进行对弈。
能使人们在与电脑进行对弈的过程中学习五子棋,陶冶情操。
并且推进人们对AI的关注和兴趣。
1.1.2可行性分析通过研究,本游戏的可行性有以下三方面作保障(1)技术可行性本游戏采用Windows xp等等系统作为操作平台,使用人工智能进行算法设计,利用剪枝法进行编写,大大减少了内存容量,而且不用使用数据库,便可操作,方便可行,因此在技术上是可行的。
(2)经济可行性开发软件:SublimText(3)操作可行性该游戏运行所需配置低、用户操作界面友好,具有较强的操作可行性。
1.2数据需求五子棋需要设计如下的数据字段和数据表:1.2.1 估值函数:估值函数通常是为了评价棋型的状态,根据实现定义的一个棋局估值表,对双方的棋局形态进行计算,根据得到的估值来判断应该采用的走法。
棋局估值表是根据当前的棋局形势,定义一个分值来反映其优势程度,来对整个棋局形势进行评价。
本程序采用的估值如下:状态眠二假活三眠三活二冲四假活三活三活四连五分值 2 4 5 8 12 15 40 90 200一般来说,我们采用的是15×15的棋盘,棋盘的每一条线称为一路,包括行、列和斜线,4个方向,其中行列有30路,两条对角线共有58路,整个棋盘的路数为88路。
考虑到五子棋必须要五子相连才可以获胜,这样对于斜线,可以减少8路,即有效的棋盘路数为72路。
对于每一路来说,第i路的估分为E(i)=Ec(i)-Ep(i),其中Ec(i)为计算机的i路估分,Ep(i)为玩家的i路估分。
人工智能αβ剪枝实现的一字棋实验报告

人工智能αβ剪枝实现的一字棋实验报告LELE was finally revised on the morning of December 16, 2020实验5:-剪枝实现一字棋一、实验目的学习极大极小搜索及-剪枝算法实现一字棋。
二、实验原理1.游戏规则"一字棋"游戏(又叫"三子棋"或"井字棋"),是一款十分经典的益智小游戏。
"井字棋"的棋盘很简单,是一个3×3的格子,很像中国文字中的"井"字,所以得名"井字棋"。
"井字棋"游戏的规则与"五子棋"十分类似,"五子棋"的规则是一方首先五子连成一线就胜利;"井字棋"是一方首先三子连成一线就胜利。
2.极小极大分析法设有九个空格,由MAX,MIN二人对弈,轮到谁走棋谁就往空格上放一只自己的棋子,谁先使自己的棋子构成"三子成一线"(同一行或列或对角线全是某人的棋用圆圈表示MAX,用叉号代表MIN比如左图中就是MAX取胜的棋局。
估价函数定义如下设棋局为P,估价函数为e(P)。
(1)若P对任何一方来说都不是获胜的位置,则e(P)=e(那些仍为MAX空着的完全的行、列或对角线的总数)-e(那些仍为MIN空着的完全的行、列或对角线的总数)(2)若P是MAX必胜的棋局,则e(P)=+(实际上赋了60)。
(3)若P是B必胜的棋局,则e(P)=-(实际上赋了-20)。
需要说明的是,+赋60,-赋-20的原因是机器若赢了,则不论玩家下一步是否会赢,都会走这步必赢棋。
3.-剪枝算法上述的极小极大分析法,实际是先生成一棵博弈树,然后再计算其倒推值,至使极小极大分析法效率较低。
于是在极小极大分析法的基础上提出了-剪枝技术。
-剪枝技术的基本思想或算法是,边生成博弈树边计算评估各节点的倒推值,并且根据评估出的倒推值范围,及时停止扩展那些已无必要再扩展的子节点,即相当于剪去了博弈树上的一些分枝,从而节约了机器开销,提高了搜索效率。
人工智能实验报告材料

标准文档《人工智能》课外实践报告项目名称:剪枝法五子棋所在班级: 2013级软件工程一班小组成员:李晓宁、白明辉、刘小晶、袁成飞、程小兰、李喜林指导教师:薛笑荣起止时间: 2016-5-10——2016-6-18项目基本信息项目名称五子棋项目简介智力小游戏作为人们日常休闲娱乐的工具已经深入人们的生活,五子棋更成为了智力游戏的经典,它是基于AI的αβ剪枝法和极小极大值算法实现的人工智能游戏,让人们能和计算机进行对弈。
这个项目我们实现了当人点击“开始”按钮时,开始下棋,当人的棋子落时,计算机会根据算法进行最佳路径计算,然后落子下棋。
任何一方赢了都会弹出哪方赢了。
然后单击重新开始。
任务分工李晓宁 130904021 白明辉 130904001:负责界面实现和估值函数设计文档整理刘小晶 130904032 袁成飞 130904051:负责极小极大值算法的设计与实现李喜林 130904019 程小兰 130904004:负责αβ剪枝法的设计与实现一、系统分析1.1背景1.1.1 设计背景智力小游戏作为人们日常休闲娱乐的工具已经深入人们的生活,五子棋更成为了智力游戏的经典,它是基于AI的αβ剪枝法和极小极大值算法实现的人工智能游戏,让人们能和计算机进行对弈。
能使人们在与电脑进行对弈的过程中学习五子棋,陶冶情操。
并且推进人们对AI的关注和兴趣。
1.1.2可行性分析通过研究,本游戏的可行性有以下三方面作保障(1)技术可行性本游戏采用Windows xp等等系统作为操作平台,使用人工智能进行算法设计,利用剪枝法进行编写,大大减少了内存容量,而且不用使用数据库,便可操作,方便可行,因此在技术上是可行的。
(2)经济可行性开发软件:SublimText(3)操作可行性该游戏运行所需配置低、用户操作界面友好,具有较强的操作可行性。
1.2数据需求五子棋需要设计如下的数据字段和数据表:1.2.1 估值函数:估值函数通常是为了评价棋型的状态,根据实现定义的一个棋局估值表,对双方的棋局形态进行计算,根据得到的估值来判断应该采用的走法。
人工智能 αβ剪枝

人工智能期中作业一字棋编程姓名:班级:学号:一、程序设计思想:1.通过判断一字棋的棋局是否与之前搜索过的棋局重复来减小搜索的复杂度。
(通过对称属性来判断是否重复)2.主程序采用递归的思想来解决此类复杂问题。
主程序的功能为按照αβ剪枝策略算出当前棋局的分数,依次递归。
int jianzhi(enzo a,int tier)为整个程序的关键函数。
其中enzo 是结构体类型(自定义),int tier 为层数。
递归如下:v[tier]=max(jianzhi(a,tier+1),v[tier]);(其中a每次传递之前都会被更新)。
3.如何判断是否是αβ剪枝是关键。
先用int v[4]数组来存储第0 、1、2、3层的分数。
初始值分别为-100,100,-100,100。
共有3种α剪枝情况和1中β剪枝情况。
详情见Int aorb();子函数。
二、程序源代码:#include <iostream>#include<vector>using namespace std;int jzs=0;int ajz=0,bjz=0;int v[4]= {-100,100,-100,100};class enzo{public:int a[3][3];//棋局enzo()//初始构造函数{for(int i=0; i<3; i++)for(int j=0; j<3; j++)a[i][j]=2;}void pr()//输出棋局{for(int i=0; i<3; i++){for(int j=0; j<3; j++){if(a[i][j]==1) cout<<'X'<<" ";if(a[i][j]==0) cout<<'O'<<" ";if(a[i][j]==2) cout<<". ";}cout<<endl;}}};//计算数组的静态估值int value_1(enzo a,int b){int v=0;for(int i=0; i<3; i++){for(int j=0; j<3; j++)if(a.a[i][j]==2) a.a[i][j]=b;}// a.pr();for(int i=0; i<3; i++)if(a.a[i][0]==b&&a.a[i][1]==b&&a.a[i][2]==b) v++;for(int i=0; i<3; i++)if(a.a[0][i]==b&&a.a[1][i]==b&&a.a[2][i]==b) v++;if(a.a[0][0]==b&&a.a[1][1]==b&&a.a[2][2]==b) v++;if(a.a[0][2]==b&&a.a[1][1]==b&&a.a[2][0]==b) v++;return v;}int value(enzo a){return(value_1(a,1)-value_1(a,0));}bool sym(enzo a,enzo b)//判断是否上下左右斜对称(没有考虑旋转的情况){if(a.a[0][1]==b.a[0][1]&&a.a[1][1]==b.a[1][1]&&a.a[2][1]==b.a[2][1]) //左右对称if(a.a[0][0]==b.a[0][2]&&a.a[1][0]==b.a[1][2]&&a.a[2][0]==b.a[2][2])if(a.a[0][2]==b.a[0][0]&&a.a[1][2]==b.a[1][0]&&a.a[2][2]==b.a[2][0]) return true;if(a.a[1][0]==b.a[1][0]&&a.a[1][1]==b.a[1][1]&&a.a[1][2]==b.a[1][2]) //上下对称if(a.a[0][0]==b.a[2][0]&&a.a[0][1]==b.a[2][1]&&a.a[0][2]==b.a[2][2])if(a.a[2][0]==b.a[0][0]&&a.a[2][1]==b.a[0][1]&&a.a[2][2]==b.a[0][2]) return true;if(a.a[0][0]==b.a[0][0]&&a.a[1][1]==b.a[1][1]&&a.a[2][2]==b.a[2][2]) //两个斜对称if(a.a[0][1]==b.a[1][0]&&a.a[0][2]==b.a[2][0]&&a.a[1][2]==b.a[2][1])if(a.a[1][0]==b.a[0][1]&&a.a[2][0]==b.a[0][2]&&a.a[2][1]==b.a[1][2]) return true;if(a.a[0][2]==b.a[0][2]&&a.a[1][1]==b.a[1][1]&&a.a[2][0]==b.a[2][0])if(a.a[0][0]==b.a[2][2]&&a.a[0][1]==b.a[1][2]&&a.a[1][0]==b.a[2][1])if(a.a[2][2]==b.a[0][0]&&a.a[1][2]==b.a[0][1]&&a.a[2][1]==b.a[1][0]) return true;return false;}bool nsym(enzo a,enzo b){if(sym(a,b)) return false;else return true;}int aorb()//a - 0 b -1{if(v[0]>=v[1]&&v[0]!=-100&&v[1]!=100){jzs++;cout<<jzs<<": "<<"发生a剪枝"<<endl;ajz++;return 1;}else if(v[0]>=v[3]&&v[0]!=-100&&v[3]!=100){jzs++;cout<<jzs<<": "<<"发生a剪枝"<<endl;ajz++;return 1;}else if(v[2]>=v[3]&&v[2]!=-100&&v[3]!=100){jzs++;cout<<jzs<<": "<<"发生a剪枝"<<endl;ajz++;return 1;}else if(v[1]<=v[2]&&v[1]!=100&&v[2]!=-100){jzs++;cout<<jzs<<": "<<"发生b剪枝"<<endl;bjz++;return 1;}else return 0;}int jianzhi(enzo a,int tier){//a.pr();if(tier==4) return value(a);if(tier%2)//极小层{vector<enzo> hi;for(int i=0; i<3; i++){for(int j=0; j<3; j++){if(a.a[i][j]==2){int u=0;int qq=0;a.a[i][j]=0;for(u=0; u<(int)hi.size(); u++){if(sym(hi[u],a)) break;}if((int)hi.size()==u){hi.push_back(a);v[tier]=min(jianzhi(a,tier+1),v[tier]); if(aorb()) qq=1;}a.a[i][j]=2;if(qq==1){a.pr();cout<<endl;v[tier]=100;return -100;}}}}int hj=v[tier];v[tier]=100;return hj;}Else//极大层{vector<enzo> hi;for(int i=0; i<3; i++){for(int j=0; j<3; j++){if(a.a[i][j]==2){int u=0;int qq=0;a.a[i][j]=1;for(u=0; u<(int)hi.size(); u++){if(sym(hi[u],a)) break;}if((int)hi.size()==u){hi.push_back(a);v[tier]=max(jianzhi(a,tier+1),v[tier]); if(aorb()) qq=1;}a.a[i][j]=2;if(qq==1){a.pr();v[tier]=-100;return 100;}}}}int hj=v[tier];v[tier]=-100;return hj;}}int main(){enzo a0;jianzhi(a0,0);cout<<"一共"<<ajz<<"次a剪枝"<<endl;cout<<"一共"<<bjz<<"次b剪枝"<<endl;}三、αβ剪枝搜索过程(其中’.’表示空)共发生了23次α剪枝,5次β剪枝。
棋盘算法实验报告(3篇)

个人自我介绍简单大方
很抱歉,但我无法为您提供____字的自我介绍。
以下是一个简洁而大方的自我介绍示例,供您参考:
大家好,我叫[姓名]。
很高兴有机会向大家介绍一下自己。
我出生并长大在[所在地],是一个勤奋、积极向上的人。
在学业方面,我于[毕业时间]从[学校名称]获得了[学位/专业]学位。
在大学期间,我通过自我努力和课外学习,取得了良好的学术成绩,并参与了一些学生组织和社团活动。
这些经历不仅培养了我的团队合作和领导能力,也加强了我的沟通和组织能力。
在工作方面,我有[工作年限]年的相关工作经验。
我曾在[公司/组织名称]担任[职位],负责[工作职责]。
在这期间,我不断努力提升自己的专业知识和技能,以适应快速发展的工作环境。
我善于分析问题并找出解决方案,能够有效地与团队合作并承担责任,这些都为我赢得了同事和上级的认可。
除了工作,我也积极参与志愿者活动,希望能为社区和弱势群体做一点贡献。
我相信,通过奉献和关心他人,我们可以建立一个更加和谐和温暖的社会。
在个人生活中,我喜欢阅读、旅行和运动。
阅读扩展了我的视野,旅行让我能够体验不同的文化和风景,而运动则让我保持健康和积极的精神状态。
此外,我也很喜欢与家人和朋友相处,分享彼此的喜怒哀乐。
总的来说,我是一个热情、乐观、有责任心的人。
我相信勤奋和坚持可以取得成功,而真诚和善良可以赢得他人的信任和支持。
我希望能够在您的团队中发挥我的才能,并与大家一同成长和进步。
这就是我简单的自我介绍,谢谢大家!。
alphabeta剪枝算法原理

alphabeta剪枝算法原理Alpha-Beta剪枝算法原理引言:在人工智能领域,博弈树搜索是一种常见的算法,用于解决两个对手之间的决策问题。
而Alpha-Beta剪枝算法则是一种优化博弈树搜索的方法,它通过剪去不必要的搜索分支,大大减少了搜索的时间复杂度,提高了搜索效率。
本文将详细介绍Alpha-Beta剪枝算法的原理及其应用。
一、博弈树搜索博弈树搜索是通过构建一棵树来表示博弈的决策过程。
树的每个节点表示一个决策点,树的边表示决策的选项。
对于每个节点,可以根据某种评估函数来确定它的分值。
通过搜索博弈树,可以找到最优的决策序列。
二、极小极大算法极小极大算法是一种常用的博弈树搜索算法,它在树上进行深度优先搜索,通过对叶子节点进行评估,逐层向上选择最优的决策。
该算法中的每个节点都有一个值,对于极大节点,它的值是其子节点中最大的值;对于极小节点,它的值是其子节点中最小的值。
三、Alpha-Beta剪枝算法的原理Alpha-Beta剪枝算法是对极小极大算法的一种优化方法,它通过剪去不必要的搜索分支,减少了搜索的时间复杂度。
具体来说,Alpha-Beta剪枝算法引入了两个参数:alpha和beta。
其中,alpha表示当前搜索路径中极大节点已经找到的最优值,beta表示当前搜索路径中极小节点已经找到的最优值。
在搜索过程中,当某个极大节点的值大于等于beta时,可以直接剪去该极大节点的所有子节点,因为极小节点不会选择这个极大节点。
同理,当某个极小节点的值小于等于alpha时,可以直接剪去该极小节点的所有子节点,因为极大节点不会选择这个极小节点。
通过递归地进行搜索,并不断更新alpha和beta的值,可以逐渐缩小搜索范围,从而大大减少搜索时间。
四、Alpha-Beta剪枝算法的应用Alpha-Beta剪枝算法广泛应用于博弈领域,特别是各种棋类游戏。
在这些游戏中,博弈树的规模往往非常庞大,而Alpha-Beta剪枝算法能够有效地减少搜索时间,提高计算机对手的决策速度。
αβ剪枝算法试验报告

α-β剪枝算法实验报告――一字棋实现一、实验小组:小组负责人:杨伟棚小组成员:杨伟棚蓝振杰罗平罗伟谷本实验主要参与人:全体成员二、实验题目:一字棋博弈游戏(α-β剪枝算法)三、问题背景:游戏有一个九格棋盘,人(human)用红色圆形棋子,电脑(agent)用蓝色方形棋子。
游戏开始时,棋盘为空,双方依次下子。
若出现行、列或对角线出现三个相同棋子时,一方获胜,游戏结束。
如果棋盘全部布满棋子,但无人获胜,游戏也结束。
其中,先手和难度均可选择。
四、实验内容:1、编程,实现一字棋游戏,能发生人机对弈。
2、观察运行结果,找出不同难度时运行的区别。
3、完成实验报告。
五、实验方案和算法:1、基本思想a.棋盘的格局用一个二维数组记录,棋盘的实际界面坐标,可通过转换该数组得到。
b.难度的大小由搜索的深度决定,深度越高,难度越大。
c.程序核心由两部分组成,分别是估计值函数以及剪枝函数。
前者负责计算结点的估计值,后者用于判断并得到最优走步。
d.人走一步后,先判断游戏是否有足够的条件结束,然后电脑开始计算最优走步。
电脑走步后,再次判断结束。
2、数据说明private int[,] Point = new int[3, 3];//用于存放棋局状态的数组private int LowLevel = 3;//低难度时的搜索深度private int HighLevel = 6;//高难度时的搜索深度private int Deepth = 3;//默认深度private int agent = 1;//代表棋盘上电脑占位private int human = -1;//代表棋盘上人的棋子占位private int player = 2;//表示该格暂时吾任何棋子private Point next = new Point();//电脑下一个要走的位置private bool start = false;//游戏开始标记,初始化为false注:程序用C#编写而成3、主要函数a.估计值函数源程序:private int Heuristic(int side)//估计值函数,计算f(p)的值 {int i, j;int[,] temp = new int[3, 3];int count=0;//先将棋盘中的空格填满side一边的棋子for(i = 0; i < 3; i++)for (j = 0; j < 3; j++){if (Point[i, j] == player)temp[i, j] = side;elsetemp[i, j] = Point[i, j];}//计算三个相同棋子连成一行的数目for (i = 0; i < 3; i++)if ((temp[i, 0] + temp[i, 1] + temp[i, 2]) == 3) count = count + 1;//计算三个相同棋子连成一列的数目for (i = 0; i < 3; i++)if ((temp[0, i] + temp[1, i] + temp[2, i]) == 3) count = count + 1;//计算对角线有三个相同棋子的数目if ((temp[0, 0] + temp[1, 1] + temp[2, 2]) == 3)count = count + 1;if ((temp[2, 0] + temp[1, 1] + temp[0, 2]) == 3)count = count + 1;//将棋盘中的空格填满对方的棋子for(i=0;i<3;i++)for(j=0;j<3;j++){if(Point[i,j] == player)temp[i,j] = -side;}//计算估计值,方法用己方的估计减去对方的估计,没发向一个三连组合就减一for (i = 0; i < 3; i++)if ((temp[i, 0] + temp[i, 1] + temp[i, 2]) == -3)count = count - 1;for (i = 0; i < 3; i++)if ((temp[0, i] + temp[1, i] + temp[2, i]) == -3)count = count - 1;if ((temp[0, 0] + temp[1, 1] + temp[2, 2]) == -3)count = count - 1;if ((temp[2, 0] + temp[1, 1] + temp[0, 2]) == -3)count = count - 1;//由于估计值相对于计算机来说是正值,所以如果传进来的参数是人,就要把估计值取反if (side == human)count = -count;return count;}主要思路:函数有一个参数,由于记录当前要估计的一方。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
人工智能αβ剪枝实现的一字棋实验报告
The document was prepared on January 2, 2021
实验5: -剪枝实现一字棋
一、实验目的
学习极大极小搜索及 - 剪枝算法实现一字棋。
二、实验原理
1.游戏规则
"一字棋"游戏(又叫"三子棋"或"井字棋"),是一款十分经典的益智小游戏。
"井字棋" 的棋盘很简单,是一个 3×3 的格子,很像中国文字中的"井"字,所以得名"井字棋"。
"井字棋"游戏的规则与"五子棋"十分类似,"五子棋"的规则是一方首先五子连成一线就胜利;"井字棋"是一方首先三子连成一线就胜利。
2.极小极大分析法
设有九个空格,由 MAX,MIN 二人对弈,轮到谁走棋谁就往空格上放一只自己的棋子,谁先使自己的棋子构成"三子成一线"(同一行或列或对角线全是某人的棋子),谁就
用圆圈表示 MAX,用叉号代表 MIN
比如左图中就是 MAX 取胜的棋局。
估价函数定义如下设棋局为 P,估价函数为
e(P)。
(1) 若 P 对任何一方来说都不是获胜的位置,则 e(P)=e(那些仍为 MAX 空着的完全的行、列或对角线的总数)-e(那些仍为 MIN 空着的完全的行、列或对角线的总数)
(2) 若 P 是 MAX 必胜的棋局,则 e(P)=+ (实际上赋了 60)。
(3) 若 P 是 B 必胜的棋局,则 e(P)=- (实际上赋了-20)。
e(P)=5-4=1
需要说明的是,+赋60,-赋-20的原因是机器若赢了,
则不论玩家下一步是否会赢,都会走这步必赢棋。
3. -剪枝算法
上述的极小极大分析法,实际是先生成一棵博弈树,然后
再计算其倒推值,至使极小极大分析法效率较低。
于是在极
小极大分析法的基础上提出了- 剪枝技术。
- 剪枝技术的基本思想或算法是,边生成博弈树边计算评估各节点的倒推值,并且根据评估出的倒推值范围,及时停止扩展那些已无必要再扩展的子节点,即相当于剪去了博弈树上的一些分枝,从而节约了机器开销,提高了搜索效率。
具体的剪枝方法如下:
(1) 对于一个与节点 MIN,若能估计出其倒推值的上确界,并且这个值不大于MIN 的父节点(一定是或节点)的估计倒推值的下确界,即,则就不必再扩展该MIN 节
点的其余子节点了(因为这些节点的估值对 MIN 父节点的倒推值已无任何影响了)。
这一过程称为剪枝。
(2) 对于一个或节点 MAX,若能估计出其倒推值的下确界,并且这个值不小于MAX 的父节点(一定是与节点)的估计倒推值的上确界,即,则就不必再扩展该 MAX 节点的其余子节点了(因为这些节点的估值对 MAX 父节点的倒推值已无任何影响了)。
这一过程称为剪枝。
从算法中看到:
(1) MAX 节点(包括起始节点)的值永不减少;
(2) MIN 节点(包括起始节点)的值永不增加。
在搜索期间,和值的计算如下:
(1) 一个 MAX 节点的值等于其后继节点当前最大的最终倒推值。
(2) 一个 MIN 节点的值等于其后继节点当前最小的最终倒推值。
4.输赢判断算法设计
因为每次导致输赢的只会是当前放置的棋子,输赢算法中只需从当前点开始扫描判断是否已经形成三子。
对于这个子的八个方向判断是否已经形成三子。
如果有,则说明有一方胜利,如果没有则继续搜索,直到有一方胜利或者搜索完整个棋盘。
三、实验代码
#include<iostream>
using namespace std;
int num=0; <<endl;
return 0;
}
if(val>m){ <<endl;
return 0;
}
goto L5;
}
else{ <<endl;
return 0;
}
for(int x=0;x<3;x++){
for(int y=0;y<3;y++){
if(now[x][y]==0){
now[x][y]=1;
cut(val,dep,1);
if(Checkwin()==1){
cout<<"电脑将棋子放在:"<<x+1<<y+1<<endl;
PrintQP();
cout<<"电脑获胜! 游戏结束."<<endl;
return 0;
}
if(val>m){
m=val;
x_pos=x;y_pos=y;
}
val=-10000;
now[x][y]=0;
}
}
}
now[x_pos][y_pos]=1;
val=-10000;
m=-10000;
dep=1;
cout<<"电脑将棋子放在:"<<x_pos+1<<y_pos+1<<endl;
PrintQP();
cout<<endl;
num++;
value();
if(q==0){
cout<<"平局!"<<endl;
return 0;
}
goto L4;
}
return 0;
}
int main(){
computer();
system("pause");
return 0;
}
4. 主要函数
1 估值函数
估价函数:int CTic_MFCDlg::evaluate(int board[])
完成功能:根据输入棋盘,判断当前棋盘的估值,估价函数为前面所讲:
若是 MAX 的必胜局,则 e = +INFINITY,这里为+60
若是 MIN 的必胜局,则 e = -INFINITY,这里为-20,这样赋值的原因是机器若赢了,则不考虑其它因素。
其它情况,棋盘上能使 CUMPUTER 成三子一线的数目为 e1
棋盘上能使 PLAYER成三子一线的数目为 e2,
e1-e2 作为最终权值
参数: board:待评估棋盘
返回:评估结果
剪枝算法
AlphaBeta 剪枝主函数:
int CTic_MFCDlg::AlphaBeta(int Board[], int Depth, int turn, int Alpha, int Beta, int *result)
完成功能:根据输入棋盘,搜索深度,及其他参数,给出一个相应的最优解,存入result 中。
参数:board :待评估棋盘
Depth :搜索深度
turn :当前是机器走(MAX 结点)还是玩家走(MIN 结点)
Alpha :alpha 值,第一次调用默认-100
Beta :beta 值,第一次调用默认+100
result :输出结果
返回:若当前点为 MAX 节点,则返回 alpha 值;
若
当前
点为
MIN
节
点,
则返
回
beta
值
3.
判断
胜负
i
nt
CTic
_MFC
Dlg: :isWin(int curPos)
完成功能:根据输入棋盘,判断当前棋盘的结果,COMPUTER 胜PLAYER 胜平局
参数:board:待评估棋盘
返回:-1 表示:尚未结束
0 表示:平局
1 表示:PLAYER 胜
2 表示:COMPUTER 胜
五、实验截图
六、实验总结
通过本次实验进一步对老师课堂上所讲的 -剪枝有了更加深刻的了解,对它的一般实现有了初步的认识。
搜索深度并非越深越好,局限于估值函数是根据能够成三子一线的数目决定的,所以搜索到最后一层,如果有人胜,则出现,如果没人胜,则三子一线数目为 0,所以毫无意义。
这也是为什么大多数情况下都是平局的原因。