迷宫问题-数据结构课程设计

该文章描述了一个使用C语言实现的迷宫问题解决算法,包括初始化栈、深度优先搜索(DFS)和广度优先搜索(BFS)等关键功能。DFS用于找到一条通路,BFS则用于找到最短通路。程序还提供了路径打印和所有可能通路的输出功能。
摘要由CSDN通过智能技术生成

题目:迷宫问题

【问题描述】

以一个 m*n 的方阵表示迷宫, 0 1 分别表示迷宫中的通路和障碍。设计一个程序,对
任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。

【需求分析】

1 ) 声明一个初始化栈的函数,输入栈地址,可以将其初始化。
2 ) 声明一个判空函数,输入栈地址,判断栈是否为空,若为空,返回 TRUE,若不
为空,返回 FALSE.。
3 ) 声明一个入栈函数,输入栈地址和即将入栈的位置信息。
4 ) 出栈函数,输入栈地址,将栈顶下标 top 指向的元素返回,并将其移出栈。
5 ) 获取栈顶元素,输入栈地址,将栈顶元素输出。
6 ) 输入当前的位置,若位置在迷宫之内返回TRUE,若位置在迷宫之外,返回FALSE。
7 ) 写一个深度优先搜索的算法,输入当前位置,在屏幕上打印出一条通路。
8 ) 写一个广度优先搜索的算法,输入起点位置,在屏幕上打印出最短的一条通路
9 ) 输入一个栈地址,将栈内的路径打印出来。
10 ) 输入起点和一个栈,将所有的路径都打印在屏幕上
【算法设计和实现】

主要函数

{
void initStack( Stack * stack ); //初始化栈
bool isEmpty( Stack * stack ); //判断栈是否满
void push( Stack * stack , Position position ); //入栈
Position pop( Stack * stack ); //出栈
Position peek( Stack * stack ); //获取栈顶元素
bool isValid( int x , int y ); //判断坐标是否在迷宫范围内
bool dfs( int x , int y ); //深度优先搜索,找出一条通路
void bfs( int startX , int startY ); //广度优先搜索,找出最短通路 32
void printPathStack( Stack * stack ); //输出路径栈中的路径
void dfsAll( int x , int y , Stack * stack ); //深度优先搜索,找出所有可能的通路
}

存储结构

{
typedef struct {
int x, y; //迷宫中的坐标
int direction; //下一步的方向
} Position ;
int maze[ MAX_SIZE ][ MAX_SIZE ]; //迷宫数组
int visited[ MAX_SIZE ][ MAX_SIZE ]; //记录已访问的位置
int m, n; //迷宫的行数与列数
int exitX, exitY; //出口的坐标
//方向数组,表示上 右 下 左
int dx[4] = { -1,0,1,0 };
int dy[4] = { 0,1,0,-1 };
//栈结构
typedef struct {
Position data[ MAX_SIZE ];
int top;
} Stack ;
}

