数据结构与算法学习之路:迷宫问题

迷宫问题在游戏里非常常见,例如仙剑系列就有各种虐人的迷宫…………刚好有个老师布置了迷宫问题给舍友,出于兴趣我就自己查阅一些知识把他简单的实现了。废话不多说,下面进入正文:


一、阅读需要的预备知识:

栈以栈的操作(入栈、出栈)、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;
}


  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
/* ****迷宫算法求解************* */ /**计目标:教学演示**************/ #include<stdio.h> #define rows 10 #define cols 10 typedef struct {int row; int col; }PosType;/* //坐标点结构 */ typedef struct {int ord;/*//通道块在路径上的“序号” */ PosType seat;/*//通道块在迷宫的“坐标位置”*/ int di;/*//从此通道快走向下一通道块的“方向” */ }SElemType;/*//栈的元素类型 */ typedef struct {SElemType *base; SElemType *top; int stacksize; }SqStack;/*//堆栈结构 */ void InitStack(SqStack &s)/*//初始化堆栈 */ { s.base=(SElemType *)malloc(100*sizeof(SElemType)); if(!s.base) return NULL; s.top=s.base; s.stacksize=100; } int StackEmpty(SqStack s)/* //栈空判别*/ {return(s.top==s.base); } void Pop(SqStack &s ,SelemType &e)/*//弹栈 */ {e=*--s.top); } void Push(SqStack &s,SElemType e)/*//将元素压入堆栈*/ { *s.top++=e; } /*static int maze[rows][cols]= {{0,0,0,0,0,0,0,0,0,0}, {0,1,1,0,1,1,1,0,1,0}, {0,1,1,0,1,0,1,0,1,0}, {0,1,1,0,1,0,0,1,1,0}, {0,1,1,0,0,1,1,1,1,0}, {0,1,1,1,0,1,1,1,1,0}, {0,1,0,1,1,1,0,1,1,0}, {0,1,0,0,0,1,0,0,1,0}, {0,0,1,1,1,1,1,1,1,0}, {0,0,0,0,0,0,0,0,0,0}, }; */ /* //初始迷宫数据(1-通,0-不通)*/ static int maze[rows][cols]= {{0,0,0,0,0,0,0,0,0,0}, {0,1,1,0,1,1,1,0,1,0}, {0,1,1,0,1,0,1,1,1,0}, {0,1,1,1,0,0,0,0,1,0}, {0,1,0,0,0,1,1,1,1,0}, {0,1,0,1,0,1,0,0,0,0}, {0,1,0,1,1,1,0,1,1,0}, {0,1,0,1,0,0,0,0,1,0}, {0,0,1,1,1,1,1,1,1,0}, {0,0,0,0,0,0,0,0,0,0}, }; /* //初始迷宫数据(1-通,0-不通)*/ static int foot[10][10]={0};/*//标记某点是否走过(1-走过,0-未走过)*/ void printpath(SqStack &s)/*//打印迷宫通路*/ {int i,j; SElemType e; while(!StackEmpty(s)) { Pop(s,e); foot[e.seat.row][e.seat.col]=1; } for(i=0;i<10;i++) {printf("\n"); for(j=0;j<10;j++) if(foot[i][j]) printf(" # "); else printf(" . "); } } int Pass(PosType pos)/*//判断当前的通道块是否可通*/ { return(maze[pos.row][pos.col]); }; void FootPrint(PosType pos) { maze[pos.row][pos.col]=0; } PosType NextPos(PosType curpos,int dir)/*//取当前通道块的下一个通道块*/ { switch(dir) {case 1: curpos.row++; break; case 2: curpos.col++; break; case 3: curpos.row--; break; case 4: curpos.col--; } return curpos;/*//将下一个通道块变为当前通道块*/ } int END(PosType curpos,PosType end) {return(curpos.row==end.row && curpos.col==end.col); } void MazePath(SqStack &s,PosType start,PosType end) {PosType curpos,nextpos; int curstep; SElemType e; SqStack *s; s=InitStack(); curpos=start; curstep=1; do{ if(Pass(curpos)) {FootPrint(curpos); e.ord=curstep;e.seat=curpos;e.di=1; Push(s,e); if(END(curpos,end)) return s; curpos=NextPos(curpos,1); curstep++; }/* end of if */ else { if(!StackEmpty(s)) { e=Pop(s); while(e.di==4 && !StackEmpty(s)) {FootPrint(e.seat);/* The same fuction as MarkPrint ? */ e=Pop(s); }/* end of while */ if(e.di<4) {e.di++;Push(s,e); curpos=NextPos(e.seat,e.di); } /* end of if */ } /* end of if */ } /* end of else */ }while(!StackEmpty(s)); curstep=0; return NULL; } void main() {SqStack *s; static PosType start={1,1},end={8,8}; s=MazePath(start,end); if(s) printpath(s); else printf("\n NO find the path!"); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值