⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.cpp

📁 八数码的
💻 CPP
字号:
#include <iostream>
#include <vector>
#include <set>
using namespace std;

enum {UP,RIGHT,DOWN,LEFT};

struct Node{
	char board[3][3];
	int x,y;	//空格坐标
	int parent; //父节点下标
	int gn,hn,fn; // g(n),h(n),f(n)
};

Node start;		//起始状态
Node target;	//目标状态

int h(const Node& node) //计算结点 h(n)的值,运  用的课件上跟随数字的方法
{
	int u=0,v=0,tempu,tempv;
	int cost=0;
	if(node.board[1][1]!='0') cost+=1;
	do{
		tempu=u;
		tempv=v;
		if(u==0)
		{
			if(v<2)
			{
				v+=1;
			}
			else 
			{
				u+=1;
			}
		}
		else if(v==2)
		{
			if(u<2) 
			{
				u+=1;
			}
			else 
			{
				v-=1;
			}
		}
		else if(u==2)
		{
			if(v>0) 
			{
				v-=1;
			}
			else 
			{
				u-=1;
			}
		}
		else if(v==0)
		{
			if(u>0)
			{
				u-=1;
			}
			else v+=1;
		}
		if(node.board[tempu][tempv]!=target.board[tempu][tempv]) cost+=2;
	}while(!(u==0&&v==0));
	return cost;
}
void init()  //初始化
{
	start.board[0][0]='2';start.board[0][1]='8';start.board[0][2]='3';   //起始状态
	start.board[1][0]='1';start.board[1][1]='6';start.board[1][2]='4';
	start.board[2][0]='7';start.board[2][1]='0';start.board[2][2]='5';
	start.x=2;start.y=1;  //修改矩阵时空格坐标也要修改
	start.parent=-1;	
	
	target.board[0][0]='1';target.board[0][1]='2';target.board[0][2]='3'; //目标状态
	target.board[1][0]='8';target.board[1][1]='0';target.board[1][2]='4';
	target.board[2][0]='7';target.board[2][1]='6';target.board[2][2]='5';
	target.x=1;target.y=1;
	target.parent=-1;
	target.fn=0;

	start.gn=0;
	start.hn=h(start);       
	start.fn=start.gn+start.hn;
}

bool equal(const Node& node1,const Node& node2)	//判断两局面是否相等
{
	for(int i=0;i<3;++i)
		for(int j=0;j<3;++j)
			if(node1.board[i][j]!=node2.board[i][j]) return false;
		return true;
}
void display(const Node& node)  //输出局面
{
	for(int i=0;i<3;++i)
	{
		for(int j=0;j<3;++j)
			cout<<node.board[i][j]<<"	  ";
		cout<<endl;
	}
}

Node Move(Node node,int dir)  //将当前状态移动生成新状态返回。 dir 取值为: UP,RIGHT,DOWN,LEFT,表示将空格上,右,下,左移动
{
	int x=node.x;
	int y=node.y;
	
	if(dir==UP)
	{
		if(x<=0)
		{
			node.x=-1; //返回错误值,不能移动
			return node;
		}
		else
		{
			char t=node.board[x][y];
			node.board[x][y]=node.board[x-1][y];
			node.board[x-1][y]=t;
			node.x=x-1;
			return node;
		}
	}
	else if(dir==RIGHT)
	{
		if(y>=2)
		{
			node.x=-1; //返回错误值,不能移动
			return node;
		}
		else
		{
			char t=node.board[x][y];
			node.board[x][y]=node.board[x][y+1];
			node.board[x][y+1]=t;
			node.y=y+1;
			return node;
		}
	}
	else if(dir==DOWN)
	{
		if(x>=2)
		{
			node.x=-1; //返回错误值,不能移动
			return node;
		}
		else
		{
			char t=node.board[x][y];
			node.board[x][y]=node.board[x+1][y];
			node.board[x+1][y]=t;
			node.x=x+1;
			return node;
		}
	}
	else if(dir==LEFT)
	{
		if(y<=0)
		{
			node.x=-1; //返回错误值,不能移动
			return node;
		}
		else
		{
			char t=node.board[x][y];
			node.board[x][y]=node.board[x][y-1];
			node.board[x][y-1]=t;
			node.y=y-1;
			return node;
		}
		
	}
	else {node.x=-1;return node;}
	
}

int exist(set<Node>& open,vector<Node>& closed,const Node& node) //在open,closed表中查询是否已经存在node状态
{
	for(set<Node>::iterator it=open.begin();
		it!=open.end();++it)
	{	
		if(equal((*it),node)) 
		{
			if(node.fn<(*it).fn) //当前的f值小于已有的f值
			{
				(*it).gn=node.gn;
				(*it).hn=node.hn;
				(*it).fn=node.fn;
				(*it).parent=node.parent;				
			}
			return 1;		
		}
	}
	for(vector<Node>::iterator it=closed.begin();it!=closed.end();++it)
	{
		if(equal((*it),node)) 
		{
			if(node.fn<(*it).fn)  //当前的f值小于已有的f值
			{
				(*it).gn=node.gn;
				(*it).hn=node.hn;
				(*it).fn=node.fn;
				(*it).parent=node.parent;
				
				open.insert((*it)); //移回open表
			}
			return 2;			
		}
	}

	open.insert(node);
	return 0;
}

void A(const Node& start,const Node& target)
{
	set<Node> open;
	vector<Node> closed;
	vector<int> result;

	open.insert(start);

	while ( !open.empty() )
	{
		Node out=(*open.begin());

		if(equal(out,target))	//找到目标状态
		{
			int i=out.parent;
			while(i!=-1)
			{
				result.push_back(i);
				i=closed[i].parent;
			}
			break;
		}

		open.erase(open.begin());  //第一个元素除去
		closed.push_back(out);     //加入到closed表

		for(int i=0;i<4;++i)
		{
			Node outm=Move(out,i);
			if(outm.x!=-1) //能这样扩展
			{
				outm.parent=closed.size()-1;   //记录父指针
				outm.gn=out.gn+1;				//计算g(n)
				outm.hn=h(outm);				//计算h(n)
				outm.fn=outm.gn+outm.hn;		//计算f(n)
				exist(open,closed,outm);		
			}
		}
		
	}
	cout<<"A算法搜索:"<<endl;
	for(int i=result.size()-1;i>=0;--i)
	{
		display(closed[result[i]]);
		cout<<endl;
	}
	display(target);
	cout<<endl;
	cout<<"搜索结束!"<<endl<<endl;
}


bool operator<(const Node& node1,const Node& node2)
{
	if(node1.fn<node2.fn)
		return 1;
	else if(node1.fn==node2.fn)
	{
		if(node1.gn<node2.gn) return 1;
		else return 0;
	}
	else return 0;
}

void main()
{
	init();
	A(start,target);	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -