分享
 
 
 

八数码(n*n-1数码)问题的代码

王朝other·作者佚名  2006-01-10
窄屏简体版  字體: |||超大  

实现了深度,广度,启发式搜索,启发函数为F=G*X+H*Y型

注意问题 :1.对已搜索的节点,不能简单的认为以后不需要搜索了,因为我们实际上是限定了搜索的深度的,在不容层上的即使局面一样,也不能简单的认为不需再往下搜索了。如果没有限定深度,这样假设是正确的。对于局面一样,且深度不小于已搜索的局面,可以直接剪裁掉,不需要搜索。

eight.h文件

#include <stdio.h>

#include <stdlib.h>

/*

by shaoxp@zju.edu.cn at 05-10-17

作为人工智能作业

*/

struct neightNode//深度,和广度搜索用的节点

{

int *state;//一种棋局

int depth;//该棋局所在的深度

int weight;//启发式搜索时用的,启发值

};

struct neightNodeLinkNode

{

struct neightNode *pneightNode;

struct neightNodeLinkNode *next;

};

eight.c文件

/*

by shaoxp@zju.edu.cn at 05-10-17

作为人工智能作业

*/

#include "eightNormal.h"

/*数码问题,0表示空位*/

static struct neightNodeLinkNode *searchLink;

static struct neightNodeLinkNode *phead,*ptail;

static struct neightNode *begin,*end,*curr;

static int neight;//neight数码问题

static int searchstep;

static int maxDepth;

static FILE * pf;//文件输出

static int searchPolicy;/*0 深度 1 广度 2 启发式*/

static int illumType,illumX,illumY;/*当启发式搜索时,该变量有用*/

static void initEight(int n,const int *startStat,const int *endStat,int maxD,FILE *pout)//n=3时,为8数码问题

{

neight=n;

maxDepth=maxD;

pf=pout;

if(pf==NULL)

pf=fopen("out.txt","w");

begin=(struct neightNode *)malloc(sizeof(struct neightNode));

end=(struct neightNode *)malloc(sizeof(struct neightNode));//为了后面回收方便

begin->state=(int *)malloc(n*n*sizeof(int));

end->state=(int *)malloc(n*n*sizeof(int));

for(int i=0;i<n*n;i++)

{

begin->state[i]=startStat[i];

begin->depth=1;

end->state[i]=endStat[i];

}

curr=begin;

searchstep=1;

searchLink=(struct neightNodeLinkNode*)malloc(sizeof(struct neightNodeLinkNode));

searchLink->pneightNode=curr;

searchLink->next=NULL;

phead=ptail=searchLink;

}

static int cmpStat(neightNode node1,neightNode node2)

{

for(int i=0;i<neight*neight;i++)

if(node1.state [i]!=node2.state[i])

return 1;

return 0;

}

static void cpyStat(neightNode *s,neightNode cd)

{

for(int i=0;i<neight*neight;i++)

s->state[i]=cd.state[i];

s->depth=cd.depth;

}

static void illum(int type,int x,int y,struct neightNode *pwillIllum);

static int dirMoveHole(int i,int j,int dir)

