您的位置:首页 > 其它

迷宫的寻找路径和最短路径的动画演示

2012-03-30 09:47 281 查看
这是自己编写的第一个dos动画程序,所以自己感触很深,今天作为一个成就,写于自己的博客中,希望和大家分享~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



定义头文件t11.h中

#include"stdio.h"

#include"string.h"

#include"ctype.h"

#include"malloc.h"

#include"stdlib.h" //atoi(),exit();

#include"io.h" //eof()

#include"math.h"

#define TRUE 1

#define FALSE 0

#define OK 1

#define ERROR 0

typedef int Status;

typedef int Boolean;

定义存储数据结构包含于m1.h头文件

#define INIT_STACK_SIZE 40

#define STACK_ADD 10

#define INIT_QUEUE 100

#define INIT_ADD 40

typedef struct

{

int road;

int foot;

int direct;

}migong,*mi;

typedef struct

{

mi elem; // 定义能够接受迷宫结构体指针的变量

int size; // 记录迷宫初始化大小

}ji,*hui;

typedef struct

{

int i; // 行

int j; // 列

}cun;

typedef struct // 把位子放入栈中 线性表操作

{

cun *top;

cun *bottom;

int stacksize;

} Sqstack;

typedef struct sq

{

int i,j; //存放前面的下标位置

int i1,j1; // 存放当前位置

}sq;

typedef struct //定义队列数据结构

{

sq*front;

sq*rear;

int size;

}dui;

定义实现函数包含于migong.cpp文件中

void initdui(dui &L) // 初始化队列

{

L.front=(sq*)malloc(INIT_QUEUE*sizeof(sq));

L.rear=L.front;

if(!L.front)

{

printf("内存分配失败!!");

exit(1);

}

L.size=INIT_QUEUE;

printf("初始化成功!! \n");

}

void enqueue(dui &L,int i,int j,int i1,int j1) // 此队列针对迷宫先全部进完后再出,而设的顺序队列

{

if(L.rear-L.front>L.size) // 队列已满,追加空间

{

L.front=(sq*)realloc(L.front,(L.size+INIT_ADD)*sizeof(sq));

if(!L.front)

{

printf("追加空间失败!!");

exit(1);

}

}

L.rear->i=i;

L.rear->j=j;

L.rear->i1=i1;

(L.rear++)->j1=j1;

}

void initstack(Sqstack &L) // 初始化栈操作

{

L.bottom=(cun*)malloc(INIT_STACK_SIZE*sizeof(cun));

if(!L.bottom)

{

printf("内存分配失败!!");

exit(-1);

}

L.top=L.bottom;

L.stacksize=INIT_STACK_SIZE;

}

Status push(Sqstack &L,int q,int p) // 压入位置 q表示行,p表示列

{

if(L.top-L.bottom >= L.stacksize)

{ L.bottom=(cun*)realloc(L.bottom,(L.stacksize+STACK_ADD)*sizeof(cun));

if(!L.bottom)

{

printf("内存分配失败!!");

exit(-1);

}

L.top=L.bottom+L.stacksize;

L.stacksize+=STACK_ADD;

}

L.top->i=q;

(L.top++)->j=p;

return OK;

}

Status pop(Sqstack &L,int &k,int &l) // 弹出 将栈顶的元素带回

{

if(L.top == L.bottom)

return ERROR;

k=(--L.top)->i; // 这点自己犯的问题 不能--L.top->i 这样就表示值减1 没意义,出错

l=L.top->j;

return OK;

}

Status emptystack(Sqstack L) // 判断栈为空

{

if(L.top == L.bottom)

return OK;

else

return ERROR;

}

void init(ji &L) // 初始化数据

{

printf("输入迷宫的行大小:");

scanf("%d",&L.size);

L.size+=2;

L.elem=(mi)malloc(L.size*L.size*sizeof(migong));

if(!L.elem)

{

printf("分配内存失败!!");

exit(1);

}

printf("初始化成功!\n");

}



void print(ji L)

