老鼠走迷宫c++两种实现

  • Post author:
  • Post category:其他


迷宫问题:给定入口和出口,随机生成一个可以走出去的迷宫。

【解决办法】

1.迷宫地图用二维数组,用随机数生成数组元素,空格为通,#做墙壁。

2.每次探测当前位置的上下左右,如果是通路,继续探测;如果不是通路,回到上一个走过位置,递归调用的思想。

当然也可以用压栈和堆栈来回溯。

3.利用二维数组下标的界限来判断是否找到出口。

这里使用了c++,直接在类中写了代码,由于代码不多,最好还是在类中声明,函数实现单独完成。

给大家贴出代码:

#include<iostream>
#include<getch.h>
#include<stdlib.h>
#include <time.h>
using namespace std;
time_t tstart;
//设置迷宫结构
struct Maze
{
private:
	//地图
	char map[15][15];
	//空位置数量
	int space; 
	//入口位置
	char in_x,in_y;
	//出口位置
	char out_x,out_y;
	//坐标
	char x,y;
	//老鼠位置
	char m_x,m_y;
	int success;
	//......
	//构造地图
	void create_map(void)
	{
		srand(time(NULL));
		//在地图中全部填#
		for(int i=0;i<15;i++)
		{
			for(int j=0;j<15;j++)
			{
				map[i][j]='#';
			}
		}
		//设置出口、入口
		for(int i=0;i<space;)
		{
			x=rand()%13+1;
			y=rand()%13+1;
			if(map[x][y]=='#')
			{
				map[x][y]=' ';
				i++;
			}
			
			
		}

		map[in_x][in_y]='@';
		
	
		
		if(map[out_x][out_y]!=' ')
		{
			map[out_x][out_y]=' ';
		}
		
	}
	//检查地图是否可以走出
	int check_map(int i,int j)
	{
		//参考经典算法大全
		map[i][j]='@';		
		if(i == out_x && j ==out_y )
		{
			success = 1;
		}
		if(success != 1 && map[i][j+1] == ' ') check_map(i, j+1);
		if(success != 1 && map[i+1][j] == ' ') check_map(i+1, j);
		if(success != 1 && map[i][j-1] == ' ') check_map(i, j-1);
		if(success != 1 && map[i-1][j] == ' ') check_map(i-1, j);
		if(success != 1)
		{
			map[i][j] = ' ';
		}
		return success;
	}
	
public:
	//构建迷宫
	Maze(char inx,char iny,char outx,char outy,int _space)
	{
		//使用构造函数的参数对成员初始化
		in_x=m_x=inx;
		in_y=m_y=iny;
		out_x=outx;
		out_y=outy;
		space=_space;
		while(1)
		{
			//构造地图
			create_map();
			//检查地图是否可以走出
			success=0;
			if(check_map(in_x,in_y)==1)
			{	
				break;
			}
		}
		for (int i = 0; i < 15; ++i)
		{
			for(int j=0;j<15;j++)
			{
				if(map[i][j]=='@')
				{
					map[i][j]=' ';
				}
			}
		}
		map[in_x][in_y]='@';
		tstart=time(NULL);
	}
	//显示迷宫
	void show(void)
	{
		system("clear");
		//printf("\33[2J");
		for(int i=0;i<15;i++)
		{
			for(int j=0;j<15;j++)
			{
				cout<<map[i][j]<<' ';
			}
			cout<<endl;
		}
	}
	//老鼠向上
	void up(void)
	{
		if(map[m_x-1][m_y]==' ')
		{
			map[m_x-1][m_y]='@';
			map[m_x][m_y]=' ';
			m_x-=1;
		}
		else 
		{
			return;
		}
	}
	//老鼠向下
	void down(void)
	{
		if(map[m_x+1][m_y]==' ')
		{
			map[m_x+1][m_y]='@';
			map[m_x][m_y]=' ';
			m_x+=1;
		}
		else 
		{
			return;
		}
	}
	//向右
	void right(void)
	{
		if(map[m_x][m_y+1]==' '&&m_y<=14)
		{
			map[m_x][m_y+1]='@';
			map[m_x][m_y]=' ';
			m_y+=1;
		}
		else 
		{
			return;
		}
	}
	//向左
	void left(void)
	{
		if(map[m_x][m_y-1]==' '&&m_y>=1)
		{
			map[m_x][m_y-1]='@';
			map[m_x][m_y]=' ';
			m_y-=1;
		}
		else 
		{
			return;
		}
	}
	//检查是否到达出口
	bool check(void)
	{
		if(m_x==out_x&&m_y==out_y)
		{
			return true;
		}
		return false;
	}
};

