迷宫求解——附栈的实现

今天我们来完成一个简单的迷宫,首先我们需要一个迷宫地图在文件中,方便我们在文件中读取它。这是地图:

然后我们就进行读取地图,并保存地图到数组里面,这样很方便给出坐标。

接下来我们就要考虑怎么走了,其实很简单,我们只需让当前位置经行查找,上下左右只要是通路就移动到下一个位置,直到找到出口。

那如果走到死胡同了该如何,其实也很容易,这里我们就需要运用回溯法来解决问题。

那么什么事回溯法呢?

回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

当我们走到死路后就退回到上一个位置,继续判断,直到有一个方向是通路就继续走。

完成回溯法就需要用到我们的栈来实现,栈的特点就是在尾部插,尾部删,我们每次走一步就push进去一个数据,当需要退回时就pop一个出来。

这里需要用到栈,我们就自己来实现一把。

<strong>template<typename T>  
class Stack  
{  
public:  
	Stack()  
		:_capacity(0)  
		, _size(0)  
		, _arr(NULL)  
	{}  
	~Stack()  
	{  
		delete[] _arr;  
		_size = 0;  
		_capacity = 0;  
		_arr = NULL;  
	}  
	void Push(const T& data);  
	void Pop();  
	T Top();  
	int Size();  
	bool Empty();  
private:  
	void CheckCapacity()  
	{  
		if (_size >= _capacity)  
		{  
			int NewCapacity = _capacity * 2 + 1;  
			T* tmp = new T[NewCapacity];  
			for (int i = 0; i < _size; i++)  
			{  
				tmp[i] = _arr[i];  
			}  
			delete[] _arr;  
			_arr = tmp;  
			_capacity = NewCapacity;  
		}  
	}  
private:  
	T* _arr;  
	int _capacity;  
	int _size;  
};  

template<typename T>  
bool Stack<T>::Empty()   //判断栈是否为空
{  
	if (_size == 0)  
		return true;  
	else  
		return false;  
}  

template<typename T>  
void Stack<T>::Push(const T& data)  //进栈
{  
	CheckCapacity();  
	_arr[_size++] = data;  
}  

template<typename T>  
void Stack<T>::Pop()  //出栈
{  
	assert(_size>0);  
	--_size;  
}  

template<typename T>  
T Stack<T>::Top()  //返回栈顶元素
{  
	return _arr[_size - 1];  
}  

template<typename T>  
int Stack<T>::Size()  //栈的大小
{  
	return _size;  
}  
</strong>
当我们每走一步就把走过的路置为2,方便判断。

下面就是代码实现:

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

template<typename T>  
class Stack  
{  
public:  
	Stack()  
		:_capacity(0)  
		, _size(0)  
		, _arr(NULL)  
	{}  
	~Stack()  
	{  
		delete[] _arr;  
		_size = 0;  
		_capacity = 0;  
		_arr = NULL;  
	}  
	void Push(const T& data);  
	void Pop();  
	T Top();  
	int Size();  
	bool Empty();  
private:  
	void CheckCapacity()  
	{  
		if (_size >= _capacity)  
		{  
			int NewCapacity = _capacity * 2 + 1;  
			T* tmp = new T[NewCapacity];  
			for (int i = 0; i < _size; i++)  
			{  
				tmp[i] = _arr[i];  
			}  
			delete[] _arr;  
			_arr = tmp;  
			_capacity = NewCapacity;  
		}  
	}  
private:  
	T* _arr;  
	int _capacity;  
	int _size;  
};  

template<typename T>  
bool Stack<T>::Empty()   //判断栈是否为空
{  
	if (_size == 0)  
		return true;  
	else  
		return false;  
}  

template<typename T>  
void Stack<T>::Push(const T& data)  //进栈
{  
	CheckCapacity();  
	_arr[_size++] = data;  
}  

template<typename T>  
void Stack<T>::Pop()  //出栈
{  
	assert(_size>0);  
	--_size;  
}  

template<typename T>  
T Stack<T>::Top()  //返回栈顶元素
{  
	return _arr[_size - 1];  
}  

template<typename T>  
int Stack<T>::Size()  //栈的大小
{  
	return _size;  
}  


#define N 10
struct POS 
{
	POS(const int& row=0,const	int col=0)
		:_row(row)
		,_col(col)
	{}
	size_t _row;
	size_t _col;
};

void Getmaze(int *arr)   //从文件中读取地图,保存在数组里
{
	FILE* maze= fopen("MazeMap.txt","r");
	assert(maze!=NULL);
	int i=0,j=0;
	for (i=0;i<N;i++)
	{
		for (j=0;j<N;)
		{
			char c=fgetc(maze);
			if (c=='0'||c=='1')
			{
				arr[i*N+j]=c-'0';
				j++;
			}
			continue;
		}
	}
	fclose(maze);
}

void Printmaze(int *arr)   //打印地图
{
	for (int i=0;i<N;i++)
	{
		for (int j=0;j<N;j++)
		{
			cout<<arr[i*N+j]<<" ";
		}
		cout<<endl;
	}
}

bool Checkpath(int *maze, POS &next)   //检查下个路是否是通路
{
	if (next._col < N && next._row < N
		&& next._col >= 0 && next._row >= 0
		&& (maze[next._row*N + next._col] == 0))
		return true;
	else
		return false;
}
bool Getpath(int *maze, int row, int col, Stack<POS> &path, POS enter)
{
	POS cur = enter;
	POS next;
	path.Push(cur);
	while (!path.Empty())
	{
		if (cur._row != enter._row&&cur._col != enter._col && (cur._row == row - 1 || cur._row == 0 || cur._col == col - 1))
		{
			maze[cur._row*N + cur._col] = 2;           //走过的路置为2
			return true;

		}

		maze[cur._row*N + cur._col] = 2;

		//右
		next = cur;
		++next._col;
		if (Checkpath(maze, next))
		{
			cur = next;
			path.Push(cur);
			continue;
		}


		//左
		next = cur;
		--next._col;
		if (Checkpath(maze, next))
		{
			cur = next;
			path.Push(cur);
			continue;
		}

		//上
		next = cur;
		--next._row;
		if (Checkpath(maze, next))
		{
			cur = next;
			path.Push(cur);
			continue;
		}

		//下
		next = cur;
		++next._row;
		if (Checkpath(maze, next))
		{
			cur = next;
			path.Push(cur);
			continue;
		}
		cur = path.Top();
		path.Pop();
	}
	return false;
}
void test()
{
	Stack<POS> path;
	int maze[N][N];
	Getmaze((int *)maze);
	Printmaze((int *)maze);
	cout << endl;
	Getpath((int *)maze, N, N, path, POS(2, 0));
	cout << "找到出口后:" << endl;
	Printmaze((int *)maze);

}

int main()
{
	test();
	system("pause");
	return 0;
}

到此迷宫的问题就完了。

这是运行后的结果:



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值