迷宫问题在游戏里非常常见,例如仙剑系列就有各种虐人的迷宫…………刚好有个老师布置了迷宫问题给舍友,出于兴趣我就自己查阅一些知识把他简单的实现了。废话不多说,下面进入正文:
一、阅读需要的预备知识:
栈以及栈的操作(入栈、出栈)、C语言基础、BFS(广度优先搜索算法)和DFS(深度优先搜索算法)以及邻接矩阵的概念
二、实现思路:
1、既然要解决迷宫问题,那么我们肯定需要用一种方式把迷宫给存储起来。在这里采用的是邻接矩阵maze[][]。在设计邻接矩阵的时候,为了操作方便,不使用maze[0][]和maze[][0]。但是这些空间白白浪费了很不值得呀,这时不妨考虑一下迷宫本身的特点,迷宫除了一些障碍肯定还有迷宫的“墙壁”,于是我们就可以把这些空间设置成墙壁了。
2、迷宫中的点首先会有一个坐标,所以我们需要x和y来存储坐标。此外,迷宫问题中,我们的点有三种“状态”,也就是:起点,终点,障碍(所有可行方向都是墙壁,俗称——死胡同)、通路、墙壁。所以要通过宏定义来设置一些常量
3、走迷宫当然需要确定哪些方向能走了,所以用一个dir[]数组来存储可以走的方向。
4、最后就是设计一个搜索迷宫的算法了。最短路径用BFS算法就可以实现,所有路径这里我是用深搜,先搜到一条可达的路径,然后通过回溯找其他的路径。(关于BFS、DFS算法网上有个图非常好,可以去搜搜)
三、代码:
#include <stdio.h>
#include <stdlib.h>
#define WALL 1
#define ROAD 0
#define END -1
#define TRUE 1
#define FALSE 0
#define VISITED 1
#define UNVISITED 0
#define BARRIER -1
#define MAXSIZE 11 //迷宫每行或每列中点的的最大数量
#define STACK_SIZE 24
typedef int Status;
//迷宫中的点
typedef struct Point{
int x;
int y;
Status status;
Status visited;
}Point;
typedef struct Stack{
Point point[STACK_SIZE];
int top;
}Stack, *StackPtr;
void Stack_Init(StackPtr s);
void Stack_Enter(StackPtr s, Point point);
void Stack_Pop(StackPtr s);
//搜索所有路径,第一条路径为最短。
//多入口多出口加个起点终点数组,将起点通过循环作为栈底,遍历到达不同终点的路径即可
void Maze_Search(StackPtr s, Point maze[MAXSIZE][MAXSIZE],Point dir[3]);
void Maze_AutoCreate();
int main(){
StackPtr stack;
Point dir[3];
Point up, down, right;
Point maze[MAXSIZE][MAXSIZE];
int i, j;
//初始化迷宫
for (i = 0; i < MAXSIZE; i++){
for (j = 0; j < MAXSIZE; j++)
maze[i][j].status = ROAD;
}
for (i = 0; i < MAXSIZE; i++)
for (j = 0; j < MAXSIZE; j++){
maze[i][j].x = i;
maze[i][j].y = j;
maze[i][j].visited = UNVISITED;
}
for (i = 0; i < MAXSIZE; i++){
maze[0][i].status = WALL;
maze[10][i].status = WALL;
maze[0][i].visited = VISITED;
maze[10][i].visited = VISITED;
}
for (i = 0; i < MAXSIZE; i++){
maze[i][0].status = WALL;
maze[i][10].status = WALL;
maze[i][0].visited = VISITED;
maze[i][10].visited = VISITED;
}
maze[1][2].status = WALL;
maze[1][3].status = WALL;
maze[1][5].status = WALL;
maze[1][6].status = WALL;
maze[1][9].status = WALL;
maze[2][3].status = WALL;
maze[2][4].status = WALL;
maze[2][7].status = WALL;
maze[2][8].status = WALL;
maze[2][9].status = WALL;
maze[3][3].status = WALL;
maze[3][5].status = WALL;
maze[3][6].status = WALL;
maze[3][8].status = WALL;
maze[4][2].status = WALL;
maze[4][4].status = WALL;
maze[4][7].status = WALL;
maze[4][9].status = WALL;
maze[5][6].status = WALL;
maze[5][3].status = WALL;
maze[5][5].status = WALL;
maze[5][8].status = WALL;
maze[6][1].status = WALL;
maze[6][4].status = WALL;
maze[6][6].status = WALL;
maze[6][7].status = WALL;
maze[6][9].status = WALL;
maze[7][4].status = WALL;
maze[7][8].status = WALL;
maze[7][9].status = WALL;
maze[8][2].status = WALL;
maze[8][6].status = WALL;
maze[9][1].status = WALL;
maze[9][2].status = WALL;
maze[1][1].visited = VISITED;
maze[1][2].visited = VISITED;
maze[1][3].visited = VISITED;
maze[1][5].visited = VISITED;
maze[1][6].visited = VISITED;
maze[1][9].visited = VISITED;
maze[2][3].visited = VISITED;
maze[2][4].visited = VISITED;
maze[2][7].visited = VISITED;
maze[2][8].visited = VISITED;
maze[2][9].visited = VISITED;
maze[3][3].visited = VISITED;
maze[3][5].visited = VISITED;
maze[3][6].visited = VISITED;
maze[3][8].visited = VISITED;
maze[4][2].visited = VISITED;
maze[4][4].visited = VISITED;
maze[4][7].visited = VISITED;
maze[4][9].visited = VISITED;
maze[5][6].visited = VISITED;
maze[5][3].visited = VISITED;
maze[5][5].visited = VISITED;
maze[5][8].visited = VISITED;
maze[6][1].visited = VISITED;
maze[6][4].visited = VISITED;
maze[6][6].visited = VISITED;
maze[6][7].visited = VISITED;
maze[6][9].visited = VISITED;
maze[7][4].visited = VISITED;
maze[7][8].visited = VISITED;
maze[7][9].visited = VISITED;
maze[8][2].visited = VISITED;
maze[8][6].visited = VISITED;
maze[9][1].visited = VISITED;
maze[9][2].visited = VISITED;
maze[9][9].status = END;
down.x = 1;
down.y = 0;
down.status = ROAD;
right.x = 0;
right.y = 1;
right.status = ROAD;
up.x = -1;
up.y = 0;
up.status = ROAD;
dir[0] = down;
dir[1] = right;
dir[2] = up;
//输出迷宫
for (i = 0; i < MAXSIZE; i++){
for (j = 0; j < MAXSIZE; j++){
if (maze[i][j].status == WALL)
printf("▇");
else
printf(" ");
}
printf("\n");
}
printf("\n");
//初始化保存路径的栈
stack = (StackPtr)malloc(sizeof(Stack));
Stack_Init(stack);
Maze_Search(stack, maze, dir);
return 0;
}
void Stack_Init(StackPtr s){
Point temp;
if (s == NULL)
return;
temp.x = 1;
temp.y = 1;
temp.status = ROAD;
temp.visited = VISITED;
s->top = 0;
s->point[s->top] = temp;
return;
}
void Stack_Push(StackPtr s, Point point){
if (s->top == (STACK_SIZE - 1)){
printf("栈已满!");
return;
}
s->top += 1;
s->point[s->top] = point;
}
void Stack_Pop(StackPtr s){
Point temp;
if (s->top == -1){
printf("栈为空!");
return;
}
temp.x = 0;
temp.y = 0;
temp.status = ROAD;
s->point[s->top] = temp;
s->top -= 1;
}
void Maze_Search(StackPtr s, Point maze[MAXSIZE][MAXSIZE],Point dir[3]){
int i,j;
if (s->point[s->top].status == END){
for (i = 0; i < MAXSIZE; i++){
for (j = 0; j < MAXSIZE; j++){
if (maze[i][j].status == WALL)
printf("▇");
else if ((maze[i][j].status == ROAD || maze[i][j].status == END) && maze[i][j].visited == VISITED && maze[i][j].visited != BARRIER)
printf("※");
else
printf(" ");
}
printf("\n");
}
maze[9][9].visited = UNVISITED;
Stack_Pop(s);
printf("\n\n");
return;
}
for (i = 0; i < 3; i++){
if (maze[s->point[s->top].x + dir[i].x][s->point[s->top].y + dir[i].y].status != WALL
&& maze[s->point[s->top].x + dir[i].x][s->point[s->top].y + dir[i].y].visited != VISITED){
maze[s->point[s->top].x + dir[i].x][s->point[s->top].y + dir[i].y].visited = VISITED;
Stack_Push(s, maze[s->point[s->top].x + dir[i].x][s->point[s->top].y + dir[i].y]);
Maze_Search(s, maze, dir);
}
}
for (i = 0; i < 3; i++){
if (maze[s->point[s->top].x + dir[i].x][s->point[s->top].y + dir[i].y].status != WALL
&& maze[s->point[s->top].x + dir[i].x][s->point[s->top].y + dir[i].y].visited != VISITED){
maze[s->point[s->top].x][s->point[s->top].y].visited = UNVISITED;
Stack_Pop(s);
return;
}
}
if (maze[s->point[s->top].x][s->point[s->top].y - 1].status == ROAD && maze[s->point[s->top].x][s->point[s->top].y - 1].visited == UNVISITED)
maze[s->point[s->top].x][s->point[s->top].y].visited = UNVISITED;
maze[s->point[s->top].x][s->point[s->top].y].visited = BARRIER;
Stack_Pop(s);
return;
}