迷宫求解(C++)

0 项目介绍

此算法适用C++,使用栈求解迷宫。比较 参考文章,本文采用系统栈函数,迷宫为n行m列,并进行了大量优化。本文介绍部分函数,资源如下*(审核中)* 。其余函数可依据参考文章,进行些许改动即可实现。
测试程序(免费)
完整资源
参考文章

1 子函数

1.1 栈相关

1.1.1 stack.h

#include <iostream>
#include <stack>
using namespace std;

struct PosType {
	int x;			//横坐标
	int y;			//纵坐标
	PosType() {
		x = y = 0;
	}
	void NextPos(int di);
};
class SElemType {
private:
	int ord;		//通道块在路径上的“序号”
	PosType seat;	//通道块在迷宫中的“坐标位置”
	int di;			//从此通道块走向下一通道块的方向
public:
	SElemType() {
		ord = di = 0;
	}
	SElemType(int o, PosType se, int d) {
		ord = o;
		seat.x = se.x;
		seat.y = se.y;
		di = d;
	}
	PosType Seat();
	void Print(stack<SElemType>& S);
	bool NoPass(stack<SElemType>& S);
	void NextPos(stack<SElemType>& S, PosType& se);
};//栈的元素类型

1.1.2 函数功能

class SElemType:

	//返回该点坐标seat
	PosType Seat();
	//打印路线,并清空栈
	void Print(stack<SElemType>& S);
	//若此点的四个方向不通,且栈不空,返回true
	//否则,返回false
	bool NoPass(stack<SElemType>& S);
	//若此点下一个方向未走过,修改该点方向,更新当前坐标,将该点入栈
	//右di=1,下di=2,左di=3,上di=4
	void NextPos(stack<SElemType>& S, PosType& se);

class PosType:

	//更新当前坐标
	void NextPos(int di);

1.1.3 stack.cpp

部分函数

#include "stack.h"

PosType SElemType::Seat() {
	return seat;
}
void SElemType::Print(stack<SElemType>& S) {
	int i = 0;
	while (!S.empty()) {
		*this = S.top();
		switch (di) {
		case 1:cout << "从西来"; break;
		case 2:cout << "从东来"; break;
		case 3:cout << "从北来"; break;
		case 4:cout << "从南来"; break;
		}
		cout << ord << ":(" << seat.x << ',' << seat.y << ')';
		i++; S.pop();
		if (!(i % 4)) cout << endl;
	}
	if (i % 4) cout << endl;
}
bool SElemType::NoPass(stack<SElemType>& S) {
	if (di == 4)
		if (!S.empty())
			return true;
	return false;
}

路线打印void SElemType::Print(stack& S),为反向打印,即从终点到起点(栈顶到栈底)。

1.2 迷宫相关

1.2.1 maze.h

#include "stack.h"
#include <time.h>

struct MazeType {
	int t;
	MazeType() {//构造函数,用于初始化
		t = 0;
	}
};
class Maze {
private:
	MazeType** maze;
	int m, n;//迷宫长m宽n
public:
	Maze(int mu,int nu) {
		m = mu;
		n = nu;
		maze = new MazeType*[nu];
		for (int i = 0; i < n; i++)
			maze[i] = new MazeType[mu]();
	}
	~Maze() {//析构函数,程序结束时自动调用
		for (int i = 0; i < n; i++)
			delete[] maze[i];
		m = n = 0;
		delete[] maze;
	}
	void Create();
	void Print();
	bool Pass(PosType p);
	void FootPrint(PosType p);
	void MarkPrint(SElemType e);
	bool MazePath(stack<SElemType>& S, PosType start, PosType end);
};

1.2.2 函数功能

class Maze:

	//构造迷宫,创造路
	void Create();
	//打印迷宫
	void Print();
	//若当前位置p合法,可以通过且未走过,maze[p.y][p.x]=1,返回true
	bool Pass(PosType p);
	//留下足迹,当前位置p已经走过,maze[p.y][p.x]=2
	void FootPrint(PosType p);
	//留下足迹,不能通过,maze[p.y][p.x]=3
	void MarkPrint(SElemType e);
	//若找到通路,存放在栈中,并返回true;否则,返回false
	bool MazePath(stack<SElemType>& S, PosType start, PosType end);

1.2.3 maze.cpp

部分函数

#include "maze.h"

void Maze::Create() {
	srand((unsigned int)time(0));
	int i, j;
	for (i = 0; i < n; i++)
		for (j = 0; j < m; j++)
			maze[i][j].t = rand() % 2;
}
void Maze::Print() {
	int i, j;
	cout << "\033[41m红墙\033[42m绿路\033[43m黄通路\033[44m蓝足迹\033[0m" << endl;
	cout << 'n' << endl;
	for (i = n - 1; i >= 0; i--) {
		printf_s("%-2d", i);
		for (j = 0; j < m; j++) {
			switch (maze[i][j].t){
			case 0:cout << "\033[41m×"; break;
			case 1:cout << "\033[42m√"; break;
			case 2:cout << "\033[43m○"; break;
			case 3:cout << "\033[44m○"; break;
			}
		}
		cout << "\033[0m" << endl;
	}
	cout << "  ";
	for (j = 0; j < m; j++)
		printf_s("%-2d", j);
	cout << 'm' << endl;
}
bool Maze::MazePath(stack<SElemType>& S, PosType start, PosType end) {
	SElemType e;
	int curstep = 1;		//探索第一步
	PosType curpos = start;	//设定当前位置为入口位置
	while (!S.empty()) S.pop();
	do {
		if (Pass(curpos)) {//当前点可以走通
			FootPrint(curpos);//留下标记,此点已经走过
			e = SElemType(curstep, curpos, 1);//得到此点的下一步,尝试向右
			S.push(e);
			if (curpos.x == end.x)
				if (curpos.y == end.y)
					return true;
			curpos.NextPos(1);//修改当前坐标
			curstep++;//步数加1
		}
		else {
			if (!S.empty()) {
				e = S.top(); S.pop();
				while (e.NoPass(S)) {//此路不通,留下足迹,回到上一步
					MarkPrint(e);
					e = S.top(); S.pop();
				}
				e.NextPos(S, curpos);//e点的下一步,顺序为:先右,后下,再左,最后上
			}
		}
	} while (!S.empty());
	return false;
}

对于void Maze::Create(),可进行优化,生成一个更好的迷宫。

2 主函数

2.1 main.cpp

#include "maze.h"

int main() {
	int m, n; SElemType e;
	stack<SElemType> S;
	PosType start, end;
	cout << "迷宫求解" << endl;
	cout << "  输入m n,迷宫长m宽n:" << endl;
	cin >> m >> n;
	Maze maze = Maze(m, n);
	while (1) {
		maze.Create();
		cout << "迷宫长" << m << "宽" << n << endl;
		maze.Print();
		cout << "输入入口坐标m n和出口坐标m n" << endl;
		cin >> start.x >> start.y >> end.x >> end.y;
		if (!maze.MazePath(S, start, end))
			cout << "\033[31m迷宫不能通过,重新生成迷宫.\033[0m" << endl;
		else break;
	}
	cout << "\033[32m成功通过迷宫 ^-^\033[0m" << endl;
	cout << "\033[32m走过的路线\033[0m" << endl;
	e.Print(S);
	cout << "\033[32m走过的迷宫\033[0m" << endl;
	maze.Print();
	return 0;
}

2.2测试截图

测试1
测试2

3 总结

3.1 不足之处

  1. 本文只是找到了一条通路,并未实现最短路径,如测试的图1
  2. 迷宫生成随意,可能会出现类似下图的情况
    在这里插入图片描述
  3. 存在空间浪费
    对于MazeType** maze,其中maze = new MazeType*[nu];
    多出了nu个maze[i].t

3.2 改进

问题3(未验证)

struct MazeType {
	int m;//迷宫长m
	int* e;
	MazeType(int mu) {//构造函数,用于初始化
		m = mu;
		e = new int[mu]();
	}
	~MazeType() {
		delete[] e;
		e = NULL;
		m = 0;
	}
};
class Maze {
private:
	MazeType* maze;
	int n;//迷宫宽n
public:
	Maze(int mu,int nu) {
		n = nu;
		maze = new MazeType[nu](mu);
	}
	~Maze() {//析构函数,程序结束时自动调用
		for (int i = 0; i < n; i++)
			delete maze[i];
		n = 0;
		delete[] maze;
		maze = NULL;
	}
	void Create();
	void Print();
	bool Pass(PosType p);
	void FootPrint(PosType p);
	void MarkPrint(SElemType e);
	bool MazePath(stack<SElemType>& S, PosType start, PosType end);
};

正向打印

可采用文章中的自定义栈函数进行实现

迷宫求解

思路如下

void Print(Stack s){
	SElemType e;
	while(S.base != S.top){
		e = *S.base;
		cout << e;
		S.base++;
	}
}

针对本课题些许改动,即可成功实现

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值