您的位置:首页 > 大数据 > 人工智能

人工智能-八数码问题

2010-12-23 23:10 323 查看
八数码问题是指这样一种游戏:将分别标有数字1,2,3,…,8的八块正方形数码牌任意地放在一块3×3的数码盘上。放牌时要求不能重叠。于是,在3×3的数码盘上出现了一个空格。现在要求按照每次只能将与空格相邻的数码牌与空格交换的原则,将任意摆放的数码盘逐步摆成某种特殊的排列。

状态表示:用一个二维数组a[3][3]表示数码盘上的某种布局,a[i][j]表示数码盘上第(i+1)行第(j+1)列的数码牌,空格则用零来表示,为了编程方便用结构体jiedian表示搜索中生成的每个结点,存储结构采用的是单链表,形成一个类似线性表的数据结构,结构体jiedian中成员C[3][3]表示数码盘上数码牌的某种状态,成员quanzhi表示A*算法中针对C[3][3]计算出的w(n),成员parent表示该结点的父结点,成员next表示在链表存储结构中该结点的下一个节点,成员layer表示该结点所处的层数。

编程规则:
空格周围的棋子可以向空格移动,换种角度看,也就是空格可以向上下左右四个方向移动,假设空格所处的位置为(a,b),则有四条规则:
(1)如果a-1>=0,则空格可以向上移动,数码牌的布局改变如下c[a][b]= c[a-1][b],
c[a-1][b]=0;
(2)如果b-1>=0,则空格可以向左移动,数码牌的布局改变如下c[a][b]= c[a][b-1],
c[a][b-1]=0;
(3)如果a+1<=2,则空格可以向下移动,数码牌的布局改变如下c[a][b]= c[a+1][b],
c[a+1][b]=0;
(4)如果b+1<=2,则空格可以向右移动,数码牌的布局改变如下c[a][b]= c[a][b+1],
c[a][b+1]=0;
A*搜索算法:取g(n)=d(n),h(n)=w(n),其中w(n)表示以目标为基准,结点n的状态中每一个数码牌与其目标位置之间的距离(不考虑夹在其间的数码牌)的总和,由于从结点n转换成目标结点至少需要w(n)步,所以对任意n,恒有w(n) ≤h*(n)。
简单程序说明:程序开始运行时,初始化两个链表(假设为a和b),一个存储未扩展的结点(相当于Open表,假设为a),一个存储已经扩展的结点(相当于Closed表,假设为b),首先将初始结点放在链表a的第一个位置,然后取出链表a的第一个元素,根据编程规则看可以对该元素对应的结点进行哪些扩展(即0数码牌可以怎么移动),如果能进行某种扩展,则生成新的对应结点(设为e),标记该结构体对应的成员变量C[3][3],quanzhi,parent,next,layer,然后查找在a中是否有某个结点的C值与该结点相同,如果没有,则在b中查找是否有某个结点的C值与该结点相同,如果也没有,则在链表中找到插入该结点的位置然后插入该结点e(a中按结点的quanzhi+layer由小到大排序,如果quanzhi+layer相同,则先生成的结点放在前面),如果在b中有某个结点(设为f)C值与该结点相同,则计算结点f的layer,比较e的layer与f的layer的大小,如果e的layer小于f的layer,也在链表中找到插入该结点的位置然后插入该结点e,如果e的layer大于等于f的layer,则不插入该结点e,如果a中有某个结点(假设为g)的C值与该结点相同,则计算结点g的layer,如果g的layer小于等于e的layer,则不插入该结点e,如果g的layer大于e的layer,则先删除结点g,然后在链表中找到插入该结点的位置然后插入该结点e,在一次扩展完成后,删除链表a的第一个结点,把它放入链表b中,循环进行,直到链表a的第一个元素的C值与目标相同(即移动结束)。
附:源代码
#include<stdio.h>
#include<malloc.h>
#include<process.h>
#include<math.h>
struct jiedian
{
int c[3][3];
int quanzhi;
jiedian *parent;
jiedian *next;
int layer;
};
typedef jiedian * lianbiao;
void fuzhi(int c[3][3],int d[3][3])
{
for(int i1=0;i1<=2;i1++)
{
for(int j1=0;j1<=2;j1++)
{
c[i1][j1]=d[i1][j1];
}
}
}
void Initlianbiao(lianbiao &l)
{
l=(lianbiao)malloc(sizeof(jiedian));
if(!l)
exit(1);
l->parent=NULL;
l->next=NULL;
}
int LocateWeizhi(lianbiao a,jiedian b)
{
int i=0;
lianbiao p=a->next;
while(p)
{
i++;
if((p->quanzhi+p->layer)>(b.quanzhi+b.layer))
return i;
if((p->quanzhi+p->layer)==(b.quanzhi+b.layer))
{
int j=i+1;
return j;
}
p=p->next;
}
return (i+1);
}
int Insertjiedian(lianbiao a,int i,jiedian b)
{
int j=0;
lianbiao s,p=a;
while(p&&j<i-1)
{
j++;
p=p->next;
}
s=(lianbiao)malloc(sizeof(jiedian));
fuzhi(s->c,b.c);
s->layer=b.layer;
s->parent=b.parent;
s->quanzhi=b.quanzhi;
s->next=p->next;
p->next=s;
return 1;
}
int DeleteJiedian(lianbiao a,int i)
{
int j=0;
lianbiao q,p=a;
while(p&&j<i-1)
{
j++;
p=p->next;
}
if(!p->next||j>i-1)
return 0;
q=p->next;
p->next=q->next;
return 1;
}
int compare1(int c[3][3],int d[3][3])
{
for(int i1=0;i1<=2;i1++)
{
for(int j1=0;j1<=2;j1++)
{
if(d[i1][j1]!=c[i1][j1])
return 0;
}
}
return 1;
}
bool find0(lianbiao a,jiedian b)
{
lianbiao p=a->next;
while(p)
{
if(compare1(p->c,b.c)==1)
return true;
p=p->next;
}
return false;
}
int find(lianbiao a,jiedian b)
{
int i=0;
lianbiao p=a->next;
while(p)
{
i++;
if(compare1(p->c,b.c)==1)
return p->layer;
p=p->next;
}
return 1000;
}
int find1(lianbiao a,jiedian b)
{
int i=0;
lianbiao p=a->next;
while(p)
{
i++;
if(compare1(p->c,b.c)==1)
return i;
p=p->next;
}
}
int compare2(int c[3][3],int d[3][3])
{
int distance=0;
for(int i = 0; i<3; i++)
for (int j = 0;j<3; j++)
for (int k = 0; k<3; k++)
for (int l = 0; l<3; l++)
if (c[i][j] == d[k][l]&&c[i][j]!=0)
distance +=abs(i - k)+abs(j - l);
return distance;
}
void print(int w[][3],int i,int j)
{
for(int i0=0;i0<=i;i0++)
{
printf("/n");
for(int j0=0;j0<=j;j0++)
printf("%d",w[i0][j0]);
}
}
void shuchu(lianbiao a)
{
jiedian shuzu[100];
lianbiao b=a->next;
int u=0;
while(b)
{
u=u+1;
fuzhi(shuzu[u].c,b->c);
b=b->parent;

}
for(int i=u;i>=1;i--)
{
print(shuzu[i].c,2,2);
printf("/n");
if(i!=1)
printf("ˇ%d",u-i+1);
}
printf("/n");
}
int main()
{

int a[3][3];
int i;
int j;
int i0;
int j0;
int top=1;
for(i=0;i<=2;i++)
{
printf("/n");
for(j=0;j<=2;j++)
scanf("%d",&a[i][j]);
}
int b[3][3]={{1,2,3},{8,0,4},{7,6,5}};
int d[3][3];
int shang[3][3],xia[3][3],zuo[3][3],you[3][3];
lianbiao r;
Initlianbiao(r);
lianbiao l;
Initlianbiao(l);
jiedian a0;
fuzhi(a0.c,a);
a0.layer=0;
a0.quanzhi=compare2(a0.c,b);
a0.parent=NULL;
a0.next=NULL;
Insertjiedian(l,1,a0);
static int h=1;
while(compare1(l->next->c,b)!=1)
{
lianbiao aa=l->next;
jiedian bb=*aa;
Insertjiedian(r,h,bb);
h++;
int m,m0;
fuzhi(d,aa->c);
fuzhi(shang,aa->c);
fuzhi(xia,aa->c);
fuzhi(zuo,aa->c);
fuzhi(you,aa->c);
for(i=0;i<=2;i++)
{
for(j=0;j<=2;j++)
{
if(d[i][j]==0)
{
i0=i;
j0=j;
break;
}
}
}
if(i0-1>=0)
{

shang[i0][j0]=shang[i0-1][j0];
shang[i0-1][j0]=0;
jiedian shang1;
fuzhi(shang1.c,shang);
shang1.parent=aa;
shang1.layer=(aa->layer)+1;
shang1.quanzhi=compare2(shang1.c,b);
shang1.next=NULL;
if(find0(l,shang1)==false)
{
if(find0(r,shang1)==false)
{
m=LocateWeizhi(l,shang1);
Insertjiedian(l,m,shang1);
}
else
{
int y=find(r,shang1);
if(shang1.layer<y)
{
m0=LocateWeizhi(l,shang1);
Insertjiedian(l,m0,shang1);
}

}
}
else
{
int x=find(l,shang1);
if(x<=shang1.layer)
{
}
else
{
int k=find1(l,shang1);
DeleteJiedian(l,k);
m=LocateWeizhi(l,shang1);
Insertjiedian(l,m,shang1);
}
}
}
if(j0-1>=0)
{
zuo[i0][j0]=zuo[i0][j0-1];
zuo[i0][j0-1]=0;
jiedian zuo1;
fuzhi(zuo1.c,zuo);
zuo1.parent=aa;
zuo1.layer=aa->layer+1;
zuo1.quanzhi=compare2(zuo,b);
if(find0(l,zuo1)==false)
{
if(find0(r,zuo1)==false)
{
m=LocateWeizhi(l,zuo1);
Insertjiedian(l,m,zuo1);
}
else
{
int y=find(r,zuo1);
if(zuo1.layer<y)
{
m0=LocateWeizhi(l,zuo1);
Insertjiedian(l,m0,zuo1);
}

}
}
else
{
int x=find(l,zuo1);
if(x<=zuo1.layer)
{
}
else
{
int k=find1(l,zuo1);
DeleteJiedian(l,k);
m=LocateWeizhi(l,zuo1);
Insertjiedian(l,m,zuo1);
}
}
}
if(i0+1<=2)
{
xia[i0][j0]=xia[i0+1][j0];
xia[i0+1][j0]=0;
jiedian xia1;
fuzhi(xia1.c,xia);
xia1.parent=aa;
xia1.layer=aa->layer+1;
xia1.quanzhi=compare2(xia,b);
if(find0(l,xia1)==false)
{
if(find0(r,xia1)==false)
{
m=LocateWeizhi(l,xia1);
Insertjiedian(l,m,xia1);
}
else
{
int y=find(r,xia1);
if(xia1.layer<y)
{
m0=LocateWeizhi(l,xia1);
Insertjiedian(l,m0,xia1);
}

}
}
else
{
int x=find(l,xia1);
if(x<=xia1.layer)
{
}
else
{
int k=find1(l,xia1);
DeleteJiedian(l,k);
m=LocateWeizhi(l,xia1);
Insertjiedian(l,m,xia1);
}
}
}
if(j0+1<=2)
{
you[i0][j0]=you[i0][j0+1];
you[i0][j0+1]=0;
jiedian you1;
fuzhi(you1.c,you);
you1.parent=aa;
you1.layer=aa->layer+1;
you1.quanzhi=compare2(you,b);
if(find0(l,you1)==false)
{
if(find0(r,you1)==false)
{
m=LocateWeizhi(l,you1);
Insertjiedian(l,m,you1);
}
else
{
int y=find(r,you1);
if(you1.layer<y)
{
m0=LocateWeizhi(l,you1);
Insertjiedian(l,m0,you1);
}

}
}
else
{
int x=find(l,you1);
if(x<=you1.layer)
{
}
else
{
int k=find1(l,you1);
DeleteJiedian(l,k);
m=LocateWeizhi(l,you1);
Insertjiedian(l,m,you1);
}
}
}
DeleteJiedian(l,1);
}
shuchu(l);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: