#pragma once
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
typedef struct _Position {//迷宫坐标
int _x;
int _y;
}Position;
#define MaxSize 128 //预先分配空间,这个数值根据实际需要预估确定
typedef Position ElemType;
typedef struct _SqStack {
ElemType* base; //栈底指针
ElemType* top; //栈顶指针
}SqStack;
bool InitStack(SqStack& S) //构造一个空栈 S
{
S.base = new ElemType[MaxSize];//为顺序栈分配一个最大容量为 Maxsize的空间
if (!S.base) //空间分配失败
return false;
S.top = S.base; //top 初始为 base,空栈
return true;
}
bool PushStack(SqStack& S, ElemType e) // 插入元素 e 为新的栈顶元素
{
if (S.top - S.base == MaxSize) //栈满
return false;
*(S.top++) = e; //元素 e 压入栈顶,然后栈顶指针加 1,等价于*S.top=e;
S.top++;
return true;
}
bool PopStack(SqStack& S, ElemType& e) //删除 S 的栈顶元素,暂存在变量 e中
{
if (S.base == S.top) { //栈空
return false;
}
e = *(--S.top); //栈顶指针减 1,将栈顶元素赋给 e
return true;
}
ElemType* GetTop(SqStack& S) //返回 S 的栈顶元素,栈顶指针不变
{
if (S.top != S.base) { //栈非空
return S.top - 1; //返回栈顶元素的值,栈顶指针不变
}
else {
return NULL;
}
}
int GetSize(SqStack& S) {//返回栈中元素个数
return (S.top - S.base);
}
bool IsEmpty(SqStack& S) {//判断栈是否为空
if (S.top == S.base) {
return true;
}
else {
return false;
}
}
void DestoryStack(SqStack& S) {//销毁栈
if (S.base) {
free(S.base);
S.base = NULL;
S.top = NULL;
}
}
#include <assert.h>
#include <iostream>
#include <string.h>
#include "maze.h"
using namespace std;
#define ROW 6
#define COL 6
typedef struct _Maze {
int map[ROW][COL];
}Maze;
void InitMaze(Maze* m, int map[ROW][COL]) //迷宫的初始化
{
for (int i = 0; i < ROW; ++i)
{
for (int j = 0; j < COL; ++j)
{
m->map[i][j] = map[i][j];
}
}
}
void PrintMaze(Maze* m) //打印迷宫
{
for (int i = 0; i < ROW; ++i)
{
for (int j = 0; j < COL; ++j)
{
printf("%d ", m->map[i][j]);
}
printf("\n");
}
printf("\n");
}
int IsValidEnter(Maze* m, Position cur) //判断是否是有效的入口
{
assert(m);
if ((cur._x == 0 || cur._x == ROW - 1)
|| (cur._y == 0 || cur._y == COL - 1)
&& (m->map[cur._x][cur._y] == 1))
return 1;
else
return 0;
}
int IsNextPass(Maze* m, Position cur, Position next) //判断当前节点的下一个节点能否走通
{
assert(m);
//判断 next 节点是否为 cur 的下一节点
if (((next._x == cur._x) && ((next._y == cur._y + 1) || (next._y ==
cur._y - 1))) //在同一行上并且相邻
|| ((next._y == cur._y) && ((next._x == cur._x + 1) || (next._x ==
cur._x - 1)))) {//或在同一列上并且相邻
//判断下一个节点是否在迷宫里面
if (((next._x >= 0 && next._x < ROW) || (next._y >= 0 && next._y
< COL))
&& (m->map[next._x][next._y] == 1)) {
return 1;
}
}
return 0;
}
int IsValidExit(Maze* m, Position cur, Position enter) //判断当前节点是不是有效的迷宫出口
{
assert(m);
//这里首先得保证该节点不是入口点,其次只要它处在迷宫的边界即可
if ((cur._x != enter._x || cur._y != enter._y)
&& ((cur._x == 0 || cur._x == ROW - 1)
|| (cur._y == 0 || cur._y == COL - 1)))
{
return 1;
}
else
return 0;
}
int PassMaze(Maze* m, Position enter, SqStack* s) //找迷宫通路
{
assert(m && IsValidEnter(m, enter) == 1); //对给的迷宫的入口进行合法性判断
Position cur = enter;
Position next;
PushStack(*s, cur); //首先将迷宫的入口压入栈中
m->map[cur._x][cur._y] = 2; //将入口值改为 2
//PrintMaze(m);
while (!IsEmpty(*s)) {
cur = *GetTop(*s);
//printf("cur: %d %d\n",cur._x, cur._y);
if (IsValidExit(m, cur, enter) == 1) //判断当前位置是否出口
return 1;
//尝试向左一步:看当前节点的左一个节点能不能走通
next = cur;
next._y = cur._y - 1;
if (IsNextPass(m, cur, next) == 1)
{
PushStack(*s, next);
m->map[next._x][next._y] = m->map[cur._x][cur._y] + 1;
//PrintMaze(m);
continue;
}
//尝试向上一步:看当前节点的上一个节点能不能走通
next = cur;
next._x = cur._x - 1;
if (IsNextPass(m, cur, next) == 1) //next 节点能够走通时,将其压入栈中
{
PushStack(*s,next);
m->map[next._x][next._y] = m->map[cur._x][cur._y] + 1; //将next节点的值等于 cur 节点的值加 1
//PrintMaze(m);
continue;
}
//右:看当前节点的向右的一个节点能不能走通
next = cur;
next._y = cur._y + 1;
if (IsNextPass(m, cur, next) == 1)
{
PushStack(*s, next);
m->map[next._x][next._y] = m->map[cur._x][cur._y] + 1;
//PrintMaze(m);
continue;
}
//下:看当前节点的下一个节点能不能走通
next = cur;
next._x = cur._x + 1;
if (IsNextPass(m, cur, next) == 1)
{
PushStack(*s, next);
m->map[next._x][next._y] = m->map[cur._x][cur._y] + 1;
//PrintMaze(m);
continue;
}
//走到这里说明当前节点的四个方向都走不通,进行回溯,看前一个节点未被遍历的方向是否还能走通
Position tmp;
PopStack(*s, tmp);
}
return 0;
}
int main()
{
int map[ROW][COL] = { //用二维数组描绘迷宫:1 代表通路,0 代表墙
0,0,1,0,0,0,
0,0,1,1,1,0,
0,0,1,0,0,0,
0,1,1,1,1,0,
0,0,1,0,1,0,
0,0,0,0,1,0
};
Maze m;
Position enter; //迷宫入口
enter._x = 0;
enter._y = 2;
InitMaze(&m, map);
PrintMaze(&m);
SqStack s; //定义栈,保存已走过的坐标轨迹,便于回溯
InitStack(s); //栈的初始
int ret = PassMaze(&m, enter, &s); //使用栈和回溯法解开迷宫
if (ret) {
printf("恭喜你!终于找到了出口~\n");
}
else {
printf("不是我笨!实在没有出口~\n");
}
PrintMaze(&m);
system("pause");
return 0;
}