源程序代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 102
typedef struct {
int x, y;//迷宫中的坐标
int direction;//下一步的方向
}Position;
int maze[MAX_SIZE][MAX_SIZE];//迷宫数组
int visited[MAX_SIZE][MAX_SIZE];//记录已访问的位置
int m, n;//迷宫的行数与列数
int exitX, exitY;//出口的坐标
// 0 1 2 3
//方向数组,表示上 右 下 左
int dx[4] = { -1,0,1,0 };
int dy[4] = { 0,1,0,-1 };
//栈结构
typedef struct {
Position data[MAX_SIZE];
int top;
}Stack;
void initStack(Stack* stack);//初始化栈
bool isEmpty(Stack* stack);//判断栈是否满
void push(Stack* stack, Position position);//入栈
Position pop(Stack* stack);//出栈
Position peek(Stack* stack);//获取栈顶元素
bool isValid(int x, int y);//判断坐标是否在迷宫范围内
bool dfs(int x, int y);//深度优先搜索,找出一条通路
void bfs(int startX, int startY);//广度优先搜索,找出最短通路
void printPathStack(Stack* stack);//输出路径栈中的路径
void dfsAll(int x, int y, Stack* stack);//深度优先搜索,找出所有可能的通路
//初始化栈
void initStack(Stack* stack) {
stack->top = -1;//将栈顶元素赋值为-1
}
//判断栈是否为空
bool isEmpty(Stack* stack) {
return stack->top == -1;
}
//入栈
void push(Stack* stack, Position position) {
stack->data[++stack->top] = position;
}
//出栈
Position pop(Stack* stack) {
return stack->data[stack->top--];
}
//获取栈顶元素
Position peek(Stack* stack) {
return stack->data[stack->top];
}
bool isValid(int x, int y) {
return x >= 1 && x <= m && y >= 1 && y <= n;
}
//深度优先搜索,找出一条通路
bool dfs(int x, int y) {
if (x == exitX && y == exitY) {
visited[x][y] = 1;
return true;//找到出口,返回true
}
visited[x][y] = 1;//标记当前位置已访问
//挨个位置搜索,找到可以走的路
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (isValid(nx, ny) && visited[nx][ny] == 0 && maze[nx][ny] == 0) {
//如果下一个位置是通路,且未被访问过,则递归搜索
if (dfs(nx, ny)) {
//如果找到通路,则输出当前位置以及方向
printf("(%d %d %d)\n", x, y, i);
return true;
}
}
}
return false;//所有方向都无法继续搜索,则返回false
}
//广度优先搜索,找出最短通路。
void bfs(int startX, int startY) {
int dist[MAX_SIZE][MAX_SIZE];//记录起始点到每个位置的最短距离
memset(dist, -1, sizeof(dist));//初始化距离为-1
Position prev[MAX_SIZE][MAX_SIZE];//记录每个位置的前驱位置
memset(prev, -1, sizeof(prev));//初始化前驱为-1
dist[startX][startY] = 0;//起始点到自己的距离为0
//使用队列存储待访问位置
Position queue[MAX_SIZE * MAX_SIZE];
int front = 0;
int rear = 0;
queue[rear++] = (Position){ startX,startY,-1 };
while (front < rear) {
Position current = queue[front++];
if (current.x == exitX && current.y == exitY) {
break;//找到出口,停止搜索
}
for (int i = 0; i < 4; i++) {
int nx = current.x + dx[i];
int ny = current.y + dy[i];
if (isValid(nx, ny) && maze[nx][ny] == 0 && dist[nx][ny] == -1) {
//如果下一个位置是通路且未被访问过,则更新他的前驱信息和距离,并将之入
队
dist[nx][ny] = dist[current.x][current.y] + 1;
prev[nx][ny] = current;
queue[rear++] = (Position){ nx,ny,i };
}
}
}
if (dist[exitX][exitY] == -1) {
printf("无解\n");
return;
}
//输出最短路径
Position shortestPath[MAX_SIZE * MAX_SIZE];
int shortestPathLength = 0;
Position current = (Position){ exitX,exitY,-1 };//保存终点位置
while (current.x != startX || current.y != startY) {//向前遍历
shortestPath[shortestPathLength++] = current;
current = prev[current.x][current.y];
}
shortestPath[shortestPathLength++] = (Position){ startX, startY, -1 };//保存起点位置
(起始位置可以到任何一个通路,没有明确的方向)
for (int i = shortestPathLength-1 ; i >= 0; i--) {//逆序输出
printf("(%d %d %d)\n", shortestPath[i].x, shortestPath[i].y, 
shortestPath[i].direction);
}
}
void printPathStack(Stack* stack) {
for (int i = 0; i <= stack->top; i++) {
Position position = stack->data[i];
printf("(%d %d %d)\n", position.x, position.y, position.direction);
}
printf("\n");
}
//深度优先搜索,找出所有可能的通路
void dfsAll(int x, int y, Stack* stack) {
if (x == exitX && y == exitY) {
visited[x][y] = 1;
printPathStack(stack);//输出路径栈中的路径
visited[x][y] = 0;//回溯,将当前位置标记为未访问
return;
}
visited[x][y] = 1;//标记当前位置已访问
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (isValid(nx, ny) && maze[nx][ny] == 0 && visited[nx][ny] == 0) {
//如果下一个位置是通路且未被访问过,则递归搜索
push(stack, (Position) { x, y, i });//将当前位置入栈
dfsAll(nx, ny, stack);
pop(stack);//回溯,将当前位置出栈
}
}
visited[x][y] = 0;//回溯,标记当前位置未被访问
}
int main() {
// 输入迷宫的行数和列数
printf("请输入迷宫的行数和列数:");
scanf("%d %d", &m, &n);
// 输入迷宫数据
printf("请输入迷宫的数据:\n");
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
scanf("%1d", &maze[i][j]);
}
}
// 输入出口的坐标
printf("请输入出口的坐标:");
scanf("%d %d", &exitX, &exitY);
// 找出一条通路
printf("一条通路:\n");
memset(visited, 0, sizeof(visited));
if (!dfs(1, 1)) {
printf("无解\n");
}
printf("\n");
// 找出迷宫中所有可能的通路
printf("所有通路:\n");
Stack pathStack;
initStack(&pathStack);
memset(visited, 0, sizeof(visited));
dfsAll(1, 1, &pathStack);
printf("\n");
// 找出最短通路
printf("最短通路:\n");
bfs(1, 1);
return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西唯兵欧泡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值