栈---求解迷宫问题

问题:

在迷宫中寻找一条路径

算法分析:

  1. 将迷宫数值化,使用二维数组来表示迷宫,墙单元用0,通道单元用1;
  2. 如果能够通过继续前进,如果不能通过则退回到上一个单元,因此用栈来存储通过的路径;
  3. 用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;
}

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XIE_QAID

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值