其他分享
首页 > 其他分享> > 迷宫

迷宫

作者:互联网

迷宫游戏

深度优先遍历(DFS)

顾名思义DFS就是从一个节点出发直到不能访问然后回转到上一层 也就是所说的“回溯+递归”
该方法我学习了老师PPT上的内容,可以这样理解:
(1)访问顶点v

在这里插入图片描述
(2)从v的未被访问的邻接点中选取一个顶点w,重复第一步,如果没有未被访问的邻接点,回溯至上一顶点
(3)重复前两步,直至图中所有和v路径相通的顶点都被访问到

总的来说就是,回溯+递归

此算法参照老师PPT教学上的代码,基本可以看懂。
C++部分代码实现:

void Creat_Map01(int x_index, int y_index)
{
	int x_tmp, y_tmp;
	int tag = 0;//做标记,看当前位置的四周是否还有有效通道Road
	int rand_Direction;//随机生成四个方向
		rand_Direction = rand() % 4;//随机生成四个方向
 		if (rand_Direction == 0 && x_index >= 3 && map[x_index - 2][y_index] == Road)//向上
          	{ x_index = x_index - 2;}
  		else if (rand_Direction == 1 && x_index < count - 3 && map[x_index + 2][y_index] == Road)//向上
         	{ x_index = x_index + 2;}
  		else if (rand_Direction == 2 && y_index > 3 && map[x_index][y_index - 2] == Road)//向左
         	{ y_index = y_index - 2;}
  		else if (rand_Direction == 3 && y_index < count - 3 && map[x_index][y_index + 2] == Road)//向右
        	{ y_index = y_index + 2;}
	while (1)
	{	tag = IsHaveNeighbor(x_index, y_index);
		if (tag == 0)	
            return;
		else
		{
		    map[x_index][y_index] = Red;
		    x_tmp = x_index;
		    y_tmp = y_index;
                                 //产生四个随机方向的新坐标;
		   map[(x_tmp + x_index) / 2][(y_tmp + y_index) / 2] = Red;
		   map[x_index][y_index] = Red;
		   Creat_Map01(x_index, y_index);
		}
	}
}

A*算法

在计算机科学中,A*算法作为Dijkstra(迪杰斯特拉)算法的扩展,是一种静态路网中求解最短路径有效的直接搜索方法,因其高效性被广泛应用于寻路及图的遍历中
首先明确几个概念:

搜索区域

搜索区域可以划分为正方形格子,但不限于此,六边形,矩形,平行四边形都可以。因此他们的中心点通常称为节点,而不是方格。

路径排序

下一步怎么移动由以下公式确定:F(n)=G+H。F(n)为估价函数,G代表的是从初始位置Start沿着已生成的路径到指定待检测结点移动开销。H表示待检测结点到目标节点B的估计移动开销。

启发函数

H为启发函数,可以看作是一种试探,由于在找到唯一路径前,不确定在前面会出现什么障碍物,因此用了一种计算H的算法,具体可以根据实际情况决定。为了简化问题,H采用的是传统的曼哈顿距离,也就是横纵向走的距离之和。

开放列表

将寻路过程中待检测的结点存放于Open List中,而已检测过的结点则存放于Close List中。

以上是A* 的关键点,尤其是启发函数,如果没有启发函数,则A* 就退化成了Dijkstra算法,是运行效率重要还是找到最佳路径重要,全靠启发函数来调节,因此也被归为启发式算法。

A*算法的具体步骤

  1. 把起点加入openlist
  2. 遍历openlist,找到F值最小的节点,把它作为当前处理的节点,并把该节点加入closelist中
  3. 对该节点的8个相邻格子进行判断, 如果格子是不可抵达的或者在closelist中,则忽略它,否则如下操作:
    a. 如果相邻格子不在openlist中,把它加入,并将parent设置为该节点和计算f,g,h值
    b.如果相邻格子已在openlist中,并且新的G值比旧的G值小,则把相邻格子的parent设置为该节点,并且重新计算f值。
  4. 重复2,3步,直到终点加入了openlist中,表示找到路径;或者openlist空了,表示没有路径。

参考文章:
A算法详解
A算法入门
https://blog.csdn.net/yghlqgt/article/details/109608550

A* 算法部分,参照了网络上的大量资料,虽然原理基本可以理解,但真正实现起来还是有些困难,故参考了CSDN上的各位大神的部分代码。

