利用C++面向对象OOP思想实现迷宫maze的路径寻找问题(详解加代码)

版权声明:转用请注明出处 https://blog.csdn.net/weixin_39411321/article/details/89283574

问题描述:

利用OOP思想完成迷宫路径的寻找问题

程序运行要求如下:

请输入迷宫的行列数: 5 5

请输入迷宫路径节点信息(1表示不能走,0表示能走)
在这里插入图片描述
开始寻找迷宫路径(从左上角到右下角的一个可通行的路径):

迷宫存在可通行的路径:
在这里插入图片描述

程序所包含的头文件和如下
#include "targetver.h"
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#include<stdio.h>
#include<fstream>
#include <tchar.h>
using namespace std;

const int RIGHT = 0;
const int DOWN = 1;
const int LEFT = 2;
const int UP = 3;
const int OK = 4;
const int ERR = 5;

题目分析:

先抽象出来三个类:

迷宫结点类(MazeNode )

结点类的成员变量

结点的坐标:mx,my;

结点的值:mval(0/1);

结点的四个方向(up/down/right/left);

class MazeNode
{
public:
	MazeNode()
	{
		// 先初始化迷宫路径的四个方向为可行走状态
		for (int i = 0; i < 4; ++i)
		{
			mway[i] = OK; //初始化把结点的四个方向都设置为可状态
		}
	}
	int getVal() { return mval; }
	int getX() { return mx; }
	int getY() { return my; }
	int getWayState(int way) { return mway[way]; }

	void setWayState(int way, int state) { mway[way] = state; }//设置方向状态
	void setVal(int val) { mval = val; }
	void setX(int x) { mx = x; }
	void setY(int y) { my = y; }
private:
	int mval;
	int mx;
	int my;
	int mway[4];
};

迷宫类(Maze)

迷宫类的成员变量

迷宫的行mrow和列mcol;

迷宫的结点MazeNode **mpcells;

存放迷宫路径的Stack mstack;

迷宫类的成员方法

// 调整路径的行走状态信息
setMazeNodeState();

//设置结点信息
setMazeNode(int val, int i, int j)

// 开始寻找迷宫路径
findMazePath();