{

int m;

// printf("打印输出!!\n\n");

m=L.size*L.size;

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

{

//if((i+1)%L.size != 1 && (i+1)%L.size != 0 && i>L.size-1 && i<m-L.size+1 )

if( (L.elem+i)->road == 0)

{

printf("▇");

}

else

printf(" ");



if((i+1)%L.size == 0)

printf("\n");







}

printf("\n");

}

void shuru(ji &L,int &e)

{

int m=L.size*L.size;

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

{

(L.elem+i)->direct=1;

(L.elem+i)->foot=0;

if((i+1)%L.size == 1 || (i+1)%L.size == 0 || i<=L.size-1 || i>=m-L.size+1)

(L.elem+i)->road=0;

else

(L.elem+i)->road=1; // 表示通路,初始化全部为

}

// print(L);

printf("设置墙:\n");

printf("输入迷宫的行和列:");

int k,j;

char ch='y';

while('Y' == ch || 'y' == ch)

{

scanf("%d%d",&k,&j);

(L.elem+k*L.size+j)->road=0;

e++;

printf("是否继续(Y/y):");

getchar();

ch=getchar();

}

// print(L);

getchar();

}

void shituan(ji &L,int z,int x,int &m,int &n) // 判断方向

{



switch((L.elem+L.size*z+x)->direct) // 线性表中位置的转换

{

case 1:m=z,n=x+1;break;

case 2:m=z+1,n=x;break;

case 3:m=z,n=x-1;break;

case 4:m=z-1,n=x;break;

}

}

void chuli(ji &L,dui &T,Sqstack &R)

{

int m=1,n=1,i=1,j=1;

int q=0,p,t;

sq*w=T.front-1,*r;

//printf("开始执行!!");

//getchar();

enqueue(T,1,1,1,1);

(L.elem+L.size+1)->foot=1;

t=1;



while(m != L.size-2 || n != L.size-2) // 循环条件是不是最后一个位置

{

// printf("进入循环!!");

// getchar();

r=w;

q=0;

for(p=1;p<=t;p++)

{



w++; // 查询入队元素的位置,不停的更新

i=w->i; // 取得已经入队元素的当前位置坐标

j=w->j;

while((L.elem+L.size*i+j)->direct <= 4) // 寻找4个方位 满足条件的位置

{

// printf("进入内部循环!!");

shituan(L,i,j,m,n);

if((L.elem+L.size*m+n)->road != 0 && (L.elem+L.size*m+n)->foot != 1) // 该位置不是墙也不是已经走过的路径

{

enqueue(T,m,n,i,j); // 压入位置

q++; // 入队元素个数记录

(L.elem+L.size*m+n)->foot=1; // 留下足迹

}



(L.elem+L.size*i+j)->direct++;

if(m == L.size-2 && n == L.size-2) // 找到最后一个跳出循环

break;

}

if(m == L.size-2 && n == L.size-2)

break;



}

t=q; // 将q循环的值放入t中,最为下次循环的终止条件

if(r == w)

{

printf("无通路!!\n");

exit(1);

}

if(m == L.size-2 && n == L.size-2)

break;

}



m=(--T.rear)->i; // 队列中的最后一个入队元素中是最后一个位置

n=T.rear->j;

push(R,m,n);

i=T.rear->i1;

j=T.rear->j1;

(L.elem+L.size*m+n)->road=2;

// printf("进入第二个循环!!");

// getchar();

while(T.rear != T.front) // 往上一直寻找

{

m=(--T.rear)->i;

n=T.rear->j;

if(i == m && j == n)

{

push(R,m,n);

(L.elem+L.size*m+n)->road=2; // 通路置为2

i=T.rear->i1;

j=T.rear->j1;

// push(R,i,j);

}

}





// print(L); // 打印路径

}

void chuli1(ji &L,Sqstack &T)

