五子棋智能算法——博弈树编程实现一字棋(四)

一字棋指的是:在一个九宫格内率先连成三个字的取胜

 首先,基于前面决策树的讲解 博弈的棋类游戏等等 只要找到合适的估值函数都可以使用博弈树来实现 下面我们来使用博弈树完成一字棋的算法。

根据前面的算法思想我们算法大致分为几步:

1.对棋局落子有正确的估值

2.通过遍历建立博弈树

3.对博弈树进行α-β剪枝增快查找速度(这里由于数据量较小 放在最后一起讲解)

4.根据极大值 极小值搜索获取博弈树产生的结果

 

首先在我们假设电脑先走 这时通过

在博弈树中通过这段代码在open表中将所有棋局储存 并且打分

for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
if(closed[closedtop]->all[i][j]==N) //在firstox中已经将棋局传入
{
    opentop++;//新节点于open表入队
    open[opentop]=new OXchess;//开辟空间
    open[opentop]->should(closed[closedtop],closedtop,i,j,step);//对新节点进行合适的操作
}

 

在经历完一轮循环后 将所有的open的元素 入closed表 (此时closed中的所有元素 flag = 1)

也就是记录了计算机所有的落子位置 下面进行第二次循环 同理完成人类落子 。。。(可以一直模拟下去 但是随着模拟的回合增加 由于估值函数不可能完全拟合 会产生过拟合的现象)

并且如果完全模拟完所有的情况有9! = 362 880种情况 

此时编译器也会报错 这里我们将博弈树深度设为5 

会发现 AI出现了问题 由于拟合层数过多 但是估值函数较为粗糙 导致随着拟合次数的增加 会使估值的误差也快速上涨 导致出现过拟合的问题 

我们可以通过调整估值代码的参数来完成更多层数的拟合 通过观察可以发现这个问题是 对于我马上要形成三个棋子并且下一步是我下棋的估值过低 导致在不断的迭代过程中 自己形成二子的得分甚至高于防止对手形成三子 对于这种情况就要提高估值 在这个游戏中往后看两步足以取胜 我们选择迭代次数为2 也就是flagmax = 2

	void toscore()//得到当前局面score值的函数
	{
		score=0;//score复位为0
		int i,j,o,x,n;//i.j循环用,o,x,n分别代表某一路(连续三子为一路)上oxn棋子的数目
		for(i=0;i<3;i++)//横向
		{
			o=0;x=0;n=0;//每一路之前要复位置零
			for(j=0;j<3;j++)
			{
				if(all[i][j]==O)//o计数
					o++;
				if(all[i][j]==X)//x计数
					x++;
				if(all[i][j]==N)//n计数
					n++;
 
				if(o+n==3)//当这一路上只有O棋子与空棋子时
				{
					if(o==3)//O有3子
						score=score+999999;//这种棋面已赢,评估值无限大
					if(o==2)//O有2子
					{
						if(flag%2==1)//如果这种棋面的层数是奇数,说明下一步是计算机下O棋,当某一路上已有2个O子时,已经必胜
									//评估值很大,但要小于对方已赢棋面评估值的绝对值,否则会产生不去围堵对方的胜招,而自顾自做2连子的棋面
							score=score+20000;
						else//如果下一步是人类下棋,这种局面的评估值不是很大
							score=score+1000;
					}
					if(o==1)//O有1子
						score=score+100;//加一点评估值
				}
 
				if(x+n==3)//当这一路上只有X棋子与空棋子时
				{
					if(x==3)//X有3子
						score=score-99999;//人类已经赢的棋面,评估值无限小
									//但绝对值要小于计算机已赢棋面的绝对值,否则会产生明明自己走在某处就可以直接胜利还偏偏去围堵对方的胜招的情况
					if(x==2)//X有2子
					{
						if(flag%2==0)//如果下一步是人类下棋,评估值很小
							score=score-10000;
						else//如果下一步是计算机下棋,评估值不是很小
							score=score-1000;
					}
					if(x==1)//X有1子
						score=score-100;//减一点评估值
				}
 
				//此处没有写oxn都有的情况 因为这种情况 这一条路 谁也赢不了
			}
		}
		for(i=0;i<3;i++)//竖向,下面同上
		{
			o=0;x=0;n=0;
			for(j=0;j<3;j++)
			{
				if(all[j][i]==O)
					o++;
				if(all[j][i]==X)
					x++;
				if(all[j][i]==N)
					n++;
				if(o+n==3)
				{
					if(o==3)
						score=score+999999;
					if(o==2)
					{
						if(flag%2==1)
							score=score+20000;
						else
							score=score+1000;
					}
					if(o==1)
						score=score+100;
				}
				if(x+n==3)
				{
					if(x==3)
						score=score-99999;
					if(x==2)
					{
						if(flag%2==0)
							score
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值