数据结构–栈C语言实现迷宫求解
- 前言
代码主要根据《数据结构》(C语言版)严蔚敏提供的C语言伪代码而写,改变了其中的一些小细节。提供这个代码主要不是学习栈,而是学习穷举迷宫求解算法,另外代码中用到了二级指针,必须要对指针熟悉才行。
运行的时候可以改变00_stack_maze.h中的相关参数来改变迷宫的规模以及迷宫中障碍的数量,开始可以调得小一些。
程序是每隔两秒打印一次,程序中的方向用每个方向英文单词首字母表示。
另外推荐学习视频是B站的数据结构官方视频,最后如果觉得代码可读性很差或者有错误,轻点骂。 - 迷宫求解思想
迷宫求解主要思想是回溯法。


- 代码
00_state.h
*预定义常量和类型
*/
#ifndef __00_STATE_H__
#define __00_STATE_H__
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<windows.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
#endif
#include"00_state.h"
#define SleepTime 2
#define MAZE_SIZE 7
#define OBSTACLE_NUMBER 10
#define STACK_INIT_SIZE 100
#define STACK_INCREMENT 10
typedef enum{
ACCESSIBLE,
START,
END,
OBSTACLE,
MARKED,
NOT_ACCESSIBLE
}maze[MAZE_SIZE][MAZE_SIZE],STATE;
typedef enum{
EAST,
SOUTH,
WEST,
NORTH
}DIR;
typedef struct{
int X;
int Y;
}PosType;
typedef struct {
int order;
PosType seat;
DIR dir;
}maze_block,StackElemType;
typedef struct{
StackElemType *base;
StackElemType *top;
int stacksize;
}stack;
Status stack_init(stack * pstack);
StackElemType get_top(stack stack_,StackElemType *e);
Status pop(stack *pstack,StackElemType *e);
StackElemType get_top(stack stack_,StackElemType *e);
Status stack_empty(stack stack_);
bool maze_path(maze maze_, PosType start, PosType end);
void create_maze(maze maze_);
void print_maze(maze maze_);
Status not_exist_in_stack(stack stack_,PosType pos);
Status pass(maze maze_,PosType pos,stack stack_);
void track_mark(maze maze_,PosType curpos);
STATE get_pos_state(maze maze_, PosType curpos);
PosType get_next_pos(maze maze_,PosType curpos,DIR dir);
void mark_not_accessible(maze maze_,PosType pos);
Status get_pos_dir_from_stack(stack stack_,int i,int j,DIR * dir);
#include"02_stack_maze.h"
stack stack_;
Status stack_init(stack * pstack)
{
pstack->base = (StackElemType*)malloc(STACK_INIT_SIZE*sizeof(StackElemType));
if(!pstack->base)
exit(OVERFLOW);
pstack->top = pstack->base;
pstack->stacksize = STACK_INIT_SIZE;
return OK;
}
StackElemType get_top(stack stack_,StackElemType *e)
{
if(stack_.top == stack_.base)
exit(1);
*e = *(stack_.top-1);
return *e;
}
Status push(stack *pstack,StackElemType e)
{
if(pstack->top-pstack->base>=pstack->stacksize)
{
pstack->base = (StackElemType*)realloc(pstack->base,(pstack->stacksize+STACK_INCREMENT)*sizeof(StackElemType));
if(!pstack->base)
exit(OVERFLOW);
pstack->top=pstack->base+pstack->stacksize;
pstack->stacksize+=STACK_INCREMENT;
}
*(pstack->top) = e;
pstack->top++;
return OK;
}
Status pop(stack *pstack,StackElemType *e)
{
if(pstack->top==pstack->base)
{
printf("栈为空\n");
return ERROR;
}
else
{
pstack->top--;
*e = *(pstack->top);
return OK;
}
}
Status stack_empty(stack stack_)
{
return stack_.base == stack_.top?TRUE:FALSE;
}
void print_stack(stack stack_)
{
StackElemType *base = stack_.base;
StackElemType *top = stack_.top;
while(base<top)
{
printf("%d",base->dir);
base++;
}
}
Status not_exist_in_stack(stack stack_,PosType pos)
{
StackElemType *base = stack_.base;
StackElemType *top = stack_.top;
if(base == top)
return TRUE;
else
{
while(base<top)
{
if(base->seat.X == pos.X&&base->seat.Y == pos.Y)
return FALSE;
else
base++;
}
}
return TRUE;
}
Status pass(maze maze_,PosType pos,stack stack_)
{
if ((maze_[pos.X][pos.Y] ==ACCESSIBLE ||maze_[pos.X][pos.Y] ==START||maze_[pos.X][pos.Y] ==END)&& not_exist_in_stack(stack_,pos))
return TRUE;
}
void track_mark(maze maze_,PosType curpos)
{
maze_[curpos.X][curpos.Y] = MARKED;
}
STATE get_pos_state(maze maze_, PosType curpos)
{
return maze_[curpos.X][curpos.Y];
}
PosType get_next_pos(maze maze_,PosType curpos,DIR dir)
{
PosType pos = curpos;
switch(dir)
{
case EAST:
pos.Y++;
break;
case SOUTH:
pos.X++;
break;
case WEST:
pos.Y--;
break;
case NORTH:
pos.X--;
break;
default:
printf("切换方向错误\n");
exit(1);
}
return pos;
}
void mark_not_accessible(maze maze_,PosType pos)
{
maze_[pos.X][pos.Y] = NOT_ACCESSIBLE;
}
Status get_pos_dir_from_stack(stack stack_,int i,int j,DIR * dir)
{
if(stack_empty(stack_))
{
return FALSE;
}
else
{
StackElemType *base = stack_.base;
StackElemType *top = stack_.top;
while(base<top)
{
if(base->seat.X == i&&base->seat.Y == j)
{
*dir = base->dir;
break;
}
else
base++;
}
}
return FALSE;
}
bool maze_path(maze maze_, PosType start, PosType end)
{
start.X = 1;
start.Y = 1;
PosType curpos = start;
int curstep = 1;
do{
if(pass(maze_,curpos,stack_))
{
if(get_pos_state(maze_,curpos) == END)
{
printf("找到出口,坐标:(%d,%d)\n",curpos.X,curpos.Y);
exit(0);
}
else
track_mark(maze_, curpos);
StackElemType e;
e.order = curstep;
e.seat = curpos;
e.dir = EAST;
push(&stack_,e);
curpos = get_next_pos(maze_,curpos,EAST);
curstep++;
}
else
{
if(!stack_empty(stack_))
{
StackElemType e;
pop(&stack_,&e);
curpos= e.seat;
while(e.dir ==NORTH &&!stack_empty(stack_))
{
mark_not_accessible(maze_,e.seat);
pop(&stack_,&e);
curpos = e.seat;
}
if(e.dir<NORTH )
{
e.dir = (DIR)(e.dir+1);
push(&stack_,e);
curpos = get_next_pos(maze_,curpos,e.dir);
}
}
}
print_maze(maze_);
}while(!stack_empty(stack_));
return FALSE;
}
void create_maze(maze maze_)
{
int i = 0;
int j = 0;
for(;j<MAZE_SIZE;j++)
{
maze_[0][j] = OBSTACLE;
maze_[MAZE_SIZE-1][j] =OBSTACLE;
}
for(;i<MAZE_SIZE;i++)
{
maze_[i][0] = OBSTACLE;
maze_[i][MAZE_SIZE-1] = OBSTACLE;
}
int k = 0;
for(; k < OBSTACLE_NUMBER; k++)
{
i = rand()%(MAZE_SIZE-2)+1;
j = rand()%(MAZE_SIZE-2)+1;
maze_[i][j] = OBSTACLE;
}
maze_[1][1] = START;
maze_[MAZE_SIZE-2][1] = END;
}
void print_maze(maze maze_)
{
int i = 0;
int j = 0;
for( i = 0; i<MAZE_SIZE; i++)
{
for( j = 0; j<MAZE_SIZE;j++)
{
switch(maze_[i][j])
{
case ACCESSIBLE:
printf(" ");
break;
case MARKED:
DIR dir;
get_pos_dir_from_stack(stack_,i,j,&dir);
switch(dir)
{
case EAST:
printf("%c",'E');break;
case SOUTH:
printf("%c",'S');break;
case WEST:
printf("%c",'W');break;
case NORTH:
printf("%c",'N');break;
default:
printf("error2");
break;
}
break;
case START:
printf("?");
break;
case OBSTACLE:
printf("#");
break;
case END:
printf("!");
break;
case NOT_ACCESSIBLE:
printf("$");
break;
default:
printf("error");
break;
}
}
printf("\n");
}
Sleep(2000);
system("cls");
}
int main(void)
{
stack_init(&stack_);
maze maze_ = {ACCESSIBLE};
create_maze(maze_);
PosType start,end;
start.X = 1;
start.Y = 1;
end.X = MAZE_SIZE-2;
end.Y = 1;
print_maze(maze_);
maze_path(maze_,start,end);
print_maze(maze_);
return 0;
}