本文主要是介绍数据结构——八方向探索迷宫问题解答,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
/*
水平有限,仅供参考
题目要求:用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
这篇关于数据结构——八方向探索迷宫问题解答的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!