Unity写的3D人工智能棋类博弈小游戏-四子棋

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sdhexu/article/details/86709474

前段时间看到有小朋友玩一种智力玩具,是一种棋类的木制玩具,玩家双方从木质的小盒子顶部放入棋子,棋子落下,双方谁先实现四子连珠(横着竖着斜着均可),即为胜利。见下图:
在这里插入图片描述
哈哈,这个创意真不错,作为一个码农,当时就想到能不能搞个智能的,让电脑来计算一哈如何胜利。。
说干就干,这两天晚上有点空,于是果断开了个unity空项目。就开始了。可惜我美工基础实在太差,做不好美术资源,用unity最基本的box/sphere来做的,建了几个不同的材质。经过几个晚上的奋斗,已经搞定:
在这里插入图片描述
在这里插入图片描述
哈哈,右键可以调整摄像机视角,左键投放棋子,可以选择玩家与玩家对战还是和电脑对战,与电脑对战可以选5种难度,可以选择电脑先手还是玩家先手,可以设置音效和背景音乐音量,总之,该有的都有了。甚至打算下一步开发网络对战功能。。
经过测试,电脑智力很牛,除了最简单的,其余的难度想赢电脑很困难,我自己,中难度往后就一局也没有赢过。。呵呵。。难道,老子赋予他智力,他就比老子还聪明了??

下面说说核心算法:
其实我的算法挺简单,挺暴力。是经典的博弈算法,电脑的思考过程是这样的:
首先,由于每次落子都只有8种可能(因为只有8列),所以遍历8个点不会太复杂。然后,假设己方棋子已经落在这个点上,那么计算一下这个点能够获得的利益,利益嘛,当然是一个利益函数,比如:如果能胜利,就返回一个很大的值,表示利益无穷大,如果能形成双冲3,那么就返回一个比较大的值,如果能形成冲三还活二,那么就返回比双冲三稍微小一点的值,还有各种情况,比如双活2,等等,都定义好利益值。这样,就能得到某一个点能够获取的己方利益值,大多数情况,在没有胜利的情况下,将该处的利益值,减去敌人能够获取到的最佳利益值,就是这个点的最终利益值,然后8个点全部遍历完成后,就选一个获利最高的点进行投子就可以了。算法很简单,但是这个算法是一个递归算法。因为获取敌人的最佳利益值,事实上就是又遍历了一次8个点,只不过这次假设放入的是地方的棋子,看敌方能够获取的利益。
额,用语言描述一个算法还是比较困难的,下面用代码来描述一下:


// 选择那一列进行投子的函数
// 返回最佳的列索引编号
// 参数:游戏方/递归深度(该值越大,难度越大)/ out 能获取的最高利益
private int SelectColumn(GamePlayer st, int level, out float ben)
{
	float maxBenefits = -100000;
	int sx = -1;
	// 遍历8个点
	for (int x = 0; x < 8; ++x)
	{
		// 看看这一列的棋子是不是已经满了,如果满了就跳过。
		int y = GetColmunHeight(x);
		if (y >= 8)
			continue;
                    
		// 假设将棋子放置在这里
		m_MapFlag[x, y] = st;
		m_ColmunHeight[x] += 1;

		// 判断是否胜利,是的话,就恢复棋盘(移除之前假设放到这里的棋子),并直接返回
		if (IsWin(x, y, st, true))
		{
			m_ColmunHeight[x] -= 1;
			m_MapFlag[x, y] = GamePlayer.NONE;
			ben = BENEFITS_WIN;
			return x;
		}
		// 获取这个点能够获得的己方最高利益值
		float benefits = GetBenefits(x, y, st);

		// 如果递归深度大于0,则计算一下敌人下一步能够获取的最高利益。
		if (level > 0)
		{
			SelectColumn((st == GamePlayer.RED) ? GamePlayer.BLUE : GamePlayer.RED, level - 1, out float enBen);

			// 用该点能获取的己方利益,减去敌人下一步能够获取到的最高利益,即为该点的最终利益。
			benefits -= enBen;
		}

		// 恢复棋盘(移除假设放到这里的棋子)
		m_ColmunHeight[x] -= 1;
		m_MapFlag[x, y] = GamePlayer.NONE;
                
		// 记录能获取到的最高利益的那个点
		if (benefits > maxBenefits)
		{
			maxBenefits = benefits;
			sx = x;
		}
	}
	ben = maxBenefits;
	return sx;
}

项目下载连接:

猛击此处下载项目(仅支持64位,编译时忘了选择x86了)

没有更多推荐了,返回首页