A星寻路
using System.Collections.Generic;
using System.Text;
using UnityEngine; namespace Game
{
public enum NodeType
{
Movable, //可移动区域
Obstacle, //障碍物
Boundary, //边界
Route //路径
} public enum NodeState
{
None, //默认
Open, //开放列表
Close //封闭列表
} public class SearchPath
{
private readonly Dictionary<Vector2, Node> m_nodes = new Dictionary<Vector2, Node>(); private readonly List<Node> list_close = new List<Node>();
private readonly List<Node> list_open = new List<Node>(); private Vector2 position_target; private Node[,] t_nodes; /// <summary>
/// 初始化地图信息
/// </summary>
/// <param name="width">宽</param>
/// <param name="height">高</param>
/// <param name="slant">斜向关联</param>
/// <returns>地图数据</returns>
public void InitMap(int width, int height, bool slant = false)
{
t_nodes = new Node[width, height]; m_nodes.Clear(); for (int i = ; i < width; i++)
{
for (int j = ; j < height; j++)
{
t_nodes[i, j] = new Node(i, j); if (i == || i == width - ||
j == || j == height - )
{
t_nodes[i, j].type = NodeType.Boundary;
} m_nodes.Add(new Vector2(i, j), t_nodes[i, j]);
}
} Vector2 key; //关联周边节点
for (int i = ; i < width; i++)
{
for (int j = ; j < height; j++)
{
if (slant)
{
for (int h = -; h <= ; h++)
{
for (int v = -; v <= ; v++)
{
if (h != || v != )
{
key = new Vector2(i + h, j + v); if (m_nodes.ContainsKey(key))
{
t_nodes[i, j].neighbour.Add(m_nodes[key]);
}
}
}
}
}
else
{
for (int k = -; k <= ; k++)
{
if (k != )
{
key = new Vector2(i + k, j); if (m_nodes.ContainsKey(key))
{
t_nodes[i, j].neighbour.Add(m_nodes[key]);
} key = new Vector2(i, j + k); if (m_nodes.ContainsKey(key))
{
t_nodes[i, j].neighbour.Add(m_nodes[key]);
}
}
}
}
}
}
} /// <summary>
/// 设置障碍物
/// </summary>
/// <param name="points">位置</param>
public void Obstacle(params Vector2[] points)
{
foreach (var key in points)
{
if (m_nodes.ContainsKey(key))
{
m_nodes[key].type = NodeType.Obstacle;
}
}
} /// <summary>
/// 寻路
/// </summary>
/// <param name="nodes">地图信息</param>
/// <param name="start">起点</param>
/// <param name="end">终点</param>
/// <returns>路径是否存在</returns>
public bool Search(Vector2 start, Vector2 end)
{
bool result = false; if (!m_nodes.ContainsKey(start) || !m_nodes.ContainsKey(end))
{
return result;
}
if (m_nodes[start].type != NodeType.Movable || m_nodes[end].type != NodeType.Movable)
{
return result;
} //设置终点
position_target = end; //重置路径
for (int i = ; i < t_nodes.GetLength(); i++)
{
for (int j = ; j < t_nodes.GetLength(); j++)
{
t_nodes[i, j].Reset();
}
} list_close.Clear();
list_open.Clear(); Node A = t_nodes[(int)start.x, (int)start.y];
A.G = ;
A.H = Vector2.Distance(position_target, A.position);
A.F = A.G + A.H;
A.parent = null;
A.state = NodeState.Close; list_close.Add(A); do
{
if (list_open.Count > )
{
A = list_open[];
}
for (int i = ; i < list_open.Count; i++)
{
if (list_open[i].F < A.F)
{
A = list_open[i];
}
} if (A.Compare(position_target))
{
result = true;
} Node B = Search(A); if (B != null)
{
do
{
B.type = NodeType.Route;
B = B.parent;
}
while (B != null);
}
list_close.Add(A);
list_open.Remove(A);
A.state = NodeState.Close;
}
while (list_open.Count > ); return result;
} private Node Search(Node A)
{
Node B; for (int i = ; i < A.neighbour.Count; i++)
{
if (A.neighbour[i] != null &&
A.neighbour[i].type == NodeType.Movable)
{
B = A.neighbour[i]; if (B.state == NodeState.None)//更新B的父节点为A,并相应更新B.G; 计算B.F,B.H; B加入OpenList
{
B.parent = A;
B.G = Vector2.Distance(A.position, B.position) + A.G;
B.H = Vector2.Distance(B.position, position_target);
B.F = B.G + B.H;
B.state = NodeState.Open; list_open.Add(B); if (B.H < Mathf.Epsilon)//B的所有父节点既是路径
{
return B;
}
}
else if (B.state == NodeState.Open)
{
float curG = Vector2.Distance(A.position, B.position); if (B.G > curG + A.G)//更新B的父节点为A,并相应更新B.G,B.H
{
B.parent = A;
B.G = curG + A.G;
B.F = B.G + B.H;
}
}
}
} return null;
} /// <summary>
/// 路径数据
/// </summary>
public List<Vector2> Output
{
get
{
List<Vector2> route = new List<Vector2>(); if (m_nodes.ContainsKey(position_target))
{
Node node = m_nodes[position_target]; while (node != null)
{
route.Add(node.position);
node = node.parent;
}
} StringBuilder sb = new StringBuilder(); for (int i = ; i < route.Count; i++)
{
sb.Append(route[i].ToString());
sb.Append("&");
} Debug.LogFormat("<color=yellow>{0}</color>", sb.ToString()); return route;
}
} public Node[,] GetNodes()
{
return t_nodes;
}
} public class Node
{
public Vector2 position; public NodeState state; public NodeType type; public float F; // F = G + H
public float G; //从起点移动到指定方格的移动代价
public float H; //从指定方格移动到终点的移动代价 public Node parent; public List<Node> neighbour = new List<Node>(); public Node(int x, int y)
{
position = new Vector2(x, y);
} public void Reset()
{
F = G = H = ; parent = null; state = NodeState.None; if (type.Equals(NodeType.Route))
{
type = NodeType.Movable;
}
} public bool Compare(Vector2 position)
{
return this.position.x == position.x &&
this.position.y == position.y;
}
}
}
using Game;
using System.Collections.Generic;
using UnityEngine; public class Test : MonoBehaviour
{
private SearchPath path_ctr; private Dictionary<Vector2, Renderer> m_map = new Dictionary<Vector2, Renderer>(); private void Awake()
{
path_ctr = new SearchPath();
} private void Start()
{
path_ctr.InitMap(, , true); for (int i = ; i < ; i++)
{
path_ctr.Obstacle(new Vector2(, i));
} for (int i = ; i < ; i++)
{
path_ctr.Obstacle(new Vector2(i, ));
} for (int i = ; i < ; i++)
{
path_ctr.Obstacle(new Vector2(i, ));
} Node[,] nodes = path_ctr.GetNodes(); InitMap(nodes); Search(new Vector2(, ), new Vector2(, ));
} private void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
Vector2 start = new Vector2(Random.Range(, ), Random.Range(, )); Vector2 end = new Vector2(Random.Range(, ), Random.Range(, )); Search(start, end);
}
} private void Search(Vector2 start, Vector2 end)
{
bool result = path_ctr.Search(start, end); if (result)
{
Debug.Log("<color=green>成功寻找到路径!</color>" + path_ctr.Output.Count);
}
else
{
Debug.LogFormat("<color=red>未寻找到路径,起始点:{0} 结束点{1}</color>", start, end);
} Node[,] nodes = path_ctr.GetNodes(); RefreshMap(nodes);
} public void InitMap(Node[,] nodes)
{
for (int i = ; i < nodes.GetLength(); i++)
{
for (int j = ; j < nodes.GetLength(); j++)
{
GameObject curCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
curCube.transform.position = new Vector3(i, j, );
m_map.Add(new Vector2(i, j), curCube.GetComponent<Renderer>());
}
}
} public void RefreshMap(Node[,] nodes)
{
for (int i = ; i < nodes.GetLength(); i++)
{
for (int j = ; j < nodes.GetLength(); j++)
{
Vector2 key = new Vector2(i, j); if (m_map.ContainsKey(key))
{
if (nodes[i, j].type == NodeType.Boundary)
{
m_map[key].material.SetColor("_Color", Color.black);
}
else if (nodes[i, j].type == NodeType.Obstacle)
{
m_map[key].material.SetColor("_Color", Color.red);
}
else if (nodes[i, j].type == NodeType.Route)
{
m_map[key].material.SetColor("_Color", Color.yellow);
}
else
{
m_map[key].material.SetColor("_Color", Color.white);
}
}
}
}
}
}
参考:https://blog.csdn.net/qq_36946274/article/details/81982691
A星寻路的更多相关文章
- A星寻路算法介绍
你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...
- 用简单直白的方式讲解A星寻路算法原理
很多游戏特别是rts,rpg类游戏,都需要用到寻路.寻路算法有深度优先搜索(DFS),广度优先搜索(BFS),A星算法等,而A星算法是一种具备启发性策略的算法,效率是几种算法中最高的,因此也成为游戏中 ...
- A星寻路算法
A星寻路算法 1.准备一个close关闭列表(存放已被检索的点),一个open开启列表(存放未被检索的点),一个当前点的对象cur 2.将cur设成开始点 3.从cur起,将cur点放入close表中 ...
- cocos2d-x学习日志(13) --A星寻路算法demo
你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢?如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! A星算法简介: A*搜寻算法俗称A星 ...
- 无递归 A星寻路算法
整理硬盘的时候,发现我早些年写的A星寻路算法.特放上来,待有缘人拿去,无递归噢,性能那是杠杠的. 码上伺候 public class Node { public int X { get; set; } ...
- A星寻路算法(A* Search Algorithm)
你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...
- A星寻路算法入门(Unity实现)
最近简单学习了一下A星寻路算法,来记录一下.还是个萌新,如果写的不好,请谅解.Unity版本:2018.3.2f1 A星寻路算法是什么 游戏开发中往往有这样的需求,让玩家控制的角色自动寻路到目标地点, ...
- A星寻路算法-Mind&Hand(C++)
//注1:Mind & Hand,MIT校训,这里指的理解与实现(动脑也动手) //注2:博文分为两部分:(1)理解部分,为参考其他优秀博文的摘要梳理:(2)代码部分,是C++代码实现的,源码 ...
- 【Android】基于A星寻路算法的简单迷宫应用
简介 基于[漫画算法-小灰的算法之旅]上的A星寻路算法,开发的一个Demo.目前实现后退.重新载入.路径提示.地图刷新等功能.没有做太多的性能优化,算是深化对A星寻路算法的理解. 界面预览: 初始化: ...
- [转载]A星寻路算法介绍
转载自:http://www.raywenderlich.com/zh-hans/21503/a%E6%98%9F%E5%AF%BB%E8%B7%AF%E7%AE%97%E6%B3%95%E4%BB% ...
随机推荐
- 【串线篇】spring boot对静态资源的映射规则
WebMvcAutoConfiguration的内部类 WebMvcAutoConfigurationAdapter 其中ResourceProperties点进去 其中addResourceHand ...
- loadrunner 使用
loadrunner给我的感觉很强势吧,第一次接触被安装包吓到了,当时用的是win10安装11版本的,各种安装失败,印象很深刻,那时候全班二三十号人,搞环境搞了两天,后来无奈,重做系统换成win7的了 ...
- 033:DTL常用过滤器(2)
date过滤器: date过滤器:将一个日期按照指定的格式,格式化成字符串.示例代码如下: views.py: from datetime import datetime def cur_date(r ...
- mysql服务设置远程连接
一.前期准备 1.虚拟机/物理机 mysql环境(非本机)2.本机 navicat软件(验证远程连接) 二 .mysql配置 1.在远程主机的本机 使用root用户连接mysql mysql ...
- vue项目中数学公式的展示
在这里有个mathjax的插件,可以将dom中的数学公式展示. 第一步安装mathjax npm install mathjax 安装完之后,你会在index.html中发现,已经引用了js文件,并且 ...
- FastDFS搭建文件管理系统
参考:https://www.cnblogs.com/chiangchou/p/fastdfs.html 目录: 一:FastDFS介绍 1:简介: FastDFS 是一个开源的高性能分布式文件系统( ...
- 最最简单的spring mvc + Maven项目
首先配置pom文件,只需要引用三个jar包文件即可: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi ...
- BZOJ 2729: [HNOI2012]排队 排列组合 + 高精度
Description 某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检.他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不 ...
- 【HDOJ6685】Rikka with Coin(DP)
题意:有10,20,30,100四种硬币,每种数量无限,给定n个a[i],问能组成所有a[i]的硬币的最小总数量 n<=1e2,a[i]<=1e9 思路: #include<bits ...
- 20180803-Java 流(Stream)、文件(File)和IO
Java 流(Stream).文件(File)和IO 下面的程序示范了用read()方法从控制台不断读取字符直到用户输入"q". // 使用BufferedReader 在控制台读 ...