{

if(curr==NULL)

return -1;

neightNode node;

node.state=(int *)malloc(neight*neight*sizeof(int));/*可以优化一下*/

cpyStat(&node,*curr);

switch(dir)

{

case 4:

(node.state[i*neight+j])^=(node.state[(i-1)*neight+j])^=(node.state[i*neight+j])^=(node.state[(i-1)*neight+j]);//空移动

break;

case 3:

(node.state[i*neight+j])^=(node.state[i*neight+j-1])^=(node.state[i*neight+j])^=(node.state[i*neight+j-1]);

break;

case 2:

(node.state[i*neight+j])^=(node.state[(i+1)*neight+j])^=(node.state[i*neight+j])^=(node.state[(i+1)*neight+j]);

break;

case 1:

(node.state[i*neight+j])^=(node.state[i*neight+j+1])^=(node.state[i*neight+j])^=(node.state[i*neight+j+1]);

break;

}

struct neightNodeLinkNode *p=searchLink;

int haveCheck=0;

while(p!=phead)//察看是不是已经检查过,对已检查过深度要求不小于未检查过的,才不予考虑

{

if(!cmpStat(node,*(p->pneightNode))&&(node.depth>=p->pneightNode->depth))

{

haveCheck=1;

break;

}

p=p->next;

}

if(haveCheck!=1)//没,需要加入到待检查的队列中

{

struct neightNode *pstatNode = (struct neightNode*)malloc(sizeof(struct neightNode));

pstatNode->state=(int *)malloc(neight*neight*sizeof(int));

cpyStat(pstatNode,node);

(pstatNode->depth)++;

struct neightNodeLinkNode *plinkNode =(struct neightNodeLinkNode*)malloc(sizeof(struct neightNodeLinkNode));

plinkNode->pneightNode=pstatNode;

if(searchPolicy==0)//深度

{

plinkNode->next=phead->next;

phead->next=plinkNode;

}

else if(searchPolicy==1)//广度,需要从后面添加

{

plinkNode->next=NULL;

ptail->next =plinkNode;

ptail=plinkNode;

}

else

{

illum(illumType,illumX,illumY,pstatNode);

struct neightNodeLinkNode *q=p;

struct neightNodeLinkNode *p=phead->next;

while(p!=NULL&&p->pneightNode->weight<plinkNode->pneightNode->weight)

{

q=p;

p=p->next;

}

plinkNode->next=q->next;

q->next=plinkNode;

}

}

free(node.state);

return 0;

}

static int moveHole(int i,int j)

{

if(curr==NULL)

return -1;

if(searchPolicy==0)//深度

{

if(i!=0)

dirMoveHole(i,j,4);//north

if(j!=0)

dirMoveHole(i,j,3);//west

if(i!=neight-1)

dirMoveHole(i,j,2);//south

if(j!=neight-1)

dirMoveHole(i,j,1);//east

}

else //广度和启发搜索

{

if(j!=neight-1)

dirMoveHole(i,j,1);//east

if(i!=neight-1)

dirMoveHole(i,j,2);//south

if(j!=0)

dirMoveHole(i,j,3);//west

if(i!=0)

dirMoveHole(i,j,4);//north

}

return 0;

}

static int ifind(int fi,int *stat)

{

for(int i=0;i<neight*neight;i++)

if(stat[i]==fi)

return i;

printf("error\n");

exit(0);

}

static int generateNextMove()/*从状态CURR生成可能的后续状态,空格按东南西北(1234)的顺序移动,如果碰到已经测试的状态,则忽略*/

{

if(curr==NULL)

return -1;

if(curr->depth==maxDepth)//如已经到达最大深度,不往下搜索

return 0;

int n=ifind(0,curr->state);

int i,j;

i=n/neight;

j=n%neight;

moveHole(i,j);//从i,j处按东南西北的方向移动空

return 0;

}

static int moveNextStep()

{

if(curr==NULL)

return -1;

generateNextMove();//从curr状态生成可能的后续状态,放到链searchLink中

phead=phead->next;

if(phead!=NULL)

{

curr=phead->pneightNode;

searchstep++;

}

else

curr=NULL;

return 0;

}

static int success()

{

return !cmpStat(*curr,*end);

}

static int eeof()

{

return curr==NULL;

}

static void print()

{

printf("STEP %d ON DEPTH %d:\n",searchstep,curr->depth);

fprintf(pf,"STEP %d ON DEPTH %d:\n",searchstep,curr->depth);

for(int i=0;i<neight;i++)

{

for(int j=0;j<neight;j++)

{

printf("%d ",curr->state[i*neight+j]);

fprintf(pf,"%d ",curr->state[i*neight+j]);

}

printf("\n");

fprintf(pf,"\n");

}

}

static void saveMem()