{

int m,n,i=1,j=1;

//printf("开始执行!!");



while(m!=L.size-2 || n!=L.size-2) // 循环条件是不是最后一个位置

{

shituan(L,i,j,m,n);

(L.elem+L.size*i+j)->direct++;

if((L.elem+L.size*m+n)->road != 0 && (L.elem+L.size*m+n)->foot != 1) // 该位置不是墙也不是已经走过的路径

{

push(T,i,j); // 压入位置

(L.elem+L.size*i+j)->foot=1; // 留下足迹

(L.elem+L.size*i+j)->road=2; // 将通路为置为2,表示路径

i=m;

j=n;

}

else if((L.elem+L.size*i+j)->direct >4) // 4个方向都没有路了

{

if(emptystack(T)) // 当前栈里面是否有元素

{

printf("无通路!!!~~~~~~~~~~~~~\n试探路径为:\n");

print(L);

exit(1); // 退出程序

}

(L.elem+L.size*i+j)->road=-1; // 将走过的路,不通的留下记号,标记为-1

(L.elem+L.size*i+j)->foot=1; // 留下足迹



pop(T,i,j); // 不通的路径出栈



}





}

if(m == L.size-2 && n == L.size-2) // 将最后一个位置为留下2

{

(L.elem+L.size*m+n)->road=2;

push(T,m,n);

}



// print(L);

}

void GotoConsoleXY(HANDLE hConsole,int x,int y) // 定位光标位置

{

COORD coordScreen={x,y};

SetConsoleCursorPosition(hConsole,coordScreen);

return;

}

void gotoxy(int x,int y) // 定位光标位置

{

HANDLE hStdOut=GetStdHandle(STD_OUTPUT_HANDLE);

GotoConsoleXY(hStdOut,x,y);

return;

}

void move(int m,int n,int p,int q,int e)

{

gotoxy(2*n,m+e); // 将上一个位置的“中”用空格代替

printf(" ");

gotoxy(2*q,e+p); // 下一个用“中”代替

printf("中");



}

void huatu(Sqstack &L,int &e,int &i) // 画图,产生动画

{

int x1,y1,x2,y2;

pop(L,x1,y1); // 弹出栈的第一个元素

gotoxy(2*x1,e+y1);

i=1;

printf("中"); // 将位置画出起始位置

getchar();

while(!emptystack(L)) // 直到栈元素全部弹出

{

pop(L,x2,y2);

move(x1,y1,x2,y2,e);

x1=x2;

y1=y2;

i++;

Sleep(500); // 暂停0.5秒



}

}

定义主函数中调用包含于main_5中



#include"t11.h"

#include "windows.h" // 包含暂停函数

#include"m1.h"

#include"migong.cpp"

void main()

{



int x1,y1,e=0,k;

ji S;

dui T;

Sqstack X,R,F; // 设立栈,将路径入栈

initdui(T);

init(S);

initstack(X);

initstack(R);

initstack(F);

shuru(S,e);

e=2*e+4; // 算出光标的位置

chuli1(S,X);

while(!emptystack(X)) // 将栈重新调整

{

pop(X,x1,y1);

push(F,x1,y1);

}



print(S); // 打印出迷宫图案

huatu(F,e,k); // 画图函数,找出按规定算法的路径



printf("\n\n恭喜你一条路径出来啦!! 历经%d步\n",k);







int m=S.size*S.size; // 保存长度值

for(int i=0;i<m;i++) // 对比,将用户设置的墙不变,其他回归初始状态

{

if((S.elem+i)->road != 0)

(S.elem+i)->road=1;

(S.elem+i)->direct=1;

(S.elem+i)->foot=0;

}

chuli(S,T,R); // 做出处理



print(S); // 打印路径

e=e+S.size+1; // 算出此刻光标位置



huatu(R,e,k); // 找出最短路径

printf("\n\n恭喜你最短路径出来啦!! 历经%d步\n",k);









}



这是全部自己思想编写出来的,我很享受思考的过程,虽然会有困难,但这是一个很有意思的过程,不仅需要严谨的逻辑思维还需要充分的耐心。

贴上代码下载代码:http://download.csdn.net/detail/wu10045125/4679590
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: