数据结构小项目—移动迷宫游戏

移动迷宫游戏:迷宫只有两个门,一个入口,一个出口。一个骑士骑马从入口走进迷宫,迷宫中设置有很多墙壁,对前进方向造成障碍。先需要你从迷宫中找到一条最短的通路,将行走路线和行走的最短距离告知骑士。

设计思路:

寻找最短路径这样的问题,最直接的方法就是使用迪杰斯特拉算法和弗洛伊德算法。
迷宫是在二维数组中进行存储的,所以如果使用前面两种算法的话,需要首先将二维数组转化为图的存储形式。

二维数组转化成图

如下图所示,此为 3*3 迷宫:


数据结构小项目—移动迷宫游戏_第1张图片
图 1 移动迷宫.png

提示:S 为入口,E 为出口,# 为墙壁,- 为通路。

迪杰斯特拉算法还是弗洛伊德算法,其处理对象都是有向网或者无向网。迷宫中并不涉及到具体的方向,所以需要将存储迷宫的二维数组转化为无向网。

无向网的存储方式也是用二维数组来实现,将迷宫中所有的顶点看作是图中的顶点,对于上图的迷宫来说,共有 9 个顶点,所以转化为无向网时,需要用 9*9 的一个二维数组来表示。

在转化时,从迷宫的左上角(上图的 S 开始),一行一行的进行转化,对于每个顶点来说,只需要判断其右侧和相邻的下方顶点是否为通路,如果是通路,转化为图中的直接体现就是两顶点之间有线连接。

例如,上图中的 S 其右侧和下方的顶点都是 - ,骑士可以通过,那在图中的表现就是 S 同其右侧顶点和下方顶点之间存储通路,如下图所示:

image.png

对于图 1 中的二维数组,其完全转化为图,如下图所示(每个顶点用其二维数组中的坐标来表示,00 表示第 0 行第 0 列):

image.png

图 1 中的二维数组转化为图的存储表示如下图所示:

数据结构小项目—移动迷宫游戏_第2张图片
image.png

提示:1 表示有通路,0 表示没有通路,# 由于表示墙壁,同其它任何顶点之间都没有通路。


迪杰斯特拉算法实现迷宫

#include 

typedef enum{
    false,true
} bool;
typedef struct {
    char vexs[250];                 //存储图中顶点数据
    int arcs[250][250];            //二维数组,记录顶点之间的关系
    int vexnum;                      //顶点数
    int arcnum;                      //记录图的弧(边)数
}MGraph;

typedef int PathMatrix[250];        //用于存储最短路径中经过的顶点的下标
typedef int ShortPathTable[250];    //用于存储各个最短路径的权值和

//迪杰斯特拉算法,v0表示有向网中起始点所在数组中的下标
void ShortestPath_Dijkstra(MGraph G,int v0,PathMatrix *p,ShortPathTable *D){
    int final[250];//用于存储各顶点是否已经确定最短路径的数组
    int v, i, w;
    //对各数组进行初始化
    for (v=0; v=0 && i=0 && j
数据结构小项目—移动迷宫游戏_第3张图片
image.png

10.4 广度优先搜索实现迷宫

广度优先搜索也可以查找最短路径,该算法的实现可以直接在二维数组中完成,没有必要转化为图的形式。

数据结构小项目—移动迷宫游戏_第4张图片
image.png

例如拿上图中的迷宫举例,骑士一开始只能选择向右走,当走到坐标为 (2,2) 的位置,骑士有两个选择:向上走或者向下走。

对于广度优先搜索来说,其实现使用的数据存储结构为队列,在搜索的过程中,将每种可选情况都入队,然后一轮一轮的对队列中的可选情况进行尝试,知道尝试出想要的结果为止。

对于此时的骑士来说,结合对广度优先算法的理解,就相当于骑士会分身术,一分为二,一个往上,一个往下,每个人每次只能走一步(你走一步然后我走一步)。

例如假设骑士走下,分身去上,当骑士走到坐标为(3,4)的位置时,又需要选择,要么往右,要么往下,此时骑士又分身,各走各的。但是无论怎么分,所有的骑士都是每次只走一步。

在这种情况下,当只要有一个骑士找到出口时,他所走的路径就绝对是最短路径。

对于广度优先搜索来说,使用的是队列的数据结构,等同于在遍历一棵二叉树时,一层一层的遍历(从上往下,从左往右),可以看做是,对于每种情况,轮流去试探,每次只走一步。

在实际编程实现时,使用广度优先搜索查找最短路径时,只能求得最短路径的长度,如果想要获取最短路径的具体路线,还需要结合其他算法。

在本节,给大家的一个解决思路是:在存储迷宫时,对于每个顶点都分配一个整形变量,在进行广度优先搜索时,骑士和其分身每走一步,该顶点所携带的整形变量的值都是骑士之前所处位置的整形变量+1。

例如,对于下图的迷宫来说,骑士在最终找到出口时的整形变量为:

数据结构小项目—移动迷宫游戏_第5张图片
image.png

提示:从入口开始,初始值假设为 0 ,其右侧通路和下方通路的整形变量的值是0+1=1,最终其出口自身所携带的整形变量值就是最短路径的长度。

通过对“骑士们”所走路线中整形变量的设置,此时我们可以结合回溯法,从入口开始寻找骑士所可能走的所有的最短路径(此时找到的可能不只有一条)。

在使用回溯法时,从入口出发,每次同当前顶点周围查找比自身整形变量值大 1 的顶点,就是骑士所走的路线。如果找不到,回退再找,直到将所有的情况都试探完。

广度优先搜索+回溯法解决迷宫问题代码:

#include 
typedef enum{
    false,true
} bool;

typedef struct {
    int x;
    int y;
    char mess;
    int value;
}check;

bool canUsed(int x,int y,char data,int n,int m){
    if (x>=0 && x=0 && y=0 && x=0 && y
数据结构小项目—移动迷宫游戏_第6张图片
image.png

你可能感兴趣的:(数据结构小项目—移动迷宫游戏)