// 打印迷宫路径信息
showResult();
迷宫类的代码如下:
class Maze
{
public:
	Maze(int r, int c)
		:mrow(r), mcol(c) //动态开辟了一个二维数组存放迷宫结点
	{
		mpcells = new MazeNode*[mrow]; //先开辟一维数组
		for (int i = 0; i < mrow; ++i) 
		{
			mpcells[i] = new MazeNode[mcol]; //在一维的基础上再开辟二维
		}
	}
	~Maze()
	{
		for (int i = 0; i < mrow; ++i)
		{
			delete[]mpcells[i];
		}
		delete[]mpcells;
		mpcells = nullptr;
	}
	void setMazeNode(int val, int i, int j)
	{
		mpcells[i][j].setVal(val);
		mpcells[i][j].setX(i);
		mpcells[i][j].setY(j);
	}
	void setMazeNodeState()
	{
		for (int i = 0; i < mrow; ++i)
		{
			for (int j = 0; j < mcol; ++j)
			{
				if (mpcells[i][j].getVal() == 1)//如果值为1 说明不可走
				{
					continue;
				}
				if (i == 0)//说明是第一行则把他的上方向置为不可走
				{
					mpcells[i][j].setWayState(UP, ERR);
				}
				if (j == 0)//说明是第一列则把他的左方向置为不可走
				{
					mpcells[i][j].setWayState(LEFT, ERR);
				}
				if (i == mrow - 1)//说明是最后一行则把他的下方向置为不可走
				{
					mpcells[i][j].setWayState(DOWN, ERR);
				}
				if (j == mcol - 1)//说明是最后一列则把他的右方向置为不可走
				{
					mpcells[i][j].setWayState(RIGHT, ERR);
				}
				if (i>0 && mpcells[i - 1][j].getVal() == 1)
				//不是第一行且他的上方向[i - 1][j]的值为1,则把他的上方向置为不可走;
				{
					mpcells[i][j].setWayState(UP, ERR);
				}
				if (i<mrow - 1 && mpcells[i + 1][j].getVal() == 1)
				//不是最后一行且他的下方向[i + 1][j]的值为1,则把他的下方向置为不可走;
				{
					mpcells[i][j].setWayState(DOWN, ERR);
				}
				if (j>0 && mpcells[i][j - 1].getVal() == 1)
				//不是第一列且他的左方向[i][j - 1]的值为1,则把他的左方向置为不可走;
				{
					mpcells[i][j].setWayState(LEFT, ERR);
				}
				if (j<mcol - 1 && mpcells[i][j + 1].getVal() == 1)
				//不是最后一列且他的右方向[i][j + 1]的值为1,则把他的右方向置为不可走;
				{
					mpcells[i][j].setWayState(RIGHT, ERR);
				}
			}
		}
	}
	void findMazePath()
	{
		//若迷宫的起始结点的值为1,则肯定不存在迷宫路径;
		if (mpcells[0][0].getVal() == 1)
			return;

		//把正确的路径结点压入stack中;
		mstack.push(mpcells[0][0]);
		
		while (!mstack.empty())
		{
			MazeNode top = mstack.top();
			int x = top.getX();
			int y = top.getY();
			if (x == mrow - 1 && y == mcol - 1)//如果到达了迷宫的右下角则退出;
			{
				return;
			}
			//我们自己默认了一个结点的查询方向依次为右下左上
			//如果某一个结点的右边的的状态为可走
			if (mpcells[x][y].getWayState(RIGHT) == OK)
			{
				mpcells[x][y].setWayState(RIGHT, ERR);
				//把当前结点的右方向置为不可走 表示已经走过这条路径以后不能再走这条冤枉路了
				//以防止后来出栈后继续走这条路导致在这里死循环
				//详细下边会讲
				mpcells[x][y + 1].setWayState(LEFT, ERR);
				//同理把右边结点的左方向也置为不可走
				mstack.push(mpcells[x][y + 1]);
				//然后把右边的结点进行压栈 压入到迷宫的正确路径里边去
				continue;
			}
			//以下三个方向的调整思想都是同理的
			if (mpcells[x][y].getWayState(DOWN) == OK)
			{
				mpcells[x][y].setWayState(DOWN, ERR);
				mpcells[x + 1][y].setWayState(UP, ERR);
				mstack.push(mpcells[x + 1][y]);
				continue;
			}
			if (mpcells[x][y].getWayState(LEFT) == OK)
			{
				mpcells[x][y].setWayState(LEFT, ERR);
				mpcells[x][y - 1].setWayState(RIGHT, ERR);
				mstack.push(mpcells[x][y - 1]);
				continue;
			}
			if (mpcells[x][y].getWayState(UP) == OK)
			{
				mpcells[x][y].setWayState(UP, ERR);
				mpcells[x - 1][y].setWayState(DOWN, ERR);
				mstack.push(mpcells[x - 1][y]);
				continue;
			}
			//走到这一步说明该结点的四个方向都是不可走的 
			//所以我们要出栈试一试上个结点的其他方向是否可以通 
			//这时候回到上个结点就不能走这个结点的方向了 
			//而要走默认顺序的四个方向的下一个方向
			//因为我们当时已经把要走的下一个方向的状态置为不可走了
			//如果上个结点的四个方向也不通则一直出栈 
			//直到栈空 说明没有正确的通的迷宫路径
			mstack.pop();
		}
	}
	void showResult()
	{
		if (mstack.empty())//判断路径栈是否空
		{
			cout << "该迷宫不存在可通行的路径" << endl;
			return;
		}
		cout << "该迷宫存在可通行的路径为:" << endl;
		while (!mstack.empty())//把栈里边的正确路径信息的结点的值都设置为*;
		{
			MazeNode node = mstack.top();
			mpcells[node.getX()][node.getY()].setVal('*');
			mstack.pop();
		}
		//打印出迷宫
		for (int i = 0; i < mrow; ++i)
		{
			for (int j = 0; j < mcol; ++j)
			{
				if (mpcells[i][j].getVal() == '*')
				{
					cout << "*" << " ";
				}
				else
				{
					cout << mpcells[i][j].getVal() << " ";
				}
			}
			cout << endl;
		}
	}
private:
	int mcol;
	int mrow;
	MazeNode **mpcells;
	Stack mstack;
};

存放迷宫正确通路径的stack类(Stack)

栈就不用多说了;就是很简单的出栈和入栈操作
代码如下:

class Stack
{
public:
	// 成员方法,操作的就是成员变量
	Stack(int size = 10)
		:mtop(-1), msize(size)
	{
		mpStack = new MazeNode[msize];
	}
	~Stack()
	{
		delete[]mpStack;
		mpStack = nullptr;
	}
	void push(MazeNode &p)
	{
		if (this->full())
			this->resize();
		mpStack[++mtop] = p;
	}
	void pop()
	{
		if (this->empty())
			return;
		this->mtop--;
	}
	MazeNode top()const
	{
		if (empty())
			throw"";
		return this->mpStack[this->mtop];
	}
	bool full()const { return this->mtop == this->msize - 1; }
	bool empty()const { return this->mtop == -1; }
private:
	MazeNode *mpStack; // 存放栈的元素
	int mtop; // 栈顶指针
	int msize; // 栈的总长度
	void resize()//stack的动态扩容函数要私有化
	{
		MazeNode* ptemp = new MazeNode[msize * 2];
		for (int i = mtop; i >= 0; i--)
		{
			ptemp[i] = mpStack[i];
		}
		delete[]mpStack;
		mpStack = ptemp;
		msize *= 2;
	}
};

主函数:

int main()
{
	cout << "输入迷宫的大小:";
	int row, col;
	cin >> row >> col;

	Maze maze(row, col);

	cout << "输入迷宫路径信息:" << endl;
	for (int i = 0; i < row; ++i)
	{
		for (int j = 0; j < col; ++j)
		{
			int data;
			cin >> data;  // data  [i, j]
			maze.setMazeNode(data, i, j);
		}
	}
	// 调整路径的行走状态信息
	maze.setMazeNodeState();

	// 开始寻找迷宫路径
	maze.findMazePath();

	// 打印迷宫路径信息
	maze.showResult();

	return 0;
}
运行结果如下

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_39411321/article/details/89283574
今日推荐