int main()
{
	//创建迷宫对象
	Maze maze(1,1,14,13,140);

	while(1)
	{
		//检查是否走通
		if(maze.check())
		{
			maze.show();
			time_t tend=time(NULL);
			cout<<"逃出迷宫!用时"<<tend-tstart<<"秒!"<<endl;
			break;
		}
		//显示地图
		maze.show();
		
		switch(getch())
		{
			case 183:maze.up();break;
			case 184:maze.down();break;
			case 185:maze.right();break;
			case 186:maze.left();break;
		}
	}
}

给大家再来一个用栈实现的版本:

Maze.h


#pragma once

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>

#include "Stack.h"

 

using namespace std;

 

struct Pos

{

 

	Pos(int row = 0, int col = 0)

	:_row(row)

	, _col(col)

	{}

	int _row;

	int _col;

};

 

void InitMazeMap(char* map, int row, int col);

void PrintMazeMap(char* map, int row, int col);

bool GetPath(char* map, int row, int col, Pos enter,Stack<Pos>& path);

bool IsExport(const Pos& pos, int row, int col);

bool IsAccess(const Pos& pos, char* map, int row, int col);

void GetSize(int* prow, int* pcol);

Maze.cpp


<pre class="cpp" name="code">#include "Maze.h"

#include <cassert>



void InitMazeMap(char* map, int row, int col)

{

	FILE* f1 = fopen("MazeMap.txt", "r");

	assert(f1);

	//跳过第一行

	int ch = fgetc(f1);

	while (ch != '\n')

	{

		ch = fgetc(f1);

	}

 

	//开始读取迷宫地图

	for (int i = 0; i < row; ++i)

	{

		for (int j = 0; j < col;)

		{

			ch = fgetc(f1);

			if (ch == '0' || ch == '1')

			{

				map[i*col + j] = ch;

				++j;

			}

		}

	}

	fclose(f1);

}

 

 

void PrintMazeMap(char* map, int row, int col)

{

	for (int i = 0; i < row; ++i)

	{

		for (int j = 0; j < col; ++j)

		{

			cout << map[i*col + j] << " ";

		}

		cout << endl;

	}

	cout << endl;

 

}

 

//找通路

bool GetPath(char* map, int row, int col, Pos enter, Stack<Pos>& path)

{

	map[enter._row*col + enter._col] = '2';

	path.Push(enter);

 

	while (!path.Empty())

	{

		Pos cur = path.Top();

		if (cur._col!= enter._col && cur._row!=enter._row && IsExport(cur,row,col))

		{

			return true;

		}

		//上

		Pos next = cur;

		next._row -= 1;

		if (IsAccess(next,map,row,col))

		{

			map[next._row*col + next._col] = '2';

 

			path.Push(next);

			continue;

		}

		//右

		next = cur;

		next._col += 1;

		if (IsAccess(next, map, row, col))

		{

			map[next._row*col + next._col] = '2';

 

			path.Push(next);

			continue;

		}

 

		//下

		next = cur;

		next._row += 1;

		if (IsAccess(next, map, row, col))

		{

			map[next._row*col + next._col] = '2';

 

			path.Push(next);

			continue;

		}

		//左

		next = cur;

		next._col -= 1;

		if (IsAccess(next, map, row, col))

		{

			map[next._row*col + next._col] = '2';

 

			path.Push(next);

			continue;

		}

		map[cur._row*col + cur._col] = '3';

		path.Pop();

	}

	return false;

}

 

