IDE:Visual Studio 2019
声明:为了方便书写代码,用到了C++的引用调用特性和iostream作为输入输出,读者可以使用指针调用和scanf_s/print语句实现相同效果
tips:有疑问可以在下面交流,我会尽量回复的
头文件heads.h
#pragma once
#include "stdio.h"
#include "iostream"
#define OK 1
#define TRUE 1
#define FALSE 0
#define ERROR 0
#define OVERFLOW -1
#define STACK_INIT_SIZE 1000
#define STACKINCREMENT 200
typedef short int Status;
using namespace std;
typedef struct Pos {//迷宫中每个点位包含的信息
int x;
int y;
bool pass;//这个坐标是否可以通过
bool mark;//这个坐标是否被“我”走过
}PosType;
typedef struct Mazequestion {//栈元素是个结构体
int ord;//序号
PosType seat;//坐标
int di;//方向
}ElemType;
typedef struct Stack {//基础栈结构
ElemType* base;
ElemType* top;
int stacksize;
}SqStack;
typedef struct Mazement{//迷宫的设置,如果读者愿意支持三维下迷宫的探索
Pos Mazes[10][10];//迷宫大小
int end[2];//出口坐标
int start[2];//入口坐标
}Maze;
头文件functions.h
#include "head.h"
//初始化
Status InitStack(SqStack& S) {
S.base = (ElemType*)malloc(STACK_INIT_SIZE * sizeof(ElemType));
if (!S.base)exit(OVERFLOW);
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return OK;
}
//清空栈
Status Clear(SqStack& S) {
while (S.base != S.top)--S.top;
return OK;
}
//摧毁栈
Status Destory(SqStack& S) {
Clear(S);
S.stacksize = NULL;
S.base = NULL;
free(S.base);
return OK;
}
//判断栈是否为空
Status StackEmpty(SqStack S) {
if (S.top == S.base)return TRUE;
else return FALSE;
}
//返回栈的长度
int StackLength(SqStack S) {
int i = 0;
for (; S.top != S.base; --S.top) {
i++;
}
return i;
}
//返回栈顶元素
Status GetTOP(SqStack S, ElemType& e) {
if (StackEmpty(S))return ERROR;
e = *(S.top--);
return OK;
}
//入栈
Status Push(SqStack& S, ElemType e) {//压入栈顶元素e
if(S.top-S.base>=S.stacksize){
S.base = (ElemType*)realloc(S.base,(S.stacksize + STACKINCREMENT) * sizeof(ElemType));
if (!S.base)return OVERFLOW;
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top++= e;
return OK;
}
//出栈
Status Pop(SqStack& S, ElemType& e) {
if (StackEmpty(S))return ERROR;
e = *--S.top;
return OK;
}
//访问结点函数
Status visit(ElemType e) {
cout <<"第"<< e.ord<<"步:向" << e.di <<"前进一步到达位置:"<<e.seat.x<<" "<<e.seat.y<<endl ;
return OK;
}
//遍历函数
Status StackTraverse(SqStack S, Status(*visit)(ElemType)) {
while (S.base != S.top) {
visit(*S.base++);
}
cout << endl;
return OK;
}
头文件lineEdit.h
//之前测试的行编辑程序,顺利执行,如需此部分需要把头文件heads里的ElemType改为char类型
#include "functions.h"
/*void LineEdit() {
SqStack S;
ElemType ch,c;
InitStack(S);
ch = getchar();
while (ch != EOF) {
while (ch != EOF && ch != '\n') {
switch (ch) {
case '#':Pop(S, c); break;
case '@':Clear(S); break;
default:Push(S, ch); break;
}//switch
ch = getchar();
}//while
StackTraverse(S,visit);
Clear(S);
if (ch != EOF)ch = getchar();
}//while
Destory(S);
}*/
头文件Maze.h
#include "functions.h"
//迷宫初始化
Status InitMaze(Maze& M) {
int width = sizeof(M.Mazes) / sizeof(M.Mazes[0]);
int length = sizeof(M.Mazes[0]) / sizeof(M.Mazes[0][0]);
bool a;
int b, c;
for (int i = 0; i < length; i++) {
for (int j = 0; j < width; j++) {
M.Mazes[i][j].x = j;
M.Mazes[i][j].y = i;
cout << "第" << i << "行第" << j << "列的pass值为" << endl;
cin >> a;
/*if (i > 0 && (i == j || i == j - 1))a = 1;
else a = 0;*/
M.Mazes[i][j].pass =a;
M.Mazes[i][j].mark = 0;
}
}
cout << "输入入口坐标" << endl;
cin >> c >> b;
if (M.Mazes[c][b].pass == 0)return ERROR;
M.start[0] = c;
M.start[1] = b;
M.Mazes[c][b].mark = 1;
cout << "输入出口坐标" << endl;
cin >> c >> b;
if (M.Mazes[c][b].pass == 0)return ERROR;
M.end[0] = c;
M.end[1] = b;
return OK;
}
//访问迷宫
Status VisitMaze(Maze& M) {
int width = sizeof(M.Mazes) / sizeof(M.Mazes[0]);
int length = sizeof(M.Mazes[0]) / sizeof(M.Mazes[0][0]);
for (int i = 0; i < length; i++) {
for (int j = 0; j < width; j++) {
cout << M.Mazes[i][j].x << " " << M.Mazes[i][j].y<< " " << M.Mazes[i][j].pass << endl;
}
}
return OK;
}
//判断该点位是否值得通过
Status Cheak(Pos P) {
if (!P.mark && P.pass)return TRUE;
return FALSE;
}
//迷宫操作算法
Status MazePath(Maze& M, Stack& S) {
InitStack(S);
ElemType e,re;
int x, y,n=1;//描述当前所在迷宫位置的坐标值
x= M.start[0];
y= M.start[1];
M.Mazes[y][x].mark = 1;
e.seat.x = M.start[0];
e.seat.y = M.start[1];
e.ord = 0;
e.di = 0;
Push(S, e);
while (1) {
if (e.di > 4) {
e.di = 1;
}
switch (e.di)
{
case 1:y++; break;
case 2:x++; break;
case 3:y--; break;
case 4:x--; break;
}
if (Cheak(M.Mazes[x][y])){//如果当前位置可以走且未被标记
M.Mazes[x][y].mark = 1;
cout << y << " " << x << " " << e.di << endl;
e.ord++;
e.seat.x = x;
e.seat.y = y;
n = 1;
Push(S, e);
if (y == M.end[0] && x == M.end[1]) {
cout << "迷宫已完成" << endl;
return OK;
}//入栈
}else{
switch (e.di)
{
case 1:y--; break;
case 2:x--; break;
case 3:y++; break;
case 4:x++; break;
}
e.di++;
n++;
}//尝试把下一步纳入通道
if (y == M.start[0] && x == M.start[1] && n == 4) break;
//结点退回起点且不能进行下一步时结束循环
if (n > 4) {//如果在一个点位停留超过四轮,说明该点位不值得尝试,退栈
Pop(S, re);
e.ord--;
switch (re.di)
{
case 1:y--; break;
case 2:x--; break;
case 3:y++; break;
case 4:x++; break;
}//退栈同时当前步骤退一位,当前位置会到上一结点位置
n = 1;
}
}
cout << "迷宫探索失败" << endl;
return ERROR;
}
调用文件main.cpp
#include "Maze.h"
int main(void) {
Stack S;
Maze M;
InitMaze(M);
MazePath(M, S);
StackTraverse(S, visit);
}