象棋最大最小剪枝算法

1.象棋中通常需要推算当前局面下,每走一步之后的局面分,通常我们可以设定考虑几步棋,通常我们所说的算棋,而计算机的AI算法中最常用的就是最大值最小值算法,而剪枝算法是对最大值最小值算法的一种优化。

有点类似于八皇后的深度树


当前局面表示电脑,作为电脑肯定会择当前局面分最大的作为下一步。如果我们的LEVEL为1,也就是我们只算下一步的得分,选最大的那个,对比途中,肯定挑选100作为下一步的走法。但一般类似我们人下象棋的过程。我们一般会去想下几步该怎么下而挑选出最好的一步,就要往下递归了,比如LEVEL为2的时候,第一分支搜索100,这时候轮到人走,人肯定选对电脑不利的局面,也就是最小局面分10,而第二分支80,往下走,人选20,第三分支90,人选30,我们要的肯定是最好的30。这就是最大,最小,最大表示作为电脑方选最大,最小表示人方选最小,最后由电脑方选出最大的一个局面分作为下一步的参考。

我们模拟电脑走法的时候,不论层次为多少,都是以最后一个并且是最大的作为我们的局面分。


将图中的50换成5

剪枝算法是对最大最小算法的优化:  场景模拟level为2:走第一步100,轮到人,人选10(对电脑最为不利),而搜索80的时候,下一步人选5,这时候,80的其他分支就没必要去算了,因为人选的5比走100选的10还小。作为电脑优先选100的这一步,这时候只需要遍历90的分支,继续查找,将100得到的局面分代入到90的遍历中,如果90的分支中有比10小的,那么90的其他分支也不再考虑。



为了方便理解 这边贴上代码

Step* AI::getStep(SceneGame* game, int level)
{
	int highScore = -3000;
	Step* ret = NULL;

	// 产生所有可能的移动,遍历
	vector<Step*> allMove = getAllPossibleMove(game);
	vector<Step*>::iterator it;
	for (it = allMove.begin(); it != allMove.end(); ++it)
	{
		Step* step = *it;
		fakeMove(game, step);
		//int score = getScore(game);
		int score = getMinScore(game, level - 1, highScore);
		unfakeMove(game, step);
		if (score > highScore)
		{
			highScore = score;
			ret = step;
		}
	}

	for (it = allMove.begin(); it != allMove.end(); ++it)
	{
		Step* step = *it;
		if (step != ret) delete step;
	}

	return ret;
}
int AI::getMinScore(SceneGame* game, int level, int curMinScore)
{
	if (level == 0)
		return getScore(game);

	int minScore = 3000;
	// 产生所有可能的移动,遍历
	//得到电脑最不利的局面
	vector<Step*> allMove = getAllPossibleMove(game);
	vector<Step*>::iterator it;
	for (it = allMove.begin(); it != allMove.end(); ++it)
	{
		Step* step = *it;
		fakeMove(game, step);
		//下一步得分
		int score = getMaxScore(game, level - 1, minScore);
		unfakeMove(game, step);

		// 减枝算法
		if (score <= curMinScore)
		{
			minScore = score;
			break;
		}

		if (score < minScore)
		{
			minScore = score;
		}
	}

	for (it = allMove.begin(); it != allMove.end(); ++it)
	{
		Step* step = *it;
		delete step;
	}

	return minScore;
}

int AI::getMaxScore(SceneGame* game, int level, int curMaxScore)
{
	if (level == 0)
		return getScore(game);

	int maxScore = -3000;
	// 产生所有可能的移动,遍历
	vector<Step*> allMove = getAllPossibleMove(game);
	vector<Step*>::iterator it;
	for (it = allMove.begin(); it != allMove.end(); ++it)
	{
		Step* step = *it;
		fakeMove(game, step);
		int score = getMinScore(game, level - 1, maxScore);
		unfakeMove(game, step);
		if (score >= curMaxScore)
		{
			maxScore = score;
			break;
		}
		if (score > maxScore)
		{
			maxScore = score;
		}
	}

	for (it = allMove.begin(); it != allMove.end(); ++it)
	{
		Step* step = *it;
		delete step;
	}

	return maxScore;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值