寻找迷宫出口<一>

寻找迷宫出口<一>

<coad = C++>

小程序目的: 判断在一个10*10的矩阵中是否可以找到迷宫的出口;

PS:程序功能比较单一,还有许多可以改进的地方,比如,可以寻找出口的最优路径,可是我现在没有想出来,

所以,在 寻找迷宫出口<二> 我会对迷宫问题做出进一步的完善!

-----------------------------------------------------------------------------


程序所用到的迷宫模板,和需要动态开辟的数组大小; 包含在文件“ test.txt”中


10 10
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
1 1 0 1 1 1 1 1 1 1
1 1 0 1 1 1 1 1 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 0 1 1 1 1 1 1 1

-----------------------------------------------------------------------------------------

程序运行结果:



----------------------------------------------

以下是程序的源代码,代码中表标有注释; coad = C++;

程序分为两部分,头文件Stack.h 包含头文件和对栈的实现;

maze.cpp包含对走迷宫的实现;

-------------------------------------------------------------------------------------------

Stack.h

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cassert>

using namespace std;


struct Pos//定位坐标,定位当前位置
{
	int _row;
	int _col;

	Pos(int row = 0,int col = 0)
		:_row(row)
		,_col(col)
	{}
};

template<typename T>
class Seqlist
{
public :
	Seqlist()
		:_pdata(NULL)
		,_size(0)
		,_capacity(3)
	{
		_pdata = new T[3];
	}
	~Seqlist()
	{
		cout<<"~Stack()"<<endl;
		if(_pdata != NULL)
		{
			delete[] _pdata;
			_size = 0;
			_capacity = 0;
		}
	}

	void push_back(const T& data)
	{
		check_capacity ();
		_pdata[_size] = data;
		_size++;
	}

	void pop_back()
	{
		assert(_pdata);
		_size--;
	}

	
protected:
	void check_capacity()
	{
		if(_size == _capacity)
		{
			size_t NewCapacity = _capacity*2 + 3;
			T* tmp = new T[NewCapacity];
			for(int i = 0; i<_size; i++)
			{
				tmp[i] = _pdata[i];
			}
			delete[] _pdata;
			_pdata = tmp;
			_capacity = NewCapacity;
		}
	}
public:	
    size_t _size;// 方便访问,如果觉得不太好,可以封装一个公有的函数返回;
	T* _pdata;
	size_t _capacity;
};

template<class T,class Container=Seqlist<T> >
class Stack
{
public:

	bool empty()
	{
		return _con._size==0;
	}

	size_t szie()
	{
		return _size;
	}

	T& top()
	{
		int size = _con._size - 1;
		return _con._pdata[size];
	}

	void push(const T& data)
	{
		_con.push_back(data);
	}

	void pop()
	{
		_con.pop_back();
	}

private:
	Container _con;
};






maze.cpp

#pragma once

#include"Stack.h"

// 设为全局变量可以省去很多传参;
int*maze = NULL;
int rows = 0;
int cols = 0;

void init_maze()// 动态开辟二维数组,读取迷宫数组;
{
	

	FILE* pf = fopen("test.txt","r");
	assert(pf);

	int tmp;
	while((tmp = fgetc(pf))!=' ')
	{
		rows =rows*10 + tmp-'0';
	}
	while((tmp = fgetc(pf))!='\n')
	{
		cols = cols*10 +tmp-'0';
	}

	maze = (int*)malloc(rows*cols*sizeof(int));
	//开辟rows*cols长度的数组,把它看作二维数组;
	assert(maze);

	for(int i = 0; i<rows; i++)
	{
		for(int j = 0; j<cols;)
		{
			tmp = fgetc(pf);
			if(tmp!=EOF && tmp!=' ' && tmp!='\n')
			{
				maze[i*rows+j] =  tmp-'0';
				j++;
			}
		}
	}
	fclose(pf);
}

void printmaze()//打印迷宫
{
	for(int i = 0; i<rows; i++)
	{
		for(int j = 0; j<cols;j++)
		{
			cout<<maze[i*rows+j]<<" ";
		}
		cout<<endl;
	}
}


void make_push(Stack<Pos>& paths,Pos pos)//压栈,给走过的路径设置标志操作;
{
	paths.push (pos);
	maze[pos._row*cols + pos._col] = 2;
}

bool check_exit(const Pos& pos)
{
	if(pos._row == 9 && pos._col == 2)
		return true;
	return false;
}

bool get_path(Stack<Pos>& paths,Pos pos)// 走迷宫,返回迷宫是否找到出口;
{
	//应该封装一个函数专门负责压栈和对走过的坐标进行标记的任务;
	//对四个方向的可行性进行判断;可行则压栈,不可行则Pop;应是一个循环;
	//考虑是否遇到出口? 遇到出口则到达边缘值,没有出口则会回到出发点,即栈会为空;

	 make_push(paths,pos);//压栈,给走过的路径设置标志操作;

	 while(!paths.empty())
	 { 
		 pos = paths.top();// 每次从栈顶读取一个元素;

		 int row_1 = pos._row - 1;
		 if(maze[row_1*cols + pos._col] == 0 
			 && row_1 >= 0 && row_1 < rows && 
			 pos._col >=0 && pos._col < cols)
		 {
			 pos._row = pos._row -1;
			 make_push(paths,pos);
			 continue ;
		 }
		 // 右
		 int  col_1 = pos._col + 1;
		 if(maze[pos._row  * cols + col_1] == 0 
			 && pos._row >= 0 && pos._row < rows && 
			 col_1 >=0 && col_1 < cols)
		 {
			 pos._col+=1;
			 make_push(paths,pos);
			 continue ;
		 }

		 // 左
		 col_1 = pos._col - 1;
		 if(maze[pos._row  * cols + col_1] == 0 
			 && pos._row >= 0 && pos._row < rows && 
			 col_1 >=0 && col_1 < cols)
		 {
			 pos._col -= 1;
			 make_push(paths,pos);
			 continue ;
		 }

		 //下
		 row_1 = pos._row + 1;
		 if(maze[row_1*cols + pos._col] == 0 
			 && row_1 >= 0 && row_1 < rows && 
			 pos._col >=0 && pos._col < cols)
		 {
			 pos._row+=1;
			 make_push(paths,pos);
			 continue ;
		 }

		 if(check_exit(pos))//检查如果到达出口则返回ture;
			 return true;
		 paths.pop ();//四个方向都不通,则删除一个栈顶元素;
	 }

	 return false;//栈为空代表没有出口,返回false;
}

