实验二源代码

#include <iostream>
#include<math.h>
using namespace std;
#define N 3
#define Max 99999

int pace = 1;//记录步数
//
typedef struct Node
{
	//节点状态
	int nine[N][N];

	//空格的下标
	int x, y;

	//启发信息
	int f, g, h;	//  总代价f(S0)=g(S0)移动步数+h(S0)各棋子不在正确位置的数目

	//指向父节点指针 
	struct Node* parent;   //father
}Node, * p_node;

//开始状态
int start[N][N] = { {1,2,3},{4,5,6},{7,8,0} };

//目标状态
int goal[N][N]= { {0,1,2},{3,4,5},{6,7,8} };

//线性变的定义   开闭表
typedef struct SeqList
{
	Node* *a;

	int length;

}List, * p_list;

//-------------------------------------//类的声明
//用类封装
class Astar {

private:
	Node* p;
	Node* Goal;  //目标
	List Open;  //Open表
	List Close;  //Clos表
public:
	
	//构造函数
	Astar(Node* goal){
		Open.a = new Node*[Max];
		Close.a = new Node*[Max];
		Goal = copy(goal);
	}
	~Astar() {
		int i;

		for (i = 0; i < Open.length; i += 1) {
			delete Open.a[i];
		}

		for (i = 0; i < Close.length; i += 1) {
			delete Close.a[i];
		}
	}

	//Open表的添加
	void openAdd(Node* temp);

	//Open去头
	Node* openDelete();

	//Close的添加
	void closeAdd();
    
	// 用于判断是与Goal否相等
	bool boolGoal() {
		return Equal(p, Goal);
	}

	//扩展结点
	bool Extend();

	//0的移动
	bool up(Node* temp);
	bool down(Node* temp);
	bool left(Node* temp);
	bool right(Node* temp);

	//判断两个结点是否相同
	bool Equal(Node* s1, Node* s2);

	//复制结点
	Node* copy(Node* temp);
	//
	//g(s)的确定
	int g(Node* temp);

	//f(s)的确定
	int f(Node* temp);

	//h(s)的确定
	int h(Node* temp);

	//判断Open表是否为空
	bool openEmpty();

	//判断是有Close相同
	bool sameClose(Node* temp);

	//判断是有Open相同
	bool sameOpen(Node* temp);

	//show
	void show(Node* temp);

	Node* GetP() {
		return p;
	}

	//返回与temp相同的Open中
	Node* findOpen(Node* temp);

	//返回与temp相同的Close中
	Node* findClose(Node* temp);

	//输出路径
	void showPath();

};

int nixu(int a[]) {
	int sum = 0;
	for (int i = 0; i < N * N ; i++)
		for (int j = i + 1; j < N * N; j++)
			if (a[i] && a[j]) //不为0
				if (a[i] > a[j])sum++;
	return sum;
}

//初始数组判断是否可行
bool init(int &sx,int &sy ,int &gx ,int &gy ) {
	int m = 0;
	cout << "请输入开始状态" << endl;
	int a[9];
	for (int i = 0; i < 9; i++) {
		cin >> a[i];
		while (a[i] > 8 || a[i] < 0) {
			cout << "输入数据有误!请重新输入:" << endl;
			cin >> a[i];
		}
	}

	int num1 = nixu(a);

	//初始化
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			 start[i][j]=a[m++];
			 if (start[i][j] == 0) {
				 sx = i;
				 sy = j;
			 }
		}
	}

	cout << "请输入目标状态" << endl;
	for (int i = 0; i < 9; i++) {
		cin >> a[i];
		while (a[i] > 8 || a[i] < 0) {
			cout << "输入数据有误!请重新输入:" << endl;
			cin >> a[i];
		}
	}

	int num2 = nixu(a);
	m = 0;
	//初始化goal
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			goal[i][j] = a[m++];
			if (goal[i][j] == 0) {
				gx = i;
				gy = j;
			}
		}
	}
	return num1 % 2 == num2 % 2;
}

//------------------------------------------------------//主函数
int main() {
	int sx, sy, gx, gy;//0的位置
	//判断是否可以
	if (!init(sx,sy,gx,gy)) {
		cout << "不可完成" << endl;
		return 0;
	}
	//初始化
	Node* goal0 = new Node();
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			goal0->nine[i][j] = goal[i][j];
		}
	}
	goal0->parent = NULL;
	goal0->x = gx;
	goal0->y = gy;
	Astar astar(goal0);
	Node* goal1 = new Node();
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			goal1->nine[i][j] = start[i][j];
		}
	}
	goal1->parent = NULL;
	goal1->x = sx;
	goal1->y = sy;
	astar.openAdd(goal1);
	//循环

	while (!astar.openEmpty() ) {  //op判断是否可完成
		astar.closeAdd();//加入Close
		//astar.show(astar.GetP());//输出
		if (astar.Equal(astar.GetP(), goal0)) {//判断是否目标
			astar.showPath();
			break;
		}
		astar.Extend();
	}
	return 0;
}

