想了很久, 终于做出来了, 不过数据结构的设计基本都是参照数据结构基础书上来的,如如何表示不同方向?怎么根据不同方向计算下一个位置的坐标等,数据结构设计的好做起来就相对会更方便。
大致流程:
1. 设计表示数据的结构。如迷宫可以用一个二维数组表示, 坐标也可以用二维数组表示, 移动的方向也可以用一个结构体表示,不同方向存在一个一维数组中, 这样设计的好处是方便计算下一个位置的坐标,以及遍历各个方向。设计一个二维数组来标记走过的足迹。
2. 使用栈来记录走过得坐标。 首先将起点入栈,比较是否是迷宫出口, 不是的话设置栈顶元素为当前位置, 然后依次遍历各个方向, 根据方向计算下一个位置的坐标, 如果合法就入栈,记录足迹,重新设置当前位置。如果不合法就跳到下一个方向, 如果所有方向都不行,就出栈, 重新设置当前位置。
3. 可以用栈为空时表示找不到走出迷宫的路径。
源码如下:
//Stack.h
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
typedef struct Element {
short int row;
short int col;
short int dir;
} Element;
typedef struct Stack {
Element * pelem;
int top;
int capacity;
}Stack;
Stack * initStack(void);
int isEmpty(const Stack * st);
int isFull(const Stack * st);
int addSpace(Stack * st);
int PUSH(Stack * st, Element e);
int POP(Stack * st, Element * e);
int destoryStack(Stack * st);
int getTop(Stack * st, Element *e);
//Stack.c
#include "Stack.h"
#define CAP 100
Stack * initStack(void)
{
Stack * pst;
pst = (Stack *)malloc(sizeof(Stack));
if(NULL == pst)
{
return NULL;
}
pst->top = -1;
pst->capacity = CAP;
pst->pelem = (Element *)malloc(CAP * sizeof(Element));
if(NULL == pst->pelem)
{
fprintf(stderr, "initStack failed.\n");
return NULL;
}
return pst;
}
int isEmpty(const Stack * st)
{
if (st->top == -1)
return 1;
return 0;
}
int isFull(const Stack * st)
{
if(st->top == st->capacity -1)
return 1;
return 0;
}
int addSpace(Stack * st)
{
if(NULL == st)
{
printf("addSpace error.\n");
return 0;
}
st->pelem = (Element *)realloc(st->pelem, 2 * st->capacity * sizeof(Element));
if(NULL == st->pelem)
{
return 0;
}
st->capacity = 2 * st->capacity;
return 1;
}
int PUSH(Stack * st, Element e)
{
if(++st->top == st->capacity)
{
addSpace(st);
}
st->pelem[st->top] = e;
return 1;
}
int POP(Stack * st, Element * e)
{
if(st->top == -1)
return 0;
memcpy(e, &st->pelem[st->top--], sizeof(Element));
return 1;
}
int destoryStack(Stack * st)
{
if(NULL == st)
return 1;
free(st->pelem);
free(st);
return 1;
}
int getTop(Stack * st, Element *e)
{
if(NULL == st || NULL == e)
{
printf("getTop error\n");
return 0;
}
*e = st->pelem[st->top];
return 1;
}
//main.c
#include "Stack.h"
#define DIR 8
#define EXIT_ROW 11
#define EXIT_COL 14
typedef struct {
short int vert;
short int horiz;
}Offsets; //表示移动方向数据结构
Offsets move[DIR] = {{-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1}};//共8个方向
void showpath(Stack * st);// 输出走出迷宫的路径
int maze[12][15] = {
{0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1},
{0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1},
{1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0},
{1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1},
{0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1},
{0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1},
{0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1},
{1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0},
{0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}
};//迷宫, 0 表示可以通过, 1表示不可以通过
int main()
{
Stack *pst;
int mark[12][15]; //1表示走过的位置
int i, j;
Element current; //当前位置
Element next; //下一个位置
int success = 0; //成功标识
pst = initStack();
if(NULL == pst)
{
printf("initStack failed.\n");
exit(1);
}
/*初始化标记为0*/
for(i = 0; i < 12; i++)
for(j = 0; j < 15; j++)
mark[i][j] = 0;
//起点入栈,并记录足迹
current.row = 0;
current.col = 0;
current.dir = 0;
PUSH(pst, current);
mark[current.row][current.col] = 1;
while(!isEmpty(pst)) //栈不空
{
int dirc;
if(current.row == EXIT_ROW && current.col == EXIT_COL) //当前位置就是出口
{
printf("Congraturation! you find the way!\n");
success = 1;
showpath(pst);
break;
}
for(dirc = 0; dirc < DIR; dirc++) //遍历各个方向
{
//根据当前的方向计算下一个坐标
current.dir = dirc;
next.row = current.row + move[current.dir].vert;
next.col = current.col + move[current.dir].horiz;
//如果下一个坐标不合法就跳到下一个方向
if(next.row < 0 || next.col < 0 || mark[next.row][next.col] == 1 || next.row > 11 || next.col > 14 ||
maze[next.row][next.col] == 1)
{
if(dirc == DIR -1) //如果所有方向的下一个位置都不合法,就退栈
{
POP(pst, ¤t);//如果起点位置被退栈说明迷宫无解
printf("pop: row = %d, col = %d\n", current.row, current.col);
getTop(pst, ¤t); //重新设置当前位置
break;
}
continue;
}
if(maze[next.row][next.col] == 0)//下一个位置合法,入栈,记录足迹,重新设置当前位置
{
current = next;
PUSH(pst, current);
printf("push: row = %d, col = %d\n", current.row, current.col);
mark[current.row][current.col] = 1;
break;
}
}
}
if(!success)
{
printf("There is no way to go, Bye.\n");
}
return 0;
}
void showpath(Stack * st)
{
Element path[st->top + 1];
int i = 0;
int count = 0;
while(!isEmpty(st))
{
POP(st, &path[i++]);
}
while(i--)
{
printf("(%d, %d) -> ", path[i].row, path[i].col);
if(count++ % 5 == 4)
printf("\n");
}
printf("success.\n");
}
如果想找出所有路径可以怎么做呢?