您的位置:首页 > 理论基础 > 数据结构算法

数据结构——八方向探索迷宫问题解答

2016-06-08 11:20 489 查看
/*

 水平有限,仅供参考

题目要求:用c语言动态演示如何走出带颜色的迷宫,并输出路径。要求探测八个方向,动态生成迷宫大小,路径用队列来存储,输出路径时用栈完成。

*/

#include<stdio.h>

typedef int ElemType;

typedef struct Data{
int r,c;  // 迷宫的行列
ElemType e;   // 上一个可通过迷宫在三元组中的位置

}SElemType,QElemType;    

#include<stdio.h>

#include"MStack.h"  // 栈的头文件

#include"MQueue.h"  // 队列的头文件

#include<stdlib.h>

#include<time.h>

#include<windows.h>

ElemType** createPuzzle(int ,int );  //   随机产生迷宫

Status rand(ElemType **,int ,int );  // 随机产生迷宫障碍物

Status showPuzzle(ElemType **, int , int );  // 输出迷宫

Status printPuzzle(ElemType **,SqStack *, int , int );  // 打印迷宫

ElemType findPath(ElemType **,ElemType **,QNode *,int i,int j,int d[][2]);   // 判断8个方向是否可以通行,并入队列

Status PushData(QNode ,SqStack *);   //  将通过的路径放进栈

int num=1;

void main(){         //   ========================   主函数    ================================================

int r,c;  //  随机产生迷宫的大小
int flag;  // 判断是否走出了迷宫
int k;
int Directrion[8][2]={{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0}};   // 逆时针方向寻找路径
ElemType **m=NULL,**mark=NULL;
SqStack *s,s1;
QNode *Q,q;
Q=&q;s=&s1;

    InitQueue(Q); // 初始化 ======
InitStack(s);
printf("请输入迷宫的大小!\n");
scanf("%d%d",&r,&c);
r=r+2;c=c+2;  // 迷宫外部需要加上墙,所以数组大小加2(上下,左右)
m=createPuzzle(r,c);  // 动态产生迷宫 m 
mark=createPuzzle(r,c);   // 标记走过的位置
for(int i=0;i<r;i++)
for(int j=0;j<c;j++)
mark[i][j]=false;   //  false 表示没有走过的位置
rand(m,r,c);  // 随机产生迷宫障碍物
flag=findPath(m,mark,Q,r,c,Directrion);  // 寻找路径
if(flag==1){    // 可以走出迷宫
PushData(q,s);
k=s->top;
k++;
for(int i=0;i<k;i++){
system("cls");
printPuzzle(m,s,r,c);  // 打印迷宫
num++;
Sleep(500);
}
StackTraverse(s1);   // 输出坐标
}
else
{
showPuzzle(m,r,c);
printf("No Path!\n");
}

}

ElemType** createPuzzle(int row,int column){  // 实现 创建矩阵 函数
ElemType **a;
a = (int **)malloc(sizeof(int *) * row);//分配指针数组
for(int i=0; i<row; i++)
{
a[i] = (int *)malloc(sizeof(int) * column);//分配每个指针所指向的数组
}
return a;

}

Status rand(ElemType **p,int row,int column){ // 随机产生迷宫
srand(unsigned(time(NULL)));
int r,c;
for(r=0;r<row;r++)   
for(c=0;c<column;c++){
if(r==0||c==0||r==row-1||c==column-1){   // 数组的第一行最后一行第一列最后一列均为墙
p[r][c]=1;
}
else{
p[r][c]=rand()%100;
if(p[r][c]>=40)
p[r][c]=0;    // 0 表示课通过 
else
p[r][c]=1;
}
}
p[1][1]=0;  //起点
p[row-2][column-2]=0;  // 终点
return OK;

}

Status printPuzzle(ElemType **m,SqStack *s, int row, int column){  // 打印迷宫
SElemType *data,data1;
int k=s->top;    // 记录栈元素的总个数
int num1=0;
int flag=1;
data=&data1;
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
if(i==0||j==0||i==row-1||j==column-1||m[i][j]==1){   //  输出迷宫墙
SetConsoleTextAttribute(GetStdHandle((STD_OUTPUT_HANDLE)),7);
printf("■");}
else{
data->r=i;
data->c=j;
if(searchStackData(s,data1)&&flag==1){
SetConsoleTextAttribute(GetStdHandle((STD_OUTPUT_HANDLE)),10);

printf("※");
num1++;
if(num1==num)
flag=0;
}
else{
printf("  ");
}
s->top=k;
}
}
printf("\n");  
}
return OK;

}

ElemType findPath(ElemType **m,ElemType **mark,QNode *Q,int row,int column,int d[][2]){          //     寻找路径  
SElemType *data,data1,data2;   //data2用于记录向不同方向探索的坐标
int flag=0;  // 判断是否走出迷宫
data=&data1;
data->c=1;  // 起点纵坐标
data->r=1;  // 起点横坐标
data->e=-1;  // 代表没有前一个元素 
EnQueue(Q,data1);  // 起点入队列
while(Q->front!=Q->rear){   // 队列非空 
int i,j;
DeQueue(Q,data);
i=data->r;  // 将行列赋给i j 便于加上方向判断是否有路径
j=data->c;
mark[i][j]=true;  // 表示已经走过
data2=data1;
data2.e=Q->front;   // 记录上个开始探索方向的初始位置
if((i==row-2)&&(j==column-2))   // 走出迷宫
{ flag=1;
 break;}
for(int k=0;k<8;k++){   // 搜索八个方向
i=data->r;j=data->c;
i+=d[k][0];j+=d[k][1];
if(m[i][j]==1||mark[i][j]==true)   // 遇见路障或者已在队列里
continue;
else{
data2.r=i;data2.c=j;
mark[i][j]=true;
EnQueue(Q,data2); // 找到通路,入队
}
} // for
Q->front++;
}  //while
return flag;

}

