#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--]);
}
}