简单的迷宫问题

学习了数据结构第二章栈后,实验作业是解决简单的迷宫问题。假设迷宫只有一个入口和出口,默认其大小是10x10。

使用栈来记录位置坐标,首先是坐标类和栈的简单定义

const int N = 10;	//迷宫大小是10x10
const int maxsize = 100;	//数组长度上限,因为默认迷宫大小是10x10,所以路径最多有100个
class Position {
private:
	int x;	//横坐标
	int y;	//纵坐标
public:
	Position();	//默认坐标(0,0)
	Position(int x, int y);	//有参构造函数
	void setpos(int x, int y);	//设置坐标
	int getx();	//获得行坐标
	int gety();	//获得列坐标
	void print();	//以坐标的形式打印
	Position left();	//返回向左移动后的坐标
	Position right();	//向右
	Position up();		//向上
	Position down();	//向下
	bool is_obstacle(bool map[][N]);	//判断该点是否是障碍
	bool overstep(bool map[][N]);	//判断是否越界
};
class Stack {
private:
	int top;	//栈顶“指针”
	Position path_[maxsize];	//存储路径的数组
public:
	Stack();
	bool isempty();	//判空
	void push(Position c);	//入栈
	Position pop();	//出栈
	Position gettop();	//返回栈顶元素
};

其次是各自的实现

#include <iostream>
using std::cout;
using std::endl;
#include "stack.h"
Position::Position() {
	x = 0;
	y = 0;
}
Position::Position(int x, int y) {
	this->x = x;
	this->y = y;
}
void Position::setpos(int x, int y) {
	this->x = x;
	this->y = y;
}
int Position::getx() {
	return x;
}
int Position::gety() {
	return y;
}
void Position::print() {
	cout << "(" << x << "," << y << ")";
}
Position Position::left() {
	return Position(x, y - 1);
}
Position Position::right() {
	return Position(x, y + 1);
}
Position Position::up() {
	return Position(x - 1, y);
}
Position Position::down() {
	return Position(x + 1, y);
}
bool Position::overstep(bool map[][N]) {
	return (x > N || x < 1 || y > N || y < 1);	//若越界则返回true,否则返回false
}
bool Position::is_obstacle(bool map[][N]) {
	return (map[x - 1][y - 1] == 1);	//若迷宫该坐标为1,则表示为障碍,返回true
}
Stack::Stack() {
	top = -1;	//初始化栈为空
	Position path_[maxsize];
}
bool Stack::isempty() {
	return (top == -1);	//栈为空返回true,否则返回false
}
void Stack::push(Position c) {
	if (top == maxsize - 1)	//上溢时扩大数组
		throw "上溢";
	top++;
	path_[top].setpos(c.getx(), c.gety());
}
Position Stack::pop() {
	if (isempty())
		throw "栈为空";
	return path_[top--];
}
Position Stack::gettop() {
	if (isempty())
		throw "栈为空";
	return path_[top];
}

最后是简单的测试代码

测试代码因为嫌麻烦没有处理异常- -!
利用深度优先搜索解决简单的迷宫问题,其核心函数定义在下面。

/*
迷宫问题,入口和出口唯一,每次有四个方向移动,规定迷宫大小为10x10
*/
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include "stack.h"
bool map[N][N];	//用bool型二维数组表示10x10的地图
bool book[N][N];	//标记每个坐标是否走过,0表示没走过,1表示走过
Position des;	//储存终点坐标
Stack path;	//存储路径的栈
void next(Position now);
bool arrived();
int main() {
	cout << "输入一个10x10的迷宫:障碍物输入1,空地输入0" << endl;
	for (int i = 0; i < N; i++) {	//输入迷宫
		for (int j = 0; j < N; j++) {
			cin >> map[i][j];
		}
	}
	cout << "迷宫如下:" << endl;
	cout << "   1 2 3 4 5 6 7 8 9 10" << endl;	//输出列号
	for (int i = 0; i < N; i++) {
		if (i == 9)
			cout << i + 1;		//输出行号,第十行时为了对齐少打印一个空格
		else
			cout << i + 1 << " ";		//输出行号
		for (int j = 0; j < N; j++) {	//输出第j+1行
			cout << " ";	//用于对齐
			if (map[i][j] == 1)
				cout << "*";	//障碍物打印'*'
			else
				cout << " ";	//空地打印空格
		}
		cout << endl;
	}
	int x, y;
	cout << "输入起点坐标(行,列)" << endl;
	cin >> x >> y;
	Position now(x, y);	//当前坐标
	cout << "输入终点坐标" << endl;
	cin >> x >> y;
	des.setpos(x, y);	//输入终点坐标
	next(now);
	if (!arrived())	//遍历所有可能走不到终点
		cout << "没有出口" << endl;
	else {
		Stack result;	因为栈不能从头输出,所以将path栈倒进result栈再输出即可实现逆序输出
		while (!path.isempty())	
			result.push(path.pop());	//path出栈后入result栈
		cout << "从起点到终点的路径为:" << endl;
		int i = 0;	//记录输出了几个坐标,使输出更加工整
		while (!result.isempty()) {
			i++;
			result.pop().print();
			cout << "  ";
			if (i % 5 == 0)	//为了整齐,每5个坐标换一行
				cout << endl;
		}
	}
	return 0;
}
bool arrived() {
	return (path.gettop().getx() == des.getx() && path.gettop().gety() == des.gety());	//到达终点返回true
}
void next(Position now) {
	path.push(now);	//当前坐标入栈
	if (book[now.getx() - 1][now.gety() - 1] == 1) {
		path.pop();	//若当前坐标已经走过,则出栈并返回上一层递归
		return;
	}
	if (arrived())
		return;	//若已经到达终点,则返回上一层递归
	if (now.is_obstacle(map) || now.overstep(map)) {
		path.pop();	//若当前坐标是障碍或者越界,则出栈并返回上一层递归
		return;
	}
	book[now.getx() - 1][now.gety() - 1] = 1;	//设置当前坐标为走过
	/*
		用递归的方式寻找每一步可以走的路径,以右,上,下,左为顺序
	*/
	next(now.right());	//先一直向右走,直到到达终点或遇到障碍或越界
	if (arrived())
		return;
	next(now.up());	//再退回来往上走,重复
	if (arrived())
		return;
	next(now.down());	//往下走
	if (arrived())
		return;
	next(now.left());	//往左走
	if (arrived())
		return;
	book[now.getx() - 1][now.gety() - 1] = 0;	//当前坐标四个方向都试过后设为未走过,供接下来的尝试继续使用
	return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值