//---------------------------------------------------------//类成员函数的定义

//Open表的添加
void Astar::openAdd(Node* temp) {
	if (Open.length == 0) {
		Open.a[Open.length++] = temp;
	}
	else {
		int i = 0;
		int j = 0; 
		for (i = 0; i < Open.length; i++) {
			if (temp->f < Open.a[i]->f) {
				for (j = Open.length - 1; j >= i; j--) {
					Open.a[j + 1] = Open.a[j];
				}
				Open.length++;
				Open.a[i] = temp;
				return;
			}
		}
		Open.a[Open.length++] = temp;
	}
}

//Open去头 对Close添加
Node* Astar::openDelete() {
	if (Open.length < 0)//防止越界
		return NULL;
	Node* temp = Open.a[0];
	if (Open.length == 1) {//只有一个
		Open.length = 0;
	}
	else {//有多个
		int i = 0;
		while (i < Open.length - 1) {
			Open.a[i] = Open.a[i + 1];
			i++;
		}
		Open.length--;
	}
	return temp;
}

//Close的添加
void Astar::closeAdd() {
	Close.a[Close.length++] = openDelete();
	if (Close.length > Max)cout << "Max定义不足" << endl;
	else
		p=Close.a[Close.length - 1];
}

//复制结点
Node* Astar::copy(Node* temp) {
	if (temp == NULL)
		return NULL;
	Node* temp2 = new Node();
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			temp2->nine[i][j] = temp->nine[i][j];
		}
	}
	temp2->f = temp->f;
	temp2->g = temp->g;
	temp2->h = temp->h;
	temp2->x = temp->x;
	temp2->y = temp->y;
	temp2->parent = temp->parent;
	return temp2;
}

//判断两个点是否相等
bool Astar::Equal(Node* s1, Node* s2){
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if (s1->nine[i][j] != s2->nine[i][j])
			{
				return false;
			}
		}
	}
	return true;
}

//扩展结点
bool Astar::Extend() {
	if (up(GetP()) | right(GetP()) |down(GetP()) |left(GetP()))//判断是否可扩展    |都要执行
		return true;
	return false;
}

//0的移动
bool Astar::up(Node* temp) {        //x--
	if (temp->x == 0)
		return false;
	Node* temp2 = copy(temp);//扩展新节点
	//交换
	{
		int temp1 = temp2->nine[temp2->x][temp2->y];
		temp2->nine[temp2->x][temp2->y] = temp2->nine[temp2->x - 1][temp2->y];
		temp2->nine[temp2->x - 1][temp2->y] = temp1;
	}
	//求估计值
	{
		temp2->x--;
		temp2->f = f(temp2);//求temp2的估价值;
		temp2->g = g(temp2);
		temp2->h = h(temp2);
	}
	if (!sameClose(temp2)) {
		if (sameOpen(temp2)) {
			if (temp2->f < findOpen(temp2)->f) {//if( temp2的估价值小于OPEN表的估价值 )

				findOpen(temp2)->parent = temp;//{把temp设置为temp2的父亲;

				findOpen(temp2)->f = temp2->f;	//更新OPEN表中的估价值; //取最小路径的估价值}
			
			}
		}
		else {
			temp2->parent = temp;	//把temp设置为X的父亲;
			openAdd(temp2);
		}
	}
	return true;
}

bool Astar::down(Node* temp) {//x++
	if (temp->x == N - 1)
		return false;
	Node* temp2 = copy(temp);//扩展新节点
	//交换
	{
		int temp1 = temp2->nine[temp2->x][temp2->y];
		temp2->nine[temp2->x][temp2->y] = temp->nine[temp2->x + 1][temp2->y];
		temp2->nine[temp2->x + 1][temp2->y] = temp1;
	}

	//求估计值
	{
		temp2->x++;
		temp2->f = f(temp2);
		temp2->g = g(temp2);
		temp2->h = h(temp2);
	}
	if (!sameClose(temp2)) {
		if (sameOpen(temp2)) {
			if (temp2->f < findOpen(temp2)->f) {//if( temp2的估价值小于OPEN表的估价值 )

				findOpen(temp2)->parent = temp;//{把temp设置为temp2的父亲;

				findOpen(temp2)->f = temp2->f;	//更新OPEN表中的估价值; //取最小路径的估价值}
			
			}
		}
		else {
			temp2->parent = temp;
			openAdd(temp2);
		}
	}
	return true;
}

