问题:
在迷宫中寻找一条路径
算法分析:
- 将迷宫数值化,使用二维数组来表示迷宫,墙单元用0,通道单元用1;
- 如果能够通过继续前进,如果不能通过则退回到上一个单元,因此用栈来存储通过的路径;
- 用0,1,2,3来分别表示4个方向
代码:
#include "pch.h"
#include <iostream>
#include<stdio.h>
#include <stdlib.h>
#include <malloc.h>
using namespace std;
typedef struct
{
int x;//行值
int y;//列值
} PosType ;
typedef struct
{
int ord;//通道块在路径上的序号
PosType seat;//通道块在迷宫中的坐标位值
int di;//从此通道块走向下一个通道块的方向0-3,东南西北
} DataType;
#define MAXLENGTH 40 //定义迷宫的最大行列数
typedef int MazeType[MAXLENGTH][MAXLENGTH];//定义迷宫MazeType 为int[][]类型
MazeType m;
int x, y;//迷宫的行,列
PosType Begin,End;//迷宫的出口和入口坐标
int curstep = 1; //当前足迹,初值为1
void Print()
/*输出迷宫的解(m数组)*/
{
int i, j;
for (i = 0; i < x; i++)
{
for (j = 0; j < y; j++)
{
printf("%3d", m[i][j]);
}
printf("\n");
}
}
void Init(int k)
/*set the layout of the maze(wall = 0, 通道值为k*/
{
int i, j, x1, y1;
cout << "Please input the rows and cols of the maze:" << endl;
scanf_s("%d,%d", &x, &y);
//定义周边值,列
for (i = 0; i < x; i++)
{
m[i][0] = 0;
m[i][x - 1] = 0;
}
//定义周边值行
for (j = 0; j < y; j++)
{
m[0][j] = 0;
m[y-1][j] = 0;
}
//定义除外墙外,其余都是通道,初值为k
for (i = 1; i < x - 1; i++)
for (j = 1; j < y - 1; j++)
m[i][j] = k;
printf("请输入迷宫内墙单元数目:");
scanf_s("%d", &j);
printf("请依次输入迷宫内墙每个单元的行数,列数:\n");
for (i = 1; i <= j; i++)
{
scanf_s("%d,%d", &x1, &y1);
m[x1][y1] = 0;//修改墙的值为0
}
cout << "迷宫的结构如下:"<<endl;
Print();
printf("请输入入口的行数和列数:\n");
scanf_s("%d,%d", &Begin.x, &Begin.y);
printf("请输入出口的行数和列数:\n");
scanf_s("%d,%d", &End.x, &End.y);
}
int Pass(PosType b)
/*当迷宫m的b的序号为1可通过路径返回1,否则返回0 */
{
if (m[b.x][b.y] == 1)
return 1;
else
return 0;
}
void FootPrint(PosType a)
/*使迷宫a点的值变为足迹*/
{
m[a.x][a.y] = curstep;
}
void NextPos(PosType *c, int di)
/*根据当前位置及移动方向,求得下一位置*/
{
PosType direc[4] = { {0,1},{1,0} ,{0,-1} ,{-1,0} };//移动方向分别为东南北西
(*c).x += direc[di].x;
(*c).y += direc[di].y;
}
void MarkPrint(PosType b)
/*使迷宫m的b点的序号变为-1(不能通过的路径)*/
{
m[b.x][b.y] = -1;
}
typedef struct
{
DataType stack[100];
int top;
}SeqStack;
void InitStack(SeqStack *S)
{
S->top = 0;
}
void PushStack(SeqStack *S, DataType a)
{
S->stack[S->top] = a;
(S->top)++;
}
int StackEmpty(SeqStack S)
{
if (S.top == 0)
return 1;
else
return 0;
}
int PopStack(SeqStack *S, DataType *e)
{
if (S->top == 0)
{
*e = S->stack[S->top - 1];
S->top--;
return 1;
}
else
return 0;
}
int MazePath(PosType start, PosType end)
/*若迷宫存在从入口start到出口end的通道,则求得一条存放在栈中,并返回1*/
{
SeqStack S;
InitStack(&S);
PosType curpos;
DataType e;//当前位置
curpos = start;
do
{
if (Pass(curpos))//如果可以通过
{
FootPrint(curpos);//留下足迹
e.ord = curstep;
e.seat = curpos;
e.di = 0;
/*入栈当前位置及状态*/
PushStack(&S, e);
curstep++;
if (curpos.x == end.x && curpos.x == end.y)
/*到达出口*/
{
return 1;
}
NextPos(&curpos, e.di);
}
else//当前位置不能通过,退回上一个位置
{
if(!StackEmpty(S))//若zhan不为空
{
PopStack(&S, &e);
curstep--;
while (e.di == 3 && !StackEmpty(S))
{
MarkPrint(e.seat);//留下不能通过的标记
PopStack(&S, &e);
curstep--;//足迹减一
}
if (e.di < 3)
{
e.di++;
//换下一个位置搜索
PushStack(&S, e);
curstep++;
curpos = e.seat;
NextPos(&curpos, e.di);
}
}
}
} while (!StackEmpty(S));
return 0;
}
int main()
{
Init(1);
if (MazePath(Begin,End))
{
cout << "有通路,从出口到入口的路径如下:\n";
Print();
}
else
{
cout << "没有一条完整的路径\n";
}
return 0;
}
void Init(int k)
/*set the layout of the maze(wall = 0, 通道值为k*/
{
int i, j, x1, y1;
cout << "Please input the rows and cols of the maze:" << endl;
scanf_s("%d,%d", &x, &y);
//定义周边值,列
for (i = 0; i < x; i++)
{
m[i][0] = 0;
m[i][x - 1] = 0;
}
//定义周边值行
for (j = 0; j < y; j++)
{
m[0][j] = 0;
m[y-1][j] = 0;
}
//定义除外墙外,其余都是通道,初值为k
for (i = 1; i < x - 1; i++)
for (j = 1; j < y - 1; j++)
m[i][j] = k;
printf("请输入迷宫内墙单元数目:");
scanf_s("%d", &j);
printf("请依次输入迷宫内墙每个单元的行数,列数:\n");
for (i = 1; i <= j; i++)
{
scanf_s("%d,%d", &x1, &y1);
m[x1][y1] = 0;//修改墙的值为0
}
cout << "迷宫的结构如下:"<<endl;
Print();
printf("请输入入口的行数和列数:\n");
scanf_s("%d,%d", &Begin.x, &Begin.y);
printf("请输入出口的行数和列数:\n");
scanf_s("%d,%d", &End.x, &End.y);
}
int Pass(PosType b)
/*当迷宫m的b的序号为1可通过路径返回1,否则返回0 */
{
if (m[b.x][b.y] == 1)
return 1;
else
return 0;
}
void FootPrint(PosType a)
/*使迷宫a点的值变为足迹*/
{
m[a.x][a.y] = curstep;
}
void NextPos(PosType *c, int di)
/*根据当前位置及移动方向,求得下一位置*/
{
PosType direc[4] = { {0,1},{1,0} ,{0,-1} ,{-1,0} };//移动方向分别为东南北西
(*c).x += direc[di].x;
(*c).y += direc[di].y;
}
void MarkPrint(PosType b)
/*使迷宫m的b点的序号变为-1(不能通过的路径)*/
{
m[b.x][b.y] = -1;
}
typedef struct
{
DataType stack[100];
int top;
}SeqStack;
void InitStack(SeqStack *S)
{
S->top = 0;
}
void PushStack(SeqStack *S, DataType a)
{
S->stack[S->top] = a;
(S->top)++;
}
int StackEmpty(SeqStack S)
{
if (S.top == 0)
return 1;
else
return 0;
}
int PopStack(SeqStack *S, DataType *e)
{
if (S->top == 0)
{
*e = S->stack[S->top - 1];
S->top--;
return 1;
}
else
return 0;
}
int MazePath(PosType start, PosType end)
/*若迷宫存在从入口start到出口end的通道,则求得一条存放在栈中,并返回1*/
{
SeqStack S;
InitStack(&S);
PosType curpos;
DataType e;//当前位置
curpos = start;
do
{
if (Pass(curpos))//如果可以通过
{
FootPrint(curpos);//留下足迹
e.ord = curstep;
e.seat = curpos;
e.di = 0;
/*入栈当前位置及状态*/
PushStack(&S, e);
curstep++;
if (curpos.x == end.x && curpos.x == end.y)
/*到达出口*/
{
return 1;
}
NextPos(&curpos, e.di);
}
else//当前位置不能通过,退回上一个位置
{
if(!StackEmpty(S))//若zhan不为空
{
PopStack(&S, &e);
curstep--;
while (e.di == 3 && !StackEmpty(S))
{
MarkPrint(e.seat);//留下不能通过的标记
PopStack(&S, &e);
curstep--;//足迹减一
}
if (e.di < 3)
{
e.di++;
//换下一个位置搜索
PushStack(&S, e);
curstep++;
curpos = e.seat;
NextPos(&curpos, e.di);
}
}
}
} while (!StackEmpty(S));
return 0;
}
int main()
{
Init(1);
if (MazePath(Begin,End))
{
cout << "有通路,从出口到入口的路径如下:\n";
Print();
}
else
{
cout << "没有一条完整的路径\n";
}
return 0;
}