数据结构-栈应用-迷宫

使用了 unity 完成,因为 unity 非常方便图形显示


Maze.cs

using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;

public class Maze : MonoBehaviour 
{
	public int StartIndex;
	public int EndIndex;

	private int[,] MazeArray;
	private const int row = 7;
	private const int col = 7;

	private GameObject Player;

	private bool success = false;
	private Stack<int> Path = new Stack<int>();

	void Awake()
	{
		// 创建迷宫
		MazeArray = new int[row, col]
		{
			{1, 1, 1, 1, 1, 1, 1},
			{1, 1, 0, 0, 0, 0, 1},
			{1, 0, 0, 0, 1, 0, 1},
			{1, 0, 0, 0, 1, 0, 1},
			{1, 0, 1, 1, 1, 1, 1},
			{1, 0, 0, 0, 0, 0, 1},
			{1, 1, 1, 1, 1, 1, 1},
		};

		for(int i = 0; i < row; i++)
		{
			for(int j = 0; j < col; j++)
			{
				if(MazeArray[i, j] == 1)
				{
					CreateCube(i, j, CubeType.Wall);
				}
				else
				{
					CreateCube(i, j, CubeType.Path);
				}
			}
		}

		// 设置迷宫的起始位置和终点位置
		Vector2 pos = GetPositionByIndex(StartIndex);
		Player = CreateCube((int)pos.x, (int)pos.y, CubeType.Player);

		pos = GetPositionByIndex(EndIndex);
		CreateCube((int)pos.x, (int)pos.y, CubeType.Exit);

	}

	void Start () 
	{
		// 激活玩家,开始探索
		MazePlayer player = new MazePlayer();
		player.LoadMaze(MazeArray, StartIndex, EndIndex);

		success = player.Search(ref Path);
		if(success)
		{
			// 开始移动。。。。
			StartCoroutine(Move());
		}
	}

	IEnumerator Move()
	{
		if(Path.Count <= 0)
			yield break;

		Vector2 pos = GetPositionByIndex(Path.Pop());
		Player.transform.position = new Vector3(pos.x, pos.y, -0.2f);

		yield return new WaitForSeconds(0.4f);
		StartCoroutine(Move());
	}


	private GameObject CreateCube(int i, int j, CubeType type)
	{
		GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
		cube.transform.parent = transform;
		cube.gameObject.transform.position = new Vector3(i, j, 0);
		cube.transform.rotation = Quaternion.identity;

		switch(type)
		{
		case CubeType.Wall:
			cube.name = "Wall";
			cube.renderer.material.color = Color.cyan;
			break;
		case CubeType.Player:
			cube.name = "Player";
			cube.renderer.material.color = Color.green;
			cube.gameObject.transform.position = new Vector3(i, j, -0.2f);
			break;
		case CubeType.Exit:
			cube.name = "Exit";
			cube.renderer.material.color = Color.red;
			cube.gameObject.transform.position = new Vector3(i, j, -0.1f);
			break;
		}

		return cube;
	}


	private Vector2 GetPositionByIndex(int index)
	{
		int tempRow = index/ col;
		int tempCol = index - tempRow * col;

		return new Vector2(tempRow, tempCol);
	}

	private enum CubeType
	{
		Wall,
		Path,
		Player,
		Exit,
	}
}