bool Astar::left(Node* temp) {//y--
	if (temp->y == 0)
		return false;
	Node* temp2 = copy(temp);//扩展新节点
	//交换
	{
		int temp1 = temp2->nine[temp2->x][temp2->y];
		temp2->nine[temp2->x][temp2->y] = temp2->nine[temp2->x][temp2->y - 1];
		temp2->nine[temp2->x][temp2->y - 1] = temp1;
	}
	temp2->y--;
	//求估计值
	{
		temp2->f = f(temp2);
		temp2->g = g(temp2);
		temp2->h = h(temp2);
	}
	if (!sameClose(temp2)) {
		if (sameOpen(temp2)) {
			if (temp2->f < findOpen(temp2)->f) {//if( temp2的估价值小于OPEN表的估价值 )

				findOpen(temp2)->parent = temp;//{把temp设置为temp2的父亲;

				findOpen(temp2)->f = temp2->f;	//更新OPEN表中的估价值; //取最小路径的估价值}

			}
		}
		else {
			temp2->parent = temp;
			openAdd(temp2);
		}
	}

	return true;
}

bool Astar::right(Node* temp) {//y++
	if (temp->y == N-1)
		return false;
	Node* temp2 = copy(temp);//扩展新节点
	//交换
	{
		int temp1 = temp2->nine[temp2->x][temp2->y];
		temp2->nine[temp2->x][temp2->y] = temp2->nine[temp2->x ][temp2->y+ 1];
		temp2->nine[temp2->x][temp2->y + 1] = temp1;
	}
	temp2->y++;
	//求估计值
	{
		temp2->f = f(temp2);
		temp2->g = g(temp2);
		temp2->h = h(temp2);
	}
	if (!sameClose(temp2)) {

		if (sameOpen(temp2)) {
			
			if (temp2->f < findOpen(temp2)->f) {//if( temp2的估价值小于OPEN表的估价值 )

				findOpen(temp2)->parent = temp;//{把temp设置为temp2的父亲;

				findOpen(temp2)->f = temp2->f;	//更新OPEN表中的估价值; //取最小路径的估价值}

			}	
		}
		else {	
			
			temp2->parent = temp;
			openAdd(temp2);
		}
	}
	return true;
}

//g(s)的确定
int Astar::g(Node* temp) {
	Node* p = temp;
	int i = 0;
	while (p) {
		p = p->parent;
		if (p)
			i++;
	}
	return i;
}

//f(s)的确定
int Astar::f(Node* temp) {

	return h(temp) + g(temp);

}

//h(s)的确定
int Astar::h(Node* temp){
	int n = 0;
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if (temp->nine[i][j] !=Goal->nine[i][j])
			{
				n++;
			}
		}
	}
	return n;
}

//判断Open表是否为空
bool Astar::openEmpty() {
	if (Open.length == 0)
		return true;//true为空
	return false;
}

//判断是有Close相同
bool Astar::sameClose(Node* temp) {
	for (int i = 0; i < Close.length; i++) {
		if (Equal(temp, Close.a[i]))
			return true;//有相同
	}
	return false;
}

//判断是有open相同
bool Astar::sameOpen(Node* temp) {
	for (int i = 0; i < Open.length; i++) {
		if (Equal(temp, Open.a[i]))
			return true;//有相同
	}
	return false;
}

//show
void Astar::show(Node* temp) {
	cout << pace++ << endl;//第几步
	cout <<" ---------------------------------------------------"<< endl;
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			cout << temp->nine[i][j]<<' ';
		}
		cout << endl;
	}
	cout << "g=" << g(temp) << ' ' << "h=" << h(temp) <<endl;
	cout << " ---------------------------------------------------" << endl;
}

//返回与temp相同的
Node* Astar::findOpen(Node* temp) {
	for (int i = 0; i < Open.length; i++) {
		if (Equal(temp, Open.a[i]))
			return Open.a[i];//有相同
	}
	return NULL;
}

//返回与temp相同的
Node* Astar::findClose(Node* temp) {
	for (int i = 0; i < Close.length; i++) {
		if (Equal(temp, Close.a[i]))
			return Close.a[i];//有相同
	}
	return NULL;
}

//输出路径
void Astar::showPath() {
	cout << "即将输出路径" << endl;
	system("pause");
	system("cls");
	List path;
	path.a = new Node * [Max];
	int i = 0;
	while (p) {
		path.a[++i]=p;
		p = p->parent;
	}
	pace = 1;
	while (i > 0) {
		show(path.a[i--]);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值