迷宫问题
以一个m*n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。
要求:
(1)首先实现一个以链表作存储结构的栈类型,然后编写一个求解迷宫的非递归程序。求得的通路以三元组(i,j,d)的形式输出,其中(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。
(2)测试几组数据,数据的规模由小变大,即网格越来越小,障碍越来越复杂。
(3)实现该问题的可视化界面。
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<stdlib.h>
#include<ctype.h>
#include<algorithm>
#include<vector>
#include<string.h>
#include<stack>
#include<set>
#include<map>
#include<sstream>
#include<time.h>
#include<utility>
#include<malloc.h>
#include<stdexcept>
#include<iomanip>
#include<iterator>
using namespace std;
int n, m, sx, sy, ex, ey, t;
int p[110][110];
char MAP[110][110];
int vis[110][110];
int dir[4][2] = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
struct node
{
int x;
int y;
};
struct node pre[30][30];//存储节点前一个位置
// 栈
#define DataType node
struct Node;
typedef struct Node *PNode;
typedef struct Node
{
DataType info;
PNode link;
}Node;
typedef struct LinkStack
{
PNode top;
}LinkStack;
typedef struct LinkStack * PLinkStack;
PLinkStack createEmptyStack(void);
int isEmptyStack(PLinkStack stack);
int push(PLinkStack stack, DataType x);
int pop(PLinkStack stack);
DataType getTop(PLinkStack stack);
void showStack(PLinkStack stack);
void setEmpty(PLinkStack stack);
void destroyStack(PLinkStack stack);
PLinkStack createEmptyStack(void)
{
PLinkStack stack = (PLinkStack)malloc(sizeof(struct LinkStack));
if (stack == NULL)
printf("存储分配失败,请重建栈!\n");
else
stack->top = NULL;
return stack;
}
int isEmptyStack(PLinkStack stack)
{
return (stack->top == NULL);
}
int push(PLinkStack stack, DataType x)
{
PNode p = (PNode)malloc(sizeof(struct Node));
if (p == NULL)
{
printf("新结点分配内存失败,进栈失败,请重试!\n");
return 0;
}
else
{
p->info = x;
p->link = stack->top;
stack->top = p;
return 1;
}
}
int pop(PLinkStack stack)
{
if (isEmptyStack(stack))
{
printf("栈为空!\n");
return 0;
}
else
{
PNode p;
p = stack->top; //删除最后一个结点
stack->top = stack->top->link;
free(p);
return 1;
}
}
DataType getTop(PLinkStack stack)
{
if (isEmptyStack(stack))
{
printf("栈为空!取栈顶元素失败!\n");
}
return (stack->top->info);
}
void showStack(PLinkStack stack)
{
if (isEmptyStack(stack))
printf("当前栈为空!无内容可显示。\n");
else
{
PNode p;
p = stack->top;
printf("顶--> ");
while (p->link != NULL)
{
printf("%d ", p->info);
p = p->link;
}
printf("%d ", p->info);
printf("-->底\n");
}
}
void setEmpty(PLinkStack stack)
{
stack->top = NULL;
}
void destroyStack(PLinkStack stack)
{
if (stack)
{
stack->top = NULL;
free(stack);
}
}
///
int check(int x, int y)
{
if (x >= 0 && x < m && y >= 0 && y < n)
return 1;
return 0;
}
void printf_path()
{
node ss,sss;
DataType data;
PLinkStack stack;
stack = createEmptyStack();
ss.x = ex;
ss.y = ey;
while (1)
{
push(stack, ss);
if (ss.x == sx && ss.y == sy)
break;
ss = pre[ss.x][ss.y];
}
int pres, presy;
printf (" 行走路径 文字描述如下:\n\n\n");
while (!(isEmptyStack(stack)))
{
ss = getTop(stack);
pop(stack);
MAP[ss.x+1][ss.y+1] = '*';
if (!(isEmptyStack(stack)))
sss = getTop(stack);
printf(" ");printf("此刻坐标(%d, %d) ", ss.x, ss.y);
if (!(isEmptyStack(stack)))
{
if (sss.x == ss.x && sss.y == ss.y + 1)
printf("向右走\n");
if (sss.x == ss.x && sss.y == sss.y - 1)
printf("向左走\n");
if (sss.x == ss.x + 1 && sss.y == sss.y)
printf("向下走\n");
if (sss.x == ss.x - 1 && sss.y == sss.y)
printf("向上走\n");
}
}printf("到达终点!\n\n\n\n");
printf (" 行走路径图如下:\n");
for(int i=0;i<=m+1;i++)
{
printf(" ");
for(int j=0;j<=n+1;j++)
{
if (j==0 || j== n+1)
printf("| ");
else if (i == 0 || i == m+1)
printf("—");
else
printf("%c ",MAP[i][j]);
}
printf("\n");
}
}
队列
#define Error( str ) FatalError( str )
#define FatalError( str ) fprintf( stderr, "%s\n", str ), exit( 1 )
#define ElementType node
#define MAXQUEUE 100
typedef struct NODE
{
ElementType data;
struct NODE* nextNode;
} NODE;
typedef struct queue
{
NODE* front; // 对首指针
NODE* rear; // 队尾指针
int items; // 队列中项目个数
} *ptrQueue;
typedef ptrQueue Queue;
int IsEmpty(Queue q);
int IsFull(Queue q);
Queue CreateQueue(void);
void DisposeQueue(Queue q);
void MakeEmpty(Queue q);
void Enqueue(ElementType x, Queue q);
ElementType Front(Queue q);
void Dequeue(Queue q);
int IsFull(Queue q)
{
return q->items == MAXQUEUE;
}
int IsEmpty(Queue q)
{
return q->items == 0;
}
Queue CreateQueue(void)
{
Queue q;
q = (Queue)malloc(sizeof(struct NODE));
if (NULL == q)
Error("空间不足,队列内存分配失败!");
q->front = (NODE*)malloc(sizeof(NODE));
if (NULL == q->front)
Error("空间不足,队列首节点内存分配失败!");
q->rear = (NODE*)malloc(sizeof(NODE));
if (NULL == q->rear)
Error("空间不足,队列尾节点内存分配失败!");
q->items = 0;
return q;
}
void DisposeQueue(Queue q)
{
MakeEmpty(q);
free(q);
}
void MakeEmpty(Queue q)
{
if (q == NULL)
Error("必须先使用CreateQueue创建队列!");
while (IsEmpty(q))
Dequeue(q);
}
void Enqueue(ElementType x, Queue q)
{
if (IsFull(q))
Error("队列已满!");
NODE* pnode;
pnode = (NODE*)malloc(sizeof(NODE));
if (NULL == pnode)
Error("新节点分配内存失败!");
pnode->data = x;
pnode->nextNode = NULL;
if (IsEmpty(q))
q->front = pnode; // 项目位于首端
else
q->rear->nextNode = pnode; // 链接到队列尾端
q->rear = pnode; // 记录队列尾端的位置
q->items++; // 项目数加1
return;
}
void Dequeue(Queue q)
{
if (IsEmpty(q))
Error("队列本身为空!");
NODE* pnode;
pnode = q->front;
q->front = q->front->nextNode;
free(pnode);
q->items--;
if (q->items == 0)
q->rear = NULL;
return;
}
ElementType Front(Queue q)
{
if (!IsEmpty(q))
return q->front->data;
Error("队列为空\n");
}
ElementType FrontAndDequeue(Queue q)
{
ElementType x;
if (IsEmpty(q))
Error("队列为空!");
else
{
q->items--;
x = q->front->data;
q->front = q->front->nextNode;
}
return x;
}
///
int bfs()
{
memset(vis, 0, sizeof(vis));
Queue sqQueue;
sqQueue = CreateQueue();
node qq, qqq;
qq.x = sx;
qq.y = sy;
vis[sx][sy] = 1;
Enqueue(qq, sqQueue);
while (!IsEmpty(sqQueue))
{
qq = Front(sqQueue);
Dequeue(sqQueue);
if (qq.x == ex && qq.y == ey)
{
printf_path();
return 1;
}
for (int i = 0; i < 4; i++)
{
int x = qq.x + dir[i][0];
int y = qq.y + dir[i][1];
if (!check(x, y) || vis[x][y] || p[x][y] == 1)
continue;
qqq = qq;
qqq.x = x;
qqq.y = y;
pre[qqq.x][qqq.y] = qq;
vis[x][y] = 1;
Enqueue(qqq, sqQueue);
}
}
return 0;
}
int main()
{
printf("请输入迷宫长和宽\n");
while (cin >> m >> n)
{
printf("输入起点坐标和终点坐标\n");
scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
printf("请输入迷宫\n");
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
cin >> p[i][j];
MAP[i+1][j+1] = p[i][j] + '0';
}
}
int ans = bfs();
if (ans == 0)
printf("不存在起点到终点的通路\n\n\n\n");
printf("\n\n\n\n");
printf("是否继续 1.yes 2.no\n ");
scanf("%d",&t);
if (t == 2) { printf(" 再见 ,谢谢使用本系统!\n\n\n"); return 0; }
printf("\n\n\n\n");
printf("请输入迷宫长和宽\n");
}
return 0;
}
测试数据:
5 5
0 0 4 4
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 1
0 0 0 1 0
1
5 5
0 0 4 4
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
2