剪枝算法实现一字棋-C++

博弈树

alpha & beta剪枝算法实现一字棋

剪枝算法首先就是要理解,把这个算法彻底弄清楚,我觉得这是一件非常有意义的事情!为后续书写其它棋类的AI打下了坚实的基础

剪枝操作的实现,遍历下一步所有可能取到的点,找出评估值最大的那一步就是我们下一步所需要的做的。
剪枝算法

int Tree::alphaBeta(int &value,int deep,bool MAX){
	if(isWin()==1){
		value=10000;
		return 0;
	}
	//递归的终点
	if(deep+this->count==9){
		return this->evaluate();
	}
	//一开始不剪枝
	bool prune=false;
	int temp,flag;

	//max结点我开始落子,电脑希望flag越大越好
	if(MAX)
		flag=10000;
	//min结点电脑开始落子,我希望flag越小越好
	else
		flag=-10000;
	for(int i=0;i<NUM && !prune;i++){
		for(int j=0;j<NUM && !prune;j++){
			//找出一个空位置下棋
			if(this->s[i][j]==' '){
				//如果当前结点是max结点,下一步是我下棋
				if(MAX){
					this->s[i][j]='X';
					//如果我下这一步我赢了,是电脑最不希望看到的,直接值取-100
					if(this->isWin()==-1)
						temp=-10000;
					else
						temp=this->alphaBeta(flag,deep+1,!MAX);
					if(temp<flag)	flag=temp;
					//如果我下棋让评分变的低了,电脑完全没必要走这一步,剪枝
					if(flag<=value) prune=true;
				}
				//min结点电脑开始下棋
				else{
					this->s[i][j]='O';
					//如果这一步对于电脑来说直接取得胜利,对于机器来说是十分想看到的
                    if(this->isWin()==1)
						temp=10000;
					else
						temp=this->alphaBeta(flag,deep+1,!MAX);
					//我们希望的flag小于实际的评分,此时flag应该更新
					if(temp>flag)	flag=temp;
					//此时对于我来说是十分不利的,我不可能走这一步让电脑获取胜利,我这一步应该被剪枝
					//或结点的alpha值不能降低其父结点的beta值,剪枝
					if(flag>=value) prune=true;
				}
				this->s[i][j]=' ';
			}
		}
	}
	//max(或)结点的扩展要是能提高value值
	if(MAX){
		if(flag>value)
			value=flag;
	}
	//min(与)结点的扩展要是能降低value值
	else{
		if(flag<value)
			value=flag;
	}
	return flag;
}

剪枝算法是一字棋程序中的核心部分,此外还需要定义一个棋类,用于初始化和实现下棋操作
棋类部分代码以及所有函数和变量

class Chess{
private:
	char a[3][3];		//棋盘的状态
	int count;          //已经下棋的步数
public:
	std::string computer,player;        //电脑与玩家
	int x,y;            				//下棋的位置
	std::string str,winner;       		//当前落子的对象
	void initial();     				//初始化函数
	void getMove();     				//获取走棋的位置
	bool makeMove(int,int,std::string);	//走棋函数
	void showStatus();  				//展示棋盘当前的状态
	bool isGameOver();  				//判断游戏是否结束
	void getStatus(char[][3]);          //获取当前的状态
	int getCount();                     //获取当前已经走棋的步数
};
void Chess::initial(){
	this->computer="Computer";
	this->player="Player";
	this->winner=" ";
	this->count=0;
	this->str=this->player;
	for(int i=0;i<NUM;i++){
		for(int j=0;j<NUM;j++){
			this->a[i][j]=' ';
		}
	}
}

主函数部分

	Onechess.initial();
	while(!Onechess.isGameOver() && Onechess.getCount()!=9){
		Onechess.showStatus();
		if(Onechess.str==Onechess.player){
			Onechess.getMove();
			Onechess.makeMove(Onechess.x,Onechess.y,Onechess.str);
		}
		else{
			tree.getChessStatus(Onechess);
			//不断的去试探,找出一个最大的value的值的走法
			for(int i=0;i<NUM;i++){
				for(int j=0;j<NUM;j++){
					if(tree.s[i][j]==' '){
						tree.s[i][j]='O';
						tree.alphaBeta(value,deep,1);
						if(value>temp){
							temp=value;
							row=i;
							column=j;
						}
						tree.s[i][j]=' ';
					}
				}
			}
			value=-10000;
			temp=-10000;
			Onechess.makeMove(row+1,column+1,Onechess.str);
		}
		printf("\n**************");
	}
	Onechess.showStatus();
	//并没有分出胜负,但是下棋的步数已经到达了9步,此时判定平局
	if(!Onechess.isGameOver() && Onechess.getCount()==9){
		printf("There are no winner! Is Draw!!!");
	}
	else
		printf("The winner is %s,let's congratulate!",Onechess.winner.c_str());

通过此次书写一字棋的博弈树,我对人工智能有了一个很好的了解。
部分运行截图。程序运行,结果最多就是平局,然后就是玩家输掉游戏。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值