人工智能-八数码问题

来源:互联网 发布:淘宝有名的软妹店 编辑:程序博客网 时间:2024/05/12 10:13

八数码问题是指这样一种游戏:将分别标有数字1238的八块正方形数码牌任意地放在一块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)

   简单程序说明:程序开始运行时,初始化两个链表(假设为ab),一个存储未扩展的结点(相当于Open表,假设为a),一个存储已经扩展的结点(相当于Closed表,假设为b),首先将初始结点放在链表a的第一个位置,然后取出链表a的第一个元素,根据编程规则看可以对该元素对应的结点进行哪些扩展(即0数码牌可以怎么移动),如果能进行某种扩展,则生成新的对应结点(设为e),标记该结构体对应的成员变量C[3][3]quanzhiparentnextlayer,然后查找在a中是否有某个结点的C值与该结点相同,如果没有,则在b中查找是否有某个结点的C值与该结点相同,如果也没有,则在链表中找到插入该结点的位置然后插入该结点ea中按结点的quanzhi+layer由小到大排序,如果quanzhi+layer相同,则先生成的结点放在前面),如果在b中有某个结点(设为fC值与该结点相同,则计算结点flayer,比较elayerflayer的大小,如果elayer小于flayer,也在链表中找到插入该结点的位置然后插入该结点e,如果elayer大于等于flayer,则不插入该结点e,如果a中有某个结点(假设为g)的C值与该结点相同,则计算结点glayer,如果glayer小于等于elayer,则不插入该结点e,如果glayer大于elayer,则先删除结点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;
}

原创粉丝点击