public static Grid aStarSearch(Grid start, Grid end) {
		//准备两个链表,分别存储 将要选择的节点  和  已经走过的节点
		ArrayList<Grid> openlist=new ArrayList<Grid>();
		ArrayList<Grid> closelist=new ArrayList<Grid>();
		//将起点加入链表,准备开始寻路。
		openlist.add(start);
		//只要链表不为空,就重复这个寻路的过程
		while(openlist.size()>0) {
			//找到 openlist中 F值最小的那个 方格(节点)
			Grid currentgrid=findMinGrid(openlist);
			//从 openlist中删除找到的那个  F值 最小的那个节点
			openlist.remove(currentgrid);
			//将这个  F值 最小的节点,加入到  closelist 中
			closelist.add(currentgrid);
			//寻找  当前找到的这个 F值最小的节点的  邻居节点 ——上下左右,四个方向上的节点,要判断它们是否为合法可用的节点。
			List<Grid> neighbors=findNeighbors(currentgrid, openlist, closelist);
			//对合法可用的邻居节点进行初始化,并加入到  openlist中
			for(Grid grid : neighbors) {
				if(!openlist.contains(grid)) {
					grid.initGrid(currentgrid,end);
					openlist.add(grid);
				}
			}
			//邻居节点加入  openlist 后,判断openlist中,是否包含  终点节点,如果包含终点,直接返回并退出。
			for(Grid grid : openlist) {
				if((grid.x==end.x) && (grid.y==end.y)) {
					return grid;
				}
			}
		}
		return null;
	}
	//寻找邻居节点的方法,返回值为  链表  ——创建一个合理的邻居链表
	private static ArrayList<Grid> findNeighbors(Grid grid, List<Grid> openlist, List<Grid> closelist) {
		ArrayList<Grid> gridlist=new ArrayList<Grid>();
		//判断上下左右邻居节点的合理性,没问题就加入到邻居链表中。
		if(isValidGrid(grid.x, grid.y-1, openlist, closelist)) {//下
			gridlist.add(new Grid(grid.x, grid.y-1));
		}
		if(isValidGrid(grid.x, grid.y+1, openlist, closelist)) {//上
			gridlist.add(new Grid(grid.x, grid.y+1));
		}
		if(isValidGrid(grid.x-1, grid.y, openlist, closelist)) {//左
			gridlist.add(new Grid(grid.x-1, grid.y));
		}
		if(isValidGrid(grid.x+1, grid.y, openlist, closelist)) {//右
			gridlist.add(new Grid(grid.x+1, grid.y));
		}
		return gridlist;
	}
	//判断当前位置的节点是否合理
	private static boolean isValidGrid(int x, int y, List<Grid> openlist, List<Grid> closelist) {
		//当前节点是否越界,不再MAZE数组范围内了,注意二位数组的长度计算方法及含意
		//MAZE。length表示行的长度
		//MAZE[0]。length表示列的长度
		if(x<0 || x>=MAZE.length || y<0 || y>=MAZE[0].length) {
			return false;
		}
		//当前节点是否为障碍节点
		if(MAZE[x][y]==1) {
			return false;
		}
		//判断当前节点是否在 openlist中
		if(containgrid(openlist, x, y)) {
			return false;
		}
		//判断当前节点是否在 closelist中
		if(containgrid(closelist, x, y)) {
			return false;
		}
		return true;
	}
	//判断当前链表中是否包含当前的节点
	private static boolean containgrid(List<Grid> grids, int x, int y) {
		for(Grid grid : grids) {
			if((grid.x==x) && (grid.y==y)) {
				return true;
			}
		}
		return false;
	}
	//寻找当前链表中的节点F值 最小的那个节点,并返回这个节点。
	private static Grid findMinGrid(ArrayList<Grid> openlist) {
		Grid tempgrid=openlist.get(0);
		for(Grid grid : openlist) {
			if(grid.f<tempgrid.f) {
				tempgrid=grid;
			}
		}
		return tempgrid;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int b1=0,b2=0;//起始坐标
		int c1=0,c2=6;
		Grid startgrid=new Grid(b2,b1);
		System.out.println("起点坐标为:"+"("+b1+","+b2+")");
		Grid endgrid=new Grid(c2,c1);
		System.out.println("终点坐标为:"+"("+c1+","+c2+")");
		Grid resultgrid=aStarSearch(startgrid,endgrid);
		//创建回溯链表
		ArrayList<Grid> path=new ArrayList<Grid>();
		while(resultgrid!=null) {
			path.add(new Grid(resultgrid.x, resultgrid.y));
			resultgrid=resultgrid.parent;
		}
		//打印输出当前寻路路径
		int count=0;
		for(int i=0; i<MAZE.length; i++) {
			for(int j=0; j<MAZE[0].length; j++) {
				if(containgrid(path, i, j)) {
					System.out.print("走, ");
					count++;
				}
				else
				{
					System.out.print(MAZE[i][j]+ ", ");
				}
			}
			System.out.println();
		}
		System.out.println("最短路径长度为:"+count);
	}

参考链接:
https://blog.csdn.net/xgf415/article/details/75200047
https://blog.csdn.net/Dog_dream/article/details/80270398
https://mochen.blog.csdn.net/article/details/109558689
https://blog.csdn.net/little_mind/article/details/45920961
https://blog.csdn.net/weixin_46037153/article/details/107136560
https://blog.csdn.net/u010944926/article/details/20635829
https://blog.csdn.net/ws_PersonalSpace/article/details/83420458

标签:index,openlist,迷宫,closelist,grid,Grid,节点
来源: https://blog.csdn.net/Smileyiii/article/details/111598648