1问题
通过给定的入口和出口,求出迷宫的通路。
2算法
【1】若当前位置“可通”,则纳入“当前路径”,并继续朝“下一位置”探索,即切换“下一位置”为“当前位置”,如此重复直至到达出口;
【2】若当前位置“不可通”,则应顺着“来向”退回到“前一通道块”,然后朝着除“来向”之外的其他方向继续搜索;
【3】若该通道块的四周4个方块均“不可通”,则应从“当前路径”上删除该通道块。
注:
“下一个位置”指的是“当前位置”四周4个方向(东、南、西、北)上相邻的方块。
3实现
#include <stdio.h>
#include <stdlib.h>
#define OK 0
#define ERROR -1
#define TRUE 1
#define FALSE 0
/*坐标*/
typedef struct
{
int n;/*行*/
int m;/*列*/
}pos_t;
/*方向顺时针表示: 东南西北*/
typedef enum
{
EAST = 0,
SOUTH,
WEST,
NORTH,
DIR_MAX,
}dir_t;
/*栈元素*/
typedef struct
{
int ord; /*序号*/
pos_t seat; /*坐标位置*/
dir_t dir; /*方向*/
}stack_elem_t;
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
/*顺序栈*/
typedef struct
{
stack_elem_t *base;/*栈底*/
stack_elem_t *top; /*栈顶指针*/
int stack_size; /*栈的初始大小*/
}seq_stack_t;
/*迷宫图*/
#define MAX_LEN 10
typedef struct
{
char maze_map[MAX_LEN][MAX_LEN];
}maze_map_t;
/*初始化栈元素*/
void init_stack_elem(stack_elem_t *elem, int ord, pos_t *pos, dir_t dir)
{
elem->ord = ord;
elem->seat = *pos;
elem->dir = dir;
}
/*栈的初始化*/
int seq_stack_init(seq_stack_t *stack)
{
stack->base = stack->top = (stack_elem_t *)malloc(STACK_INIT_SIZE * sizeof(stack_elem_t));
if (stack->base == NULL)
{
return ERROR;
}
stack->stack_size = STACK_INIT_SIZE;
return OK;
}
/*进栈操作*/
int push(seq_stack_t *stack, stack_elem_t *elem)
{
/*栈慢则追加空间*/
if (stack->top - stack->base >= stack->stack_size)
{
stack->base = (stack_elem_t *)realloc(stack->base, (STACK_INIT_SIZE + STACKINCREMENT)*sizeof(stack_elem_t));
if (stack->base == NULL)
{
return ERROR;
}
stack->top = stack->base + stack->stack_size;
stack->stack_size = STACK_INIT_SIZE + STACKINCREMENT;
}
/*进栈*/
*stack->top++ = *elem;
return OK;
}
/*出栈操作*/
int pop(seq_stack_t *stack, stack_elem_t *elem)
{
/*栈空则出错*/
if (stack->base == stack->top)
{
return ERROR;
}
*elem = *(--stack->top);
return OK;
}
/*栈空判断*/
int stack_empty(seq_stack_t *stack)
{
return (stack->base == stack->top);
}
/*栈的销毁*/
void seq_stack_destroy(seq_stack_t *stack)
{
if (stack->base)
{
free(stack->base);
}
stack->stack_size = 0;
return ;
}
/*初始化迷宫*/
void init_maze_wall(maze_map_t *maze)
{
int i,j;
/*将迷宫外墙设置为#*/
for (i = 0; i < MAX_LEN; i++)
{
/*迷宫上下围墙*/
maze->maze_map[0][i] = '#';
maze->maze_map[MAX_LEN-1][i] = '#';
/*迷宫左右围墙*/
maze->maze_map[i][0] = '#';
maze->maze_map[i][MAX_LEN-1] = '#';
}
/*迷宫内部所有通道设置为可通,用'0'表示*/
for (i = 1; i < MAX_LEN-1; i++)
{
for (j = 1; j < MAX_LEN-1;j++)
{
maze->maze_map[i][j] = '0';
}
}
/*在迷宫内设置不可通的通道,用'#表示*/
maze->maze_map[1][3] = maze->maze_map[1][7] = '#';
maze->maze_map[2][3] = maze->maze_map[2][7] = '#';
maze->maze_map[3][5] = maze->maze_map[3][6] = '#';
maze->maze_map[4][2] = maze->maze_map[4][3] = maze->maze_map[4][4] = '#';
maze->maze_map[5][4] = '#';
maze->maze_map[6][2] = maze->maze_map[6][6] = '#';
maze->maze_map[7][2] = maze->maze_map[7][3] = maze->maze_map[7][4] = maze->maze_map[7][6] = maze->maze_map[7][7]= '#';
maze->maze_map[8][1] = '#';
return ;
}
/*打印迷宫图*/
void maze_print(maze_map_t *map)
{
int i,j;
for (i = 0; i < MAX_LEN; i++)
{
for (j = 0; j < MAX_LEN; j++)
{
printf("%2c ", map->maze_map[i][j]);
}
printf("\n");
}
}
/*位置是否可通*/
int pos_pass(maze_map_t *map, pos_t *pos)
{
return map->maze_map[pos->n][pos->m] == '0';
}
/*下一个位置*/
pos_t pos_next(pos_t *pos, dir_t dir)
{
pos_t tmp = *pos;
switch(dir)
{
case EAST:
tmp.m += 1;
break;
case WEST:
tmp.m -= 1;
break;
case SOUTH:
tmp.n += 1;
break;
case NORTH:
tmp.n -= 1;
break;
}
return tmp;
}
/*留下足迹'1'表示走过,在四周探索时,该位置即为来向,走不通*/
void foot_print(maze_map_t *map, pos_t *pos)
{
map->maze_map[pos->n][pos->m] = '1';
}
/*标记为不可通,表示该路径不可通*/
void make_print(maze_map_t *map, pos_t *pos)
{
map->maze_map[pos->n][pos->m] = '@';
}
/*查找迷宫路径*/
int maze_path_find(maze_map_t *map, pos_t start, pos_t end, seq_stack_t *stack)
{
stack_elem_t elem;
pos_t curpos = start;/*当前路径*/
int curstep = 1; /*探索第一步*/
do
{
/*当前路径可通*/
if (pos_pass(map, &curpos))
{
foot_print(map, &curpos);/*留下足迹'1',由'1'构成的路径便是通路*/
init_stack_elem(&elem, curstep, &curpos, EAST);
push(stack, &elem);/*加入路径*/
if (curpos.n == end.n && curpos.m == end.m)
{
return TRUE;/*到达终点*/
}
curpos = pos_next(&curpos, EAST);/*下一个位置是当前位置的东临*/
curstep++;/*探索下一步*/
}
else
{
if (!stack_empty(stack))
{
pop(stack, &elem);
while (elem.dir == DIR_MAX && !stack_empty(stack))
{
make_print(map, &elem.seat);/*留下不能通过标记*/
pop(stack, &elem); /*退回一步*/
}
/*继续向其他方向探索*/
if (elem.dir < DIR_MAX)
{
elem.dir++;/*向其他三个方向探索,通过pos_pass判断是否可通。来向块已记为'1,自然不可通'*/
push(stack, &elem);
curpos = pos_next(&elem.seat, elem.dir);
}
}
}
}while(!stack_empty(stack));
return FALSE;
}
int main()
{
int ret;
maze_map_t map; /*声明迷宫图*/
seq_stack_t stack; /*声明栈*/
pos_t start, end;/*声明迷宫入口和出口*/
/*初始化栈*/
seq_stack_init(&stack);
/*初始化迷宫图*/
init_maze_wall(&map);
/*初始化迷宫入口和出口*/
start.n = start.m = 1;
end.n = end.m = 8;
printf("***********迷宫图************\n");
maze_print(&map);
/*查找迷宫通路*/
ret = maze_path_find(&map, start, end, &stack);
if (ret == TRUE)
{
printf("\n*********迷宫图通路**********\n");
maze_print(&map);
printf("\n.由1构成的路径便是迷宫图通路.\n");
}
/*销毁栈*/
seq_stack_destroy(&stack);
return 0;
}
ubuntu $ ./maze
***********迷宫图************
# # # # # # # # # #
# 0 0 # 0 0 0 # 0 #
# 0 0 # 0 0 0 # 0 #
# 0 0 0 0 # # 0 0 #
# 0 # # # 0 0 0 0 #
# 0 0 0 # 0 0 0 0 #
# 0 # 0 0 0 # 0 0 #
# 0 # # # 0 # # 0 #
# # 0 0 0 0 0 0 0 #
# # # # # # # # # #
*********迷宫图通路**********
# # # # # # # # # #
# 1 1 # @ @ @ # 0 #
# 0 1 # @ @ @ # 0 #
# 1 1 @ @ # # 0 0 #
# 1 # # # 0 0 0 0 #
# 1 1 1 # 0 0 0 0 #
# 0 # 1 1 1 # 0 0 #
# 0 # # # 1 # # 0 #
# # 0 0 0 1 1 1 1 #
# # # # # # # # # #
.由1构成的路径便是迷宫图通路.
ubuntu $