{

struct neightNodeLinkNode *p=searchLink;

struct neightNodeLinkNode *q;

while(p!=NULL)

{

q=p->next;

free(p->pneightNode->state);

free(p->pneightNode);

free(p);

p=q;

}

}

void df(int n, const int *startStat, const int *endStat,int maxD,FILE *pout)//深度搜索从startStat到endStat的n*n-1数码问题,maxD为最大深度

{

initEight(n,startStat,endStat,maxD,pout);

searchPolicy=0;

while(!eeof()&&!success())

{

print();

moveNextStep();

}

if(!eeof())

{

print();

printf("SUCCESS AT %dth on depth %d\n",searchstep,curr->depth);

printf("结果同样输出到out.txt文件了\n");

fprintf(pf,"SUCCESS AT %dth on depth %d\n",searchstep,curr->depth);

}

else

{

printf("FAILURE AT DEPTH %d\n",maxDepth);

printf("结果同样输出到out.txt文件了\n");

fprintf(pf,"FAILURE AT DEPTH %d\n",maxDepth);

}

saveMem();

}

void bf(int n,const int *startStat,const int *endStat,int maxD,FILE *pout)//广度搜索从startStat到endStat的n*n-1数码问题,maxD为最大深度

{

initEight(n,startStat,endStat,maxD,pout);

searchPolicy=1;

while(!eeof()&&!success())

{

print();

moveNextStep();

}

if(!eeof())

{

print();

printf("SUCCESS AT %dth on depth %d\n",searchstep,curr->depth);

printf("结果同样输出到out.txt文件了\n");

fprintf(pf,"SUCCESS AT %dth on depth %d\n",searchstep,curr->depth);

}

else

{

printf("FAILURE AT DEPTH %d\n",maxDepth);

printf("结果同样输出到out.txt文件了\n");

fprintf(pf,"FAILURE AT DEPTH %d\n",maxDepth);

}

saveMem();

}

static int countDiff(int *p1,int *p2)

{

int count=0;

for(int i=0;i<neight*neight;i++)

if(p1[i]!=p2[i])

count++;

return count;

}

static int countShortestSum(int *p1,int *endStat)

{

int sum=0;

for(int i=0;i<neight*neight;i++)

{

int n=ifind(p1[i],endStat);

sum+=(abs(n/neight-i/neight)+abs((n%neight)-(i%neight)));

}

return sum;

}

static void illum(int type,int x,int y,struct neightNode *pwillIllum)//启发函数,启发函数的形式为f=g*x+h*y,其中x,y表示g,h分别所占的权重

/*type:

1: g表示深度,h表示pwillIllum状态中放错位置的节点总数

2: g表示深度,h表示pwillIllum状态中各数字现在所处的位置和正确的位置最短距离的总和

*/

{

if(pwillIllum!=NULL)

{

switch(type)

{

case 1:

int diff;

diff=countDiff(pwillIllum->state ,end->state);

pwillIllum->weight=pwillIllum->depth*x+diff*y;//计算启发函数

break;

case 2:

int shortestSum;

shortestSum=countShortestSum(pwillIllum->state,end->state);

pwillIllum->weight=pwillIllum->depth*x+shortestSum*y;

break;

}

}

}

void ill(int n,const int *startStat,const int *endStat,int maxD,int illtype,int illx,int illy,FILE *pout)//启发式搜索,

{

initEight(n,startStat,endStat,maxD,pout);

searchPolicy=2;

illumType=illtype;

illumX=illx;

illumY=illy;

while(!eeof()&&!success())

{

print();

moveNextStep();

}

if(!eeof())

{

print();

printf("SUCCESS AT %dth on depth %d\n",searchstep,curr->depth);

printf("结果同样输出到out.txt文件了\n");

fprintf(pf,"SUCCESS AT %dth on depth %d\n",searchstep,curr->depth);

}

else

{

printf("FAILURE AT DEPTH %d\n",maxDepth);

printf("结果同样输出到out.txt文件了\n");

fprintf(pf,"FAILURE AT DEPTH %d\n",maxDepth);

}

saveMem();

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有