MazePlayer.cs

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MazePlayer 
{
	private int _StartPos;
	private int _EndPos;
	private int[,] _MazeArray;
	private int _RowSize;
	private int _ColSize;

	public class Node
	{
		public int Index;
		public bool CanPass;
		public int Direction;
		public bool FootPrint;

		public Node(int index, bool canPass)
		{
			this.Index = index;
			this.CanPass = canPass;
			this.Direction = 0;
			this.FootPrint = false;
		}
	}

	private List<Node> _NodeList = new List<Node>();
	public Stack<Node> PathStack{get; private set;}

	public void LoadMaze(int[,] maze, int startPos, int endPos)
	{
		_MazeArray = maze;
		_RowSize = _MazeArray.GetLength(0); 
		_ColSize = _MazeArray.GetLength(1);

		for(int i = 0; i < _RowSize; i++)
		{
			for(int j = 0; j < _ColSize; j++)
			{
				Node node = new Node(i * _RowSize + j, _MazeArray[i, j] == 0);
				_NodeList.Add(node);
			}
		}

		this._StartPos = startPos;
		this._EndPos = endPos;
	}

	public bool Search(ref Stack<int> Path)
	{
		PathStack = new Stack<Node>();
		PathStack.Push(_NodeList[_StartPos]);

		do{
			// 查看当前块是否可通过
			Node node = PathStack.Peek();

			if(node.CanPass)
			{
				if(node.Index == _EndPos)
				{
					break;
				}

				MarkPrint(node);
				// 顺时针方向加入节点四个方向的块
				if(node.Direction < 4)
				{
					node.Direction++;
					int index = GetNextNodeIndex(node.Index, node.Direction);
					Node nextNode = _NodeList[index];
					if(nextNode.FootPrint == false)
					{
						PathStack.Push(nextNode);
					}
				}
				else
				{
					node = PathStack.Pop();
					node.CanPass = false;
				}
			}
			else
			{
				node = PathStack.Pop();
				node.CanPass = false;
			}

		}while(PathStack.Count > 0);

		if(PathStack.Count > 0)
		{
			while(PathStack.Count > 0)
			{
				Node node = PathStack.Pop();
				Path.Push(node.Index);
			}
			return true;
		}

		return false;
	}

	private void MarkPrint(Node node)
	{
		node.FootPrint = true;
	}


	private int GetNextNodeIndex(int crtIndex, int direction)
	{
		int crtRow = crtIndex / _ColSize;
		int crtCol = crtIndex - crtRow * _ColSize;

		int nextRow = crtRow;
		int nextCol = crtCol;
		if(direction == 1)
		{
			nextRow--;
		}
		else if(direction == 2)
		{
			nextCol++;
		}
		else if(direction == 3)
		{
			nextRow++;
		}
		else
		{
			nextCol--;
		}

		return nextRow * _ColSize + nextCol;
	}
}



### 数据结构 迷宫求解 算法实现 #### 1. 迷宫问题中的作用 是一种遵循“后进先出”(LIFO, Last In First Out)原则的数据结构,非常适合用于解决回溯类问题。在迷宫求解中,当沿着某条路径前进遇到死胡同时,需要退回到上一个岔路口尝试其他方向。这种行为正好可以用来模拟[^1]。 具体而言,每次进入一个新的位置时将其压入中;如果当前节点无路可,则弹出该节点并返回至上一节点重新寻找出路。通过这种方式可以记录下已经访问过的路径以及当前位置的状态信息。 #### 2. 基本思路 对于给定的一个二维数组表示的迷宫地图,其中`0`代表可通过的道路而`1`则表示墙壁不可穿越的地方。目标是从起点`(xs, ys)`出发找到到达终点`(xe, ye)`的一条合法路径或者判断不存在这样的路径。 整个过程大致分为以下几个方面考虑: - **初始化**:创建一个空用来保存行轨迹上的坐标点,并将起始点加入到这个里作为初始状态。 - **探索规则**:按照某种固定顺序依次试探四个方向(上下左右),一旦发现某个新方向满足条件就立即转向那里继续深入下去直到抵达目的地或是再次陷入困境为止。 - **标记已过区域**:为了避免重复遍历相同的位置造成循环往复的情况发生,在实际编码过程中还需要额外开辟一块辅助空间用作标志位阵列来指示哪些地方已经被考察过了。 以下是基于上述原理的具体C++代码示例: ```cpp #include <iostream> using namespace std; const int MAX = 10; // 定义最大迷宫尺寸 int maze[MAX][MAX]; // 存储迷宫布局 bool visited[MAX][MAX]; // 记录是否访问过 struct Point { int x; int y; }; Point stackArray[MAX * MAX]; // 使用数组模拟 int top = -1; // 顶指针 // 判断指定位置是否有效且未被访问 bool isValid(int x, int y){ return (x >=0 && x<MAX && y>=0 && y<MAX && !visited[x][y] && maze[x][y]==0); } void push(Point p){ stackArray[++top]=p; } Point pop(){ return stackArray[top--]; } bool findPath(int startX,int startY,int endX,int endY){ Point current={startX,startY}; push(current); while(top>-1){ current=pop(); if(current.x==endX&&current.y==endY){ cout<<"找到了一条路径!"<<endl; return true; } visited[current.x][current.y]=true; // 尝试向右移动 if(isValid(current.x,current.y+1)){ Point next={current.x,current.y+1}; push(next); continue; } // 尝试向下移动 if(isValid(current.x+1,current.y)){ Point next={current.x+1,current.y}; push(next); continue; } // 尝试向左移动 if(isValid(current.x,current.y-1)){ Point next={current.x,current.y-1}; push(next); continue; } // 尝试向上移动 if(isValid(current.x-1,current.y)){ Point next={current.x-1,current.y}; push(next); continue; } } cout<<"没有找到任何路径"<<endl; return false; } ``` 以上程序展示了如何利用来完成简单的迷宫寻径任务。需要注意的是这里仅提供了一个基础框架,实际情况下的迷宫规模可能会更大更复杂,因此可能需要进一步优化算法性能或调整数据结构以适应不同需求[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值