用栈实现简单的迷宫游戏

迷宫游戏的实现是运用了栈的“后进先出”的原理,究竟如何实现的呢?下来简单的分析一下。

比如:下图是一个小迷宫

1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
0 0 0 1 1 1 1 1 1 1
1 1 0 1 1 1 1 1 1 1      //0---表示通路
1 1 0 1 1 1 1 0 0 0     //1----表示墙
1 1 0 1 1 1 1 0 1 1
1 1 0 0 0 0 0 0 1 1
1 1 0 1 1 1 1 0 1 1
1 1 0 1 1 1 1 0 1 1
1 1 1 1 1 1 1 1 1 1

我们实现迷宫的步骤:

1.利用栈来解决此问题,首先得有个栈,可以自己实现也可以用库里的.

栈只允许在末端进行插入和删除的线性表,具有“后进先出”的特点;

如下图,data10后push进的,却先被pop.


2.首先得开辟一个二维数组并将迷宫代表数据读入;

1)开辟该数组有两种方式:

void InitMaze(int arr[][N])    //二维数组形式
void InitMaze(int* arr)        //一维数组形式
其实,二维数组在

计算机中存储时依然是线性的,以一维数组的形式更能模拟二维数组的开辟。

2)从文本文件中读取数据时需注意:

*读出来的是字符‘0’,‘1’,要进行转化(字符-'0'转化为数字);

*控制列时,将空格跳过.

3.下来就是如何得到一条通路(这里就要用栈的原理了):

1)首先我们将入口push进去,然后对现在位置的四个方向进行检测(试探法),哪个方向是通的就继续往下走,如果走到边界仍然通的那么恭喜你找到迷宫出的路线了(可以做个标记),假如走入死胡同,那么必须就得返回继续找通路;

2)每往下走一步,push进一个数据,并加以标记;每返回一步,就pop掉一个数据,再做个标记,这一点就体现了回溯法。

下来先看一下栈的代码实现:

#include<assert.h>
#include<ostream>
using namespace std;

struct Istruetype
{
	bool get()
	{
		return true;
	}
};
struct Isfalsetype
{
	bool get()
	{
		return false;
	}
};
template<typename T>
struct TypeTraits
{
	typedef Isfalsetype Ispodtype;   //自定义类型
};
template<>
struct TypeTraits<int>
{
	typedef Istruetype Ispodtype;    //内置类型
};
template<>
struct TypeTraits<char>
{
	typedef Istruetype Ispodtype;    //内置类型
};


template<class T>
class Stack
{
public:
	Stack():_data(0)
		   ,_sz(0)
		   ,_capacity(0)
	{}
	~Stack()
	{
		if(_data!=NULL)
		{
			delete[] _data;
			_data=NULL;
		}
		_sz=0;
		_capacity=0;
	}
public:
	void Push(const T& x)
	{
		CheckCapacity();
		_data[_sz++]=x;
	}
	void Pop()
	{
		assert(_sz>0);
		--_sz;
	}
	bool Empty()
	{
		return _sz==0;
	}
	size_t Size()
	{
		return _sz;
	}
	T& Top()
	{
		return _data[_sz-1];
	}
	void PrintStack()
	{
		if(_sz==0)
		{
			cout<<"顺序表已空"<<endl;
		}
		for(size_t i=0;i<_sz;++i)
		{
			cout<<_data[i]<<" ";
		}
		cout<<endl;
	}
	
protected:
	void CheckCapacity()
	{
		if(_sz==_capacity)
		{
			size_t newcapacity=_capacity*2+2;
			T* tmp=new T[newcapacity];
		    if(TypeTraits<T>::Ispodtype().get())
			{
				memcpy(tmp,_data,sizeof(T)*_sz);
			}
			else
			{
				for(size_t i=0;i<_sz;++i)
				{
					tmp[i]=_data[i];
				}	
			}
			delete[] _data;
			_data=tmp;
			_capacity=newcapacity;
		}
	}

private:
	T* _data;
	size_t _sz;
	size_t _capacity;
};

然后就是迷宫实现的主体部分:

#include<iostream>
using namespace std;
#include<assert.h>
#include"Stack.h"
const int N=10;
//void InitMaze(int arr[][N]);    //二维数组形式
void InitMaze(int* arr)        //一维数组形式
{
	FILE* file=fopen("MazeMap.txt","r");
	assert(file);
	for(size_t i=0;i<N;++i)
	{
		for(size_t j=0;j<N;)
		{
			char value=fgetc(file);
			if(value=='0'||value=='1')
			{
				arr[i*N+j]=value-'0';    //以一维数组的形式
				++j;                    //跳过空格
			}
		}
	}
	fclose(file);
}

struct pos
{
	int _row;
	int _col;
	pos(int row=2,int col=0)
		:_row(row),_col(col)
	{}
};

bool CheckCross(int* arr,pos next)        //检查下一位置是否有效
{
	if((next._row>=0) && (next._row<N )        //不能越界且值为0才通过
	   && (next._col>=0 )&& (next._col<N)
	   && (arr[next._row*N+next._col]==0))
	{
		return true;
	}
	else
	{
		return false;
	}
}

bool GetPath(Stack<pos> path,pos& entry,int* arr)
{
	path.Push(entry);
	arr[entry._row*N+entry._col]=2;
	while(!path.Empty())
	{
		pos cur=path.Top();   //每次cur为栈顶元素
		pos next=cur;
		if(next._row == N-1 ||next._row==0 || next._col==N-1)   //走到边界就返回
		{
			return true;
		}
		//上
		next._row--;
		if(CheckCross(arr,next))
		{
			path.Push(next);
			arr[next._row*N+next._col]=2;
			continue;
		} 
		next._row++; 
		//下
		next._row++;
		if(CheckCross(arr,next))
		{
			path.Push(next);
			arr[next._row*N+next._col]=2;
			continue;
		}
		next._row--;

		//左
		next._col--;
		if(CheckCross(arr,next))
		{
			path.Push(next);
			arr[next._row*N+next._col]=2;
			continue;
		}
		next._col++;
		//右
		next._col++;
		if(CheckCross(arr,next))
		{
			path.Push(next);
			arr[next._row*N+next._col]=2;
			continue;
		}
		next._col--;

		path.Pop();                  //找不到通路就返回
		arr[cur._row*N+cur._col]=3; //标记回溯路线
	}
	return false;

}

void PrintMaze(int* arr)
{
	for(size_t i=0;i<N;++i)
	{
		for(size_t j=0;j<N;++j)
		{
			cout<<arr[i*N+j]<<" ";
		}
		cout<< endl;
	}
}
void PrintPath(int* arr)
{
	Stack<pos> path;
	pos entry;
	GetPath(path,entry,arr);
	for(size_t i=0;i<N;++i)
	{
		for(size_t j=0;j<N;++j)
		{
			cout<<arr[i*N+j]<<" ";
		}
		cout<< endl;
	}
}

int main()
{
	int arr[N][N];
	InitMaze((int*)arr);
	PrintMaze((int*) arr);
	cout<<endl;
	PrintPath((int*) arr);
	system("pause");
	return 0;
}

根据试探法的检测方向的顺序不同,回溯标记就会不同.对于迷宫游戏的优化,比如找出最优通路等暂时还没想出来,继续努力!









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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值