迷宫问题求解

 

大一上学期的程序设计算法作业,没有利用深度搜索求出所有路径,有点遗憾。  发博客也只是记录一些大学生活的实验而已。 

问题描述:以一个 m*n 的长方阵表示迷宫,0 和 1 分别表示迷宫中的通路和障碍。设计一个程序,对任意设 定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。

 

这里为了调试方便,采用的是内置的7*7大小的bool型二维数组表示迷宫。

 

数据结构:

坐标:

struct coordinate {//坐标
	int x;
	int y;
};

迷宫属性:

struct cell {//迷宫元素
	bool edge;//是否为障碍
	bool visited;//是否已经访问
	int direction;//方向,-1下 -2 右 1上 2左
};

存储属性的栈:

stack<cell>cellstack;

迷宫操作:

迷宫初始化:

void InitMap(cell map[7][7],bool init[7][7]) {
	for (int i = 0; i < 7; i++) 
		for (int j = 0; j < 7; j++) {
			map[i][j].edge = init[i][j];//初始化操作
			map[i][j].visited = false;
		}
}

打印迷宫:

void printMap(cell map[7][7]) {
	cout << "迷宫形式为:" << endl;
	for (int i = 0; i < 7; i++) {
		for (int j = 0; j < 7; j++) {
			if (map[i][j].edge == 1)
				cout << "■";
			else
				cout << "□";
		}
		cout << endl;
	}
}

迷宫内的某点是否能走:

bool feasible(cell atom) {
	//判定该点能走
	if (atom.edge) return false;
	if (atom.visited) return false;
	return true;
}

walk函数:

bool walk(cell map[7][7], int x0,int y0,int x1,int y1) {
	//给定地图与起点、终点
	map[x0][y0].visited = 1;//起点访问
	map[x0][y0].direction = 0;//起点访问
	cellstack.push(map[x0][y0]);//起点入栈
	cout << "起点:(" << x0 << "," << y0 <<")"<< endl;
	cout << "终点:(" << x1 << "," << y1 << ")" << endl;
	int x = x0;
	int y = y0;
	while (!cellstack.empty()) {
		//如果栈不空
		if (x + 1<7&&map[x + 1][y].edge == 0&& map[x + 1][y].visited==0) {
			//尝试向下走,不是障碍且未被访问
			x++;
			map[x][y].direction = 1;//标记上
			map[x][y].visited = 1;//该点被访问
			cellstack.push(map[x][y]);
			if (x == x1 && y == y1)//找到通路,返回1
				return 1;
			}
		else if (y + 1 < 7 && map[x][y + 1].edge == 0 && map[x][y + 1].visited == 0) {
			//尝试向右走,不是障碍且未被访问
			y++;
			map[x][y].direction = 2;//标记左
			map[x][y].visited = 1;//该点被访问
			cellstack.push(map[x][y]);
			if (x == x1 && y == y1)
				return 1;
		}
		else if (x - 1 >=0 && map[x-1][y].edge == 0 && map[x-1][y].visited == 0) {
			//尝试向上走,不是障碍且未被访问
			x--;
			map[x][y].direction = -1;//标记下
			map[x][y].visited = 1;//该点被访问
			cellstack.push(map[x][y]);
			if (x == x1 && y == y1)
				return 1;
		}
		else if (y-1>=0 && map[x][y - 1].edge == 0 && map[x][y - 1].visited == 0) {
			//尝试向左走,不是障碍且未被访问
			y--    ;
			map[x][y].direction = -2;//标记右
			map[x][y].visited = 1;//该点被访问
			cellstack.push(map[x][y]);
			if (x == x1 && y == y1)
				return 1;
		}
		else {
			//都不能走
			if (!cellstack.empty()) {
				if (cellstack.top().direction == -1)
					x++;
				if (cellstack.top().direction == -2)
					y++;
				if (cellstack.top().direction == 1)
					x--;
				if (cellstack.top().direction == 2)
					y--;
			}
			cellstack.pop();//出栈,坐标变换
		}
	}
	//找不到通路,返回0
	return 0;
}

打印通路:

void display(int x1, int y1) {
	//打印通路
	//cout << cellstack.size() << endl;
	int num = cellstack.size();
	coordinate *p = new coordinate[num];//创建适合大小的数组
	p[0].x = x1, p[0].y = y1;
	int x = x1, y = y1;
	//初始化终点
	for (int i = 1; i < num; i++) {
		if (cellstack.top().direction == -1) {
			p[i].x = ++x;
			p[i].y = y;
		}
		if (cellstack.top().direction == -2) {
			p[i].x = x;
			p[i].y = ++y;
		}
		if (cellstack.top().direction == 1) {
			p[i].x = --x;
			p[i].y = y;
		}
		if (cellstack.top().direction == 2) {
			p[i].x = x;
			p[i].y = --y;
		}
		cellstack.pop();
	}
	for (int i = num - 1; i >= 0;i--) {
		cout <<"->"<< "(" << p[i].x << "," << p[i].y << ")";
	}
	cout << endl;
}

主函数:

int main()
{
	bool mapinit[7][7] = {
		0,1,0,1,1,0,0,
		0,0,0,0,1,0,1,
		1,1,1,0,0,0,1,
		0,0,1,1,1,0,0,
		1,1,0,0,1,0,0,
		0,1,1,0,0,1,0,
		0,0,0,0,1,0,0
	};
	cell map[7][7];
	InitMap(map, mapinit);
	printMap(map);
	//if (walk(map, 0, 0, 6, 5)) {
	//	cout << "找到了一条通路:" << endl;
	//	display(6, 5);
	//}
	if (walk(map, 0, 0, 3, 0)) {
		cout << "\n结果:\n找到了一条通路:" << endl;
		display(3, 0);
	}
	else
		cout << "\n结果:\n无通路" << endl;
	return 0;
}

成功示例:

失败示例:

 

结语:很早写的,当然现在的代码水平更是菜,哈哈哈,写博客记录一下而已。需要改进的地方很多,没有支持自动输入迷宫,没有利用深搜遍历所有的路径。利用面对对象的方法将迷宫看作一个对象,编写迷宫类,将迷宫的动作作为方法,坐标作为成员变量可能会比较好。

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值