//判断pos位置是否通

bool IsAccess(const Pos& pos, char* map, int row, int col)

{

	if (pos._row >= 0 && pos._row < row

		&&pos._col >= 0 && pos._col < col

		&&map[pos._row*col + pos._col] == '0')

	{

		return true;

	}

	else

	{

		return false;

	}

}

 

//判断pos位置是否为出口

bool IsExport(const Pos& pos, int row ,int col)

{

	if (pos._col == 0 || pos._row == 0 || pos._col == (col - 1) || pos._row == (row - 1))

	{

		return true;

	}

	else

	{

		return false;

	}

}

 

//从文件中获取迷宫的大小

void GetSize(int* prow, int* pcol)

{

	FILE* f = fopen("MazeMap.txt", "r");

	assert(f);

	int ch = fgetc(f);

 

	while (ch != '\n' && (ch <= '0' || ch >= '9'))//跳过非数字字符

	{

		ch = fgetc(f);

	}

	while (ch >= '0'&&ch <= '9') //row

	{

		*prow = *prow * 10 + (ch - '0');

		ch = fgetc(f);

	}

	while (ch != '\n'&& (ch<='0' || ch>='9'))

	{

		ch = fgetc(f);

	}

	while (ch >= '0' && ch <= '9')//col

	{

		*pcol = *pcol * 10 + (ch - '0');

		ch = fgetc(f);

	}

	fclose(f);

}

Stack.h当然也可以用库里的,这里自己实现了一下


#pragma once

#include <cassert>

#include <iostream>

using namespace std;

 

 

template <class T>

class Stack

{

public:

	Stack()

		:_data(NULL)

		, _size(0)

		, _capacity(0)

	{}

	~Stack()

	{

		if (_data != NULL)

		{

			delete _data;

			_data = NULL;

			_size = 0;

			_capacity = 0;

		}

	}

	void Push(const T& data)

	{

		CheckCapacity();

		_data[_size++] = data;

	}

	void Pop()

	{

		assert(_size > 0);

		_size--;

	}

	T& Top() const

	{

		assert(_size > 0);

		return _data[_size - 1];

	}

	bool Empty() const

	{

		return _size == 0;

	}

	size_t Size() const

	{

		return _size;

	}

protected:

	void CheckCapacity()

	{

		if (_size == _capacity)

		{

			size_t newCapacity = _capacity * 2 + 3;

			T* tmp = new T[newCapacity];

			for (size_t i = 0; i < _size; ++i)

			{

				tmp[i] = _data[i];

			}

			delete _data;

			_data = tmp;

			_capacity = newCapacity;

		}

	}

protected:

	T* _data;

	size_t _size;

	size_t _capacity;

};

test.cpp


#include "Stack.h"

#include "Maze.h"

void TestStack()

{

	Stack<int> s1;

	s1.Push(1);

	s1.Push(2);

	s1.Push(3);

	s1.Push(4);

 

	while (!s1.Empty())

	{

		cout << s1.Top() << endl;

		s1.Pop();

	}

 

}

 

void TestMaze()

{

	int row = 0;

	int col = 0;

	GetSize( &row, &col);

	char* Map = (char*)malloc((row*col)*sizeof(char));

	Pos mEnter(2, 0);

	Stack<Pos> path;

	InitMazeMap( Map, row, col);

 

	PrintMazeMap(Map, row, col);

	if(GetPath(Map, row, col, mEnter, path))

	{

		PrintMazeMap(Map, row, col);

	}

	else

	{

		cout << "没有通路"<<endl;

	}

	free(Map);

}

int main()

{

	TestMaze();

	system("pause");

	return 0;

}



版权声明:本文为Dachao0707原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。