Status PushData(QNode q,SqStack *s){   //  将通过的路径放进栈
SElemType data1;
int i;
i=q.front;  // 上一个元素的位置
while(i!=-1){    // 起点的值为 -1
data1=q.base[i];
Push(s,data1);  // 坐标入栈
i=q.base[i].e;
}
return OK;

}

showPuzzle(ElemType **m, int row, int column){
SElemType *data,data1;
data=&data1;
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
if(i==0||j==0||i==row-1||j==column-1||m[i][j]==1)    //  输出迷宫墙
printf("■");
else
printf("  ");
}
printf("\n");  
}
return OK;
}

/* ==================================================            栈的头文件     ==========================================================*/

#ifndef _MSTACK_H_  

#define _MSTACK_H_

/* 如果没有定义_MSTACK_H_,则定义_MSTACK_H_,

并编译下面的代码部分,直到遇到#endif。这样,当重复引用时,

由于_MSTACK_H_已经被定义,则下面的代码部分就不会被编译了,

这样就避免了重复定义。  */

#include<windows.h>

#define STACK_INIT_SIZE 12500  // 存储空间初始分配量

#define STACKINCREMENT 10  // 存储空间分配增量

#define true 1

#define false 0

#define OK 1

#define OVERFLOW -1

typedef int Status; //函数返回类型,其值为结果状态码

 struct stack1{
SElemType base[STACK_INIT_SIZE];
int top;  //指示栈顶位置

};

 typedef struct stack1 SqStack;

 

Status Push(SqStack *s,SElemType data){      //  元素入栈
if(s->top==STACK_INIT_SIZE-1)
return OVERFLOW;
else{
s->top++;
s->base[(s->top)]=data;
}
return OK;

}

Status Pop(SqStack *s,SElemType *data){      //  栈顶元素出栈
if(s->top==-1)
return OVERFLOW;
else{
*data=s->base[s->top];
s->top--;
}
return OK;

}

Status Get(SqStack *s,SElemType *data){   // 得到栈顶元素
if(s->top==-1)
return OVERFLOW;
else{
*data=s->base[s->top];
}
return OK;

}

Status StackEmpty(SqStack *s){     //  判断栈是否为空
if(s->top==-1)
   return true;
else

    return false;

}

Status InitStack(SqStack *s){    //    初始化栈
s->top=-1;
if(!s->base)
return OVERFLOW;
return OK;

}

Status StackTraverse(SqStack s){         //栈元素的遍历
if(s.top==-1){
printf("栈已空!\n");
return OK;
}
while(s.top!=-1){
SetConsoleTextAttribute(GetStdHandle((STD_OUTPUT_HANDLE)),5);
printf("<%d:%d> ",s.base[s.top].r,s.base[s.top].c);  // 输出坐标
s.top--;
}
printf("\n");
SetConsoleTextAttribute(GetStdHandle((STD_OUTPUT_HANDLE)),7);
return OK;

}

Status searchStackData(SqStack *s,SElemType data){
while(s->top>=0){
if((s->base[s->top].r==data.r)&&(s->base[s->top].c==data.c))
return true;
s->top--;
}
return false;

}

#endif

/* ==================================================            队列的头文件     ==========================================================*/

#ifndef _MQUEUE_H_  

#define _MQUEUE_H_

/* 如果没有定义_MQUEUE_H_,则定义_MQUEUE_H_,

并编译下面的代码部分,直到遇到#endif。这样,当重复引用时,

由于_MQUEUE_H_已经被定义,则下面的代码部分就不会被编译了,

这样就避免了重复定义。  */

#include<malloc.h>

#include<stdlib.h>

#define ERROR 0   // 函数结果状态码

#define OK 1

#define OVERFLOW -1

#define true 1

#define false 0

#define STACK_INIT_SIZE 12500

typedef int Status;   // 函数返回值类型

typedef struct QUeue1{
QElemType base[STACK_INIT_SIZE];    
int front;  // 队头
int rear;  // 队尾

}QNode;

Status InitQueue(QNode *Q){  // 初始化队列
Q->front=0;  
Q->rear=0;
if(!Q->base)
return OVERFLOW;
return OK;

}

 Status QueueEmpty(QNode *Q){  // 判断队列是否为空
if(Q->front==Q->rear)
   return true;
else

    return false;

 }

Status EnQueue(QNode *Q,QElemType data){  // 入队列
if(Q->rear==STACK_INIT_SIZE-1)
return OVERFLOW;
else{
Q->base[(Q->rear)]=data;
Q->rear++;  //指向下一个元素
}
return OK;

}

Status DeQueue(QNode *Q,QElemType *data){  // 出队列,队列不为空,返回其值
if(Q->front==Q->rear)
return OVERFLOW;
else{
*data=Q->base[Q->front];

}
return OK;

}

#endif
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构 迷宫