迷宫问题-数据结构课程设计-程序员宅基地

技术标签: 算法  C语言-数据结构-课程设计  c语言  数据结构  课程设计  

题目:迷宫问题

【问题描述】

以一个 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;
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/2202_75442297/article/details/131866013

智能推荐

本题要求你计算A−B。不过麻烦的是,A和B都是字符串 —— 即从字符串A中把字符串B所包含的字符全删掉,剩下的字符组成的就是字符串A−B。_,可以帮助她计算字符串a b的结果,即从字符串a中把字符串b所包含的字符全删-程序员宅基地

文章浏览阅读7.4k次,点赞3次,收藏8次。本题要求你计算A−B。不过麻烦的是,A和B都是字符串 —— 即从字符串A中把字符串B所包含的字符全删掉,剩下的字符组成的就是字符串A−B。输入格式:输入在2行中先后给出字符串A和B。两字符串的长度都不超过10​4​​ ,并且保证每个字符串都是由可见的ASCII码和空白字符组成,最后以换行符结束。输出格式:在一行中打印出A−B的结果字符串。输入样例:I love GPLT! It’s a fun game!aeiou输出样例:I lv GPLT! It’s fn gm!解题思路:_,可以帮助她计算字符串a b的结果,即从字符串a中把字符串b所包含的字符全删

移动物联网简介_物联网业务pcf-程序员宅基地

文章浏览阅读3k次。物联网核心网的总体网络组织架构如图所示,主要核心网元及平台包括HLR/HSS(物联卡号码及用户数据存储)、PGW(用于疏通物联卡用户的数据业务)、CG(存储物联卡用户的计费话单)、短信中心(用于物联卡终端短信的转发)、PBOSS/CMIOT(业务受理开通、计费话单采集等)、物联网运营管理平台(OneLink平台,负责全网业务的运营支撑,实现物联网业务运营管理、通信管理、能力管理等)、业务网关(提供M-SMSC与业务平台间短信的转发)。由于5G的更新,通信能力的不断升级换代,2G网络已陆续进行减频。_物联网业务pcf

flowable 配置自定义表单_web工作流管理系统开发之四 自定义表单-程序员宅基地

文章浏览阅读2.2k次。在开发工作流管理系统时,很多人只重视流程引擎,流程模型的建立,而忽略了自定义表单工具。自定义表单工具是实现独立业务模块的可视化编辑工具,业务模块可以通过这种工具编辑生成。如果单纯从流程实现来说,确实自定义表单不是重点,流程实现了,可以挂接上表单就可以了。至于表单业务模块,可以是表单工具生成的,也可以是代码编写的表单,总之能用代码来实现的是最灵活的。但实际上流程的每一个步骤的业务数据都需要靠表单来展...

matlab二进制数字基带传输系统仿真实践——通信原理篇——信噪比与误码率的计算_误码率和信噪比的关系公式-程序员宅基地

文章浏览阅读2.4w次,点赞31次,收藏220次。这里先明确几个点:S:信号平均功率N:噪声平均功率Eb:每bit的信号能量N0:噪声功率谱密度Es:符号信号的能量Rb:传信率,即每秒传输的bit数目W(B):带宽Ts(Tb):采样点的时间间隔k:每个符号包含的bit数目其中Es=Eb*k,Rb=k/Ts..._误码率和信噪比的关系公式

rv1126之硬盘测速_rv1126的内存读写速度-程序员宅基地

文章浏览阅读305次。rv1126 不同接入的硬盘测速_rv1126的内存读写速度

Windows7 搭建靶场xssplatform_xss-platform.rar-程序员宅基地

文章浏览阅读182次。Windows7 phpstudy_pro小皮面板,环境是apache2.4.39+MySQL5.7.26+php7.0.9来搭建xssplatform靶场_xss-platform.rar

随便推点

MATLAB 在一个数组中随机选择n个数_matlab从数组中随机选取几个数-程序员宅基地

文章浏览阅读5.6w次,点赞29次,收藏143次。MATLAB 中在一个数组内随机选择n个数。例如:在 A = [10, 50, 80, 100, 130, 260] 中随机选择5个数。允许重复:n = 5;A = [10, 50, 80, 100, 130, 260];random_num = A(randi(numel(A),1,n));random_num = sort(random_num);不允许重复:n = 5;A = [10, 50, 80, 100, 130, 260];random_num = A(randperm(_matlab从数组中随机选取几个数

赛扬处理器_有问有答:怎么认识电脑处理器的划分?比如英特尔i5i7这些代表什么意思?...-程序员宅基地

文章浏览阅读223次。首选我们要知道现在电脑处理器的品牌有两个一个是Intel另一个是AMD,他们两家现在的命名规则基本都是相近的,Intel家的酷睿系列是主力产品,而AMD方面则以锐龙系列处理器作为主力,下面先来说说Intel家的。Inetl家的桌面酷睿处理器下面细分出酷睿i3/i5/i7/i9这四个等级,这是按处理器的核心数以及线程数划分的,而频率与缓存容量只会影响后面的数字,而现在HEDT也就是高端桌面..._i3 i5 i7 i9处理器都是一样生产的

计算机毕业设计Node.js+Vue智能家电商城(程序+源码+LW+部署)_vuenode家电商城-程序员宅基地

文章浏览阅读77次。该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流项目运行环境配置:项目技术:Express框架 + Node.js+ Vue 等等组成,B/S模式 +Vscode管理+前后端分离等等。环境需要1.运行环境:最好是Nodejs最新版,我们在这个版本上开发的。其他版本理论上也可以。2.开发环境:Vscode或HbuilderX都可以。推荐HbuilderX;3.mysql环境:建议是用5.7版本均可4.硬件环境:windows 7/8/10 1G内存以上;_vuenode家电商城

向量点乘是什么意思-程序员宅基地

文章浏览阅读517次。向量点乘是指在线性代数中对两个向量进行的运算。向量点乘的结果是一个标量(即一个单独的数字)。向量点乘的运算规则如下:如果两个向量的维数相同,则向量点乘的结果是两个向量的对应元素的积的和。例如,如果有两个二维向量 $\mathbf{a}=(a_1,a_2)$ 和 $\mathbf{b}=(b_1,b_2)$,则它们的点乘结果为:$$\mathbf{a} \cdot \mathbf{b} = a..._点乘 啥意思

C++与蓝图互调-程序员宅基地

文章浏览阅读207次。Kismet库蓝图方法cpp使用例:打LOG:Print String蓝图节点的鼠标tips:Target is Kismet System Library#include "Runtime/Engine/Classes/Kismet/KismetSystemLibrary.h" UKismetSystemLibrary::PrintString(this, s) //Ki..._c++调用蓝图