void free_memery()//千万别因为程序运行出来了而忘了释放内存;
{
	 free(maze);
	 maze = NULL;
}

int main()
{
	init_maze();//从文件中将迷宫读取到二维数组中;
	printmaze();//打印迷宫;

	Stack<Pos> paths;
	//用栈的目的在于保存以前走过的路径,万一走到死胡同,还有回旋的余地;

	cout<<"此迷宫是否有通路:\n1:有\n0:没有\n结果:"<<get_path(paths,Pos(2,0))<<endl;

	printmaze();
	//再打印一次迷宫;

	free_memery();
	//paths对象在程序结束后会自己调用析构函数;

	system("pause");
	return 0;
}

代码比较粗糙,如有问题,欢迎指出!

#include <stdio.h> #include <iostream> #include <queue> #include <stack> #include <vector> #include <algorithm> // 用于remove函数 using namespace std; // 定义节点结构体,包含坐标、步数、前驱坐标 typedef struct node { int x; int y; int count; int preX; // 前驱节点x坐标 int preY; // 前驱节点y坐标 } node; // 方向数组(下、左、上、右) int dx[4] = {1, 0, -1, 0}; int dy[4] = {0, -1, 0, 1}; int main() { int rows, cols, xbegin, ybegin, numExits; // 输入迷宫基本信息 printf("请输入迷宫大小(行 列): "); scanf("%d%d", &rows, &cols); printf("请录入起点坐标(x y): "); scanf("%d%d", &xbegin, &ybegin); printf("请输入出口数量: "); scanf("%d", &numExits); // 存储出口坐标 vector<pair<int, int>> exits(numExits); printf("请输入每个出口的坐标(x y),空格分隔:\n"); for (int i = 0; i < numExits; i++) { scanf("%d%d", &exits[i].first, &exits[i].second); } // 存储迷宫格局(1表示障碍,0表示通路) vector<vector<int>> maze(rows + 1, vector<int>(cols + 1)); printf("请输入迷宫格局(1表示障碍,0表示通路):\n"); for (int i = 1; i <= rows; i++) { for (int k = 1; k <= cols; k++) { scanf("%d", &maze[i][k]); } } // 访问标记数组(2表示已访问) vector<vector<int>> visited(rows + 1, vector<int>(cols + 1, 0)); // 初始化起点节点 node start; start.x = xbegin; start.y = ybegin; start.count = 0; start.preX = -1; // 起点无前驱,用-1标记 start.preY = -1; visited[xbegin][ybegin] = 2; // 标记起点已访问 queue<node> q; q.push(start); // 存储找到出口节点 vector<node> endNodes; bool allExitsFound = false; // BFS搜索 while (!q.empty() &&!allExitsFound) { node current = q.front(); // 取出队首节点 q.pop(); // 弹出队首,避免死循环 // 检查当前节点是否为出口 for (auto it = exits.begin(); it!= exits.end(); ) { if (current.x == it->first && current.y == it->second) { endNodes.push_back(current); // 记录找到出口 it = exits.erase(it); // 移除已找到出口 if (exits.empty()) { allExitsFound = true; // 所有出口找到,结束搜索 } break; } else { ++it; } } // 探索四个方向 for (int i = 0; i < 4; i++) { int tx = current.x + dx[i]; int ty = current.y + dy[i]; // 检查边界、是否为通路、是否已访问 if (tx >= 1 && tx <= rows && ty >= 1 && ty <= cols && maze[tx][ty] == 0 && visited[tx][ty]!= 2) { // 生成新节点 node temp; temp.x = tx; temp.y = ty; temp.count = current.count + 1; // 步数+1 temp.preX = current.x; // 前驱为当前节点x temp.preY = current.y; // 前驱为当前节点y visited[tx][ty] = 2; // 标记已访问 q.push(temp); // 加入队列 } } } // 输出所有找到的路径 if (!endNodes.empty()) { for (int i = 0; i < endNodes.size(); i++) { stack<node> path; // 用栈存储路径(从出口回溯到起点) node cur = endNodes[i]; // 回溯路径:从出口倒推到起点 while (cur.preX!= -1 && cur.preY!= -1) { path.push(cur); // 当前节点入栈 // 通过前驱坐标找到一个节点 int prevX = cur.preX; int prevY = cur.preY; // 更新当前节点为前驱节点(继续回溯) cur.x = prevX; cur.y = prevY; } path.push({xbegin, ybegin, 0, -1, -1}); // 起点入栈 // 输出路径(栈顶到栈底是起点到出口) printf("出口 %d 的路径:\n", i + 1); while (!path.empty()) { node n = path.top(); path.pop(); printf("(%d, %d) ", n.x, n.y); } printf(" 总步数: %d\n", endNodes[i].count); } } else { printf("未找到任何出口的路径!\n"); } return 0; }这样是不是不对呀?
最新发布
07-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值