用回溯法链表求解迷宫问题,并加上完整的人物演示过程 (按一键小人开始搜索)
创建人: 颜清国 2006年3月18日(下载源码(点击右键,目标另存为))
说明: 程序中按照上-右-下-左搜索,运行效果如图
#include"graphics.h" #include"stdio.h" #include"dos.h" #define LENGTH sizeof(struct Node) /****************************************** * 定义全局变量,用来保存PEOPLE的位置 * ******************************************/ struct site { int mapsite; /*定义是墙还是可移动的*/ int xnow; int ynow; }psite[18][25]; static int xp=1,yp=1,oldxp=1,oldyp=1;/*记录此时PAOPAO的位置和PAOPAO的个数*/ typedef struct Node /*定义链表结点的结构体*/ { int x,y; int direction; struct Node*next; }node; /*********************************** *栈的基本操作 ************************************/ int findnext(node*head,node*p,int *direct); node*initstack(int x,int y,int direction); void push(node*head,node*p); void pop(node*head,node**p); void gettop(node*head,node*p); int stackempty(node*head); void dispstack(node*head); /***************************************** * box()函数用来画出PAOPAO总的活动范围 * ******************************************/ void box(int x1,int y1,int x2,int y2) { line(x1,y1,x1,y2); line(x1,y1,x2,y1); line(x2,y1,x2,y2); line(x2,y2,x1,y2); } /****************************************** * 函数用来在屏幕上画PEOPLE * ******************************************/ void drawpeople(int x,int y,int color) { int people[8]; people[0]=x-6; people[1]=y-4; people[2]=x-10; people[3]=y+10; people[4]=x+10; people[5]=y+10; people[6]=x+6; people[7]=y-4; setcolor(color); ellipse(x,y-7,0,360,10,4); drawpoly(4,people); } /****************************************** * 函数用来移动PEOPLE在屏幕上的位置 * ******************************************/ void movepeople() { if(psite[yp][xp].mapsite==0 ) { drawpeople(psite[yp][xp].xnow,psite[yp][xp].ynow,4); drawpeople(psite[oldyp][oldxp].xnow,psite[oldyp][oldxp].ynow,1); } } /****************************************** * 函数用来初始化每个方格的属性和坐标, * * 其中属性来自外部的文件 * ******************************************/ void initsite() { FILE*fp; int i=0,j=0; char ch; if((fp=fopen("site.txt","r"))==NULL) { printf("the site not found"); exit(1); } while((ch=fgetc(fp))!=EOF) { if(ch==10) continue; else { psite[i][j].mapsite=ch-48;/*读取数组,存入MAPSITE[]*/ if((j+1)>=25) i++; j=(j+1)%25; } } for(i=0;i<18;i=i++)/*初始化网格的中心坐标*/ { for(j=0;j<25;j++) { psite[i][j].ynow=12+24*i; psite[i][j].xnow=j*24+12; } } for(i=0;i<18;i=i++) { for(j=0;j<25;j++) { switch(psite[i][j].mapsite) { case 0:break; case 1: { setfillstyle(8,4); bar3d(psite[i][j].xnow-12,psite[i][j].ynow-12,psite[i][j].xnow+12, psite[i][j].ynow+12,0,1); floodfill(psite[i][j].xnow,psite[i][j].ynow,4); /*画出地图对应的东西,0是走道,1是墙,2是栅栏*/ break; } case 2: { setfillstyle(11,3); bar(psite[i][j].xnow-12,psite[i][j].ynow-12,psite[i][j].xnow+12, psite[i][j].ynow+12); floodfill(psite[i][j].xnow,psite[i][j].ynow,3); break; } default:printf("error");exit(1); } } } } void initall() { int driver,mode; driver=DETECT; mode=0; registerbgidriver(EGAVGA_driver); initgraph(&driver,&mode,"//tc"); clearviewport(); setbkcolor(1); box(0,0,600,432); box(1,1,599,431); initsite(); drawpeople(psite[yp][xp].xnow,psite[yp][xp].ynow,4); /*paopao的初始显示位置*/ } /************************************** *创建头结点,并初始化第一个结点 *X,Y,DIRECTION为NODE结构体的域值 ****************************************/ node*initstack(int x,int y,int direction) { node*head=(node*)malloc(LENGTH);/*创建头结点*/ node*p=(node*)malloc(LENGTH); p->x=x; /*初始化第一个结点*/ p->y=y; p->direction=direction; p->next=NULL; head->next=p; return head; } /**************************************** *输出链表 ******************************************/ void dispstack(node*head) { node*p=head->next; if(stackempty(head)) { printf("stack empty!"); return; } while(p->next!=NULL) { printf("(%d,%d) <---- ",p->x,p->y); p=p->next; } printf("(%d,%d)",p->x,p->y); } /***************************************** *判断栈是否为空,返回1时为空,为0是非空 *******************************************/ int stackempty(node*head) { return(head->next==NULL); } /********************************************* *栈顶的元素出栈 *注意这里的第二叁数要为node**p *否则其返回时P指针变量的值不被改变 **********************************************/ void pop(node*head,node**p) { if(stackempty(head)) { printf("stack empty!"); return; } else { (*p)=head->next; head->next=(*p)->next; (*p)->next=NULL; } } /********************************************* *一元素入栈 **********************************************/ void push(node*head,node*p) { node*q=(node*)malloc(LENGTH); /*注意这里必须分配空间*/ if(stackempty(head)) { printf("stack empty!"); return; } else { q->x=p->x; /*简单的拷贝P里面的值域*/ q->y=p->y; q->direction=p->direction; q->next=head->next; head->next=q; } } /*********************************************** *注意此处node*p指针变量的内容未变 *但其指向的结构体单元的内容在返回后已经改变 ************************************************/ void gettop(node*head,node*p) { p->x=head->next->x; p->y=head->next->y; p->direction=head->next->direction; /*注意此处不用p=head->next,防止指针域被复制而破坏链表*/ } /************************************************* *寻找下一个可以走的路径 *找到返回1,否则返回0 *其中direct是该可走点的方位 **************************************************/ int findnext(node*head,node*p,int *direct) { int d=head->next->direction,flag=0; int x=head->next->x,y=head->next->y; /*用来保存当前点的值,以便恢复*/ while((d < 5) && (flag==0)) { d++; p->x=x; /*每次换方位搜索还原该点值*/ p->y=y; switch(d) { case 1: p->y --; /*搜索上*/ break; case 2: p->x ++; /*搜索右*/ break; case 3: p->y ++; /*搜索下*/ break; case 4: p->x --; /*搜索左*/ break; } if(psite[p->y][p->x].mapsite==0) { flag=1; } } if(d==5) { return 0; /*没有找到*/ } else { (*direct)=d; /*记录若下次退栈时从该方位+1处开始搜索*/ p->direction=0;/*新的结点从上方位开始搜索*/ return 1; /*已找到下一路径*/ } } void delays(double second) { long far*ptr=(long far*)0x0040006c; long current,final; current=*ptr; final=current+second*1193180/65536; while(current<=final) current=*ptr; } int main() { int direct=0; node*head,*p,*current=(node*)malloc(LENGTH); current->next=NULL; initall(); head=initstack(1,1,0);/*初始化头结点*/ while(!stackempty(head)) { gettop(head,current);/*取前一个或后一个结点*/ if((current->x == 23) && (current->y == 16))/*已经找到出口*/ { return 1; } else { if(findnext(head,current,&direct))/*搜索下一个,并且找到*/ { head->next->direction=direct;/*记录旧结点搜索到的方位*/ psite[head->next->y][head->next->x].mapsite=-1;/*标志已搜索过*/ push(head,current);/*当前结点入栈,其中方位号已置为上方*/ } else /*当前结点为死结点,不可走,退栈*/ { pop(head,¤t);/*回到了前一个结点*/ psite[head->next->y][head->next->x].mapsite=0;/*重新对上一结点搜索*/ } } oldxp=xp; oldyp=yp; xp=head->next->x; yp=head->next->y; movepeople(); delays(0.3); } }