象棋AI博弈算法(最大值最小值算法)

最大值最小值在象棋运用的很多,也是最基础的走棋算法:首先根据基础局面计算各个走棋的局面分,假如说电脑要计算三层,那么如图:

 总之就是要在所有走法中瘸子里面挑将军的意思:电脑想自己得分最高,电脑假设人下棋的时候要推断出最优的走法也就是得分最高的走法,那么人就会选择电脑走法得分最高的走法,然后人从这些走法中挑选出分值最小的走法给电脑,电脑又想从人给的这些走法中挑出值最大的哪一个,所以这就是最小值最大值算法

下面是C++版本的AI走棋算法:

Step& AI::getStep(GameScene& game,int level) {
	this->step = NULL;
	this->level = level;
	//game.chessBoard->pieces.at(1)->col;
	// 从所有最小值中获得最大值
	this->getMaxScore(&game,level);
	return *this->step;
}
// 获得所有可能移动的移动方案
Vector<Step*> AI::getAllSteps(GameScene& game) {
	Vector<Step*> stepArr;
	time_t start, end;
	double cost;
	time(&start);
	int start = 0;
	if (game.selfType) {
		start = 16;
	}
	else {
		start = 0;
	}
	for (int i = start; i < start + 16; i++) {
		Piece* piece = game.chessBoard->pieces.at(i);
		// 死去的棋子没有办法吃棋走棋逻辑
		if (!piece->isDead) {
			for (int row = 0; row < 10; row++) {
				for (int col = 0; col < 9; col++) {
					int killId = game.chessBoard->getPieceIdByRowAndCol(row, col);
					if (piece->row == row && piece->col == col) {
						continue;
					}
					if (killId == -1 && game.chessBoard->dealRealWar(piece->id, killId, piece->row, piece->col, row, col)) {
						// 创建一个step
						Step* step = Step::create(piece->id, piece->row, piece->col, row, col, killId);
						stepArr.pushBack(step);
					}
					else if (killId != -1 && game.chessBoard->dealWar(piece->id, killId)) {
						// 棋子类型相同的时候不允许加入到走棋数组中去
						if (game.chessBoard->pieces.at(killId)->type != game.chessBoard->pieces.at(piece->id)->type) {
							// 创建一个step
							Step* step = Step::create(piece->id, piece->row, piece->col, row, col, killId);
							stepArr.pushBack(step);
						}
					}
				}
			}
		}
	}
	time(&end);
	cost = difftime(end,start);
	return stepArr;
}
// 获得局面分最大的分数
int AI::getMaxScore(GameScene* game, int level) {
	if (level == 0) {
		return this->calScore(game);
	}
	Vector<Step*> allMoves = this->getAllSteps(*game);
	int topScore = -30000323;
	// 遍历每一种走法
	for (int i = 0; i < allMoves.size(); i++) {
		Step* moveItem = allMoves.at(i);
		// 走棋试探
		this->fakeMove(game, moveItem);
		// 计算局面分
		int score = this->getMinScore(game,level - 1);
		if (score > topScore) {
			topScore = score;
			//currentStep = moveItem;
			if (level == this->level) {
				this->step = moveItem;
			}
		}
		// 取消走棋试探
		this->unFakeMove(game, moveItem);
	}
	return topScore;
}
// Ai获得对方子局面中最小的分值
int AI::getMinScore(GameScene* game, int level) {
	if (level == 0) {
		return this->calScore(game);
	}
	Vector<Step*> allMoves = this->getAllSteps(*game);
	int minScore = 30000323;
	// 遍历每一种走法
	for (int i = 0; i < allMoves.size(); i++) {
		Step* moveItem = allMoves.at(i);
		// 走棋试探
		this->fakeMove(game, moveItem);
		// 计算局面分
		int score = this->getMaxScore(game, level - 1);
		if (score < minScore) {
			minScore = score;
			//currentStep = moveItem;
			if (level == this->level) {
				this->step = moveItem;
			}
		}
		// 取消走棋试探
		this->unFakeMove(game, moveItem);
	}
	return minScore;
}
// 计算得分
int AI::calScore(GameScene* game) {
	// 每个棋子的评分
	int gameScore[] = { 10,5,3,2,1000,2,3,5,10,5,5,1,1,1,1,1 };
	// 己方得分
	int bottomScore = 0;
	// 敌方得分
	int upScore = 0;
	for (int i = 0; i < 16; i++) {
		if (!game->chessBoard->pieces.at(i)->isDead) {
			bottomScore += gameScore[i];
		}
	}
	for (int j = 16; j < 32; j++) {
		if (!game->chessBoard->pieces.at(j)->isDead) {
			upScore += gameScore[(32 - j) - 1];
		}
	}
	// 返回得分
	return upScore - bottomScore;

}
// 试探性的走棋
void AI::fakeMove(GameScene* game,Step* step) {
	/*Piece* pieceItem = game->chessBoard->pieces.at(step->sId);
	pieceItem->row = step->toRow;
	pieceItem->col = step->toCol;*/
	game->movePiece(step->sId,step->toRow,step->toCol,step->killId);

}
// 取消试探走棋逻辑
void AI::unFakeMove(GameScene* game, Step* step) {
	/*int row = step->fromRow;
	int col = step->fromCol;
	game->movePiece(step->sId, row, col, step->killId);*/
	// 还原原来棋子的行和列
	game->chessBoard->pieces.at(step->sId)->row = step->fromRow;
	game->chessBoard->pieces.at(step->sId)->col = step->fromCol;

	game->chessBoard->map[step->fromRow][step->fromCol] = 1;
	if (step->killId != -1) {
		game->chessBoard->map[step->toRow][step->toCol] = 1;
		Piece* targetNode = game->chessBoard->pieces.at(step->killId);
		targetNode->row = step->toRow;
		targetNode->col = step->toCol;
		// 目标棋子的死亡状态重置为false
		targetNode->isDead = false;
	}
	else {
		game->chessBoard->map[step->toRow][step->toCol] = 0;
	}
	game->redRun = !game->redRun;
}

猜你喜欢

转载自blog.csdn.net/lck8989/article/details/102984668
今日推荐