//把起点放到开启列表
/*while(打开列表>0)
{
*得到当前位置周围f值最小的点,加入到开启列表;
*把当前点加入到关闭列表
*寻找出他周围可以走的位置,放到一个集合M里面
while(M里面是否有存在在开启列表里面的)
{
*计算出新的路径值G;
*if(新的路径更短)//新的路径就是经过当前位置的路径
{
把他的父亲设置为当前位置
}
else//什么也不做,哪怕是选中它了,那也无所谓,就忽略吊当前位置了
{
}
}
else //没有
{
* 让他的父亲是当前物体
* 重新计算F,G、
* 加入到开启列表
}
}*/
方块信息类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Point {
public Point Parent { get; set; }//地图信息
public float F { get; set; }
public float G { get; set; }
public float H { get; set; }
public int X { get; set; }
public int Y { get; set; }
public bool IsWall { get; set; }
public Point(int x,int y,Point parent=null)
{
this.X = x;
this.Y = y;
this.Parent = parent;
IsWall = false;
}
public void UpdateParent(Point parent,float g)
{
this.Parent = parent;
this.G = g;
F = G + H;
}
}
主代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class astart : MonoBehaviour {
private Point[,] map = new Point[8, 6];
private int mapWith = 8;//宽度
private int mapHeight = 6;//地图高度
void Start () {
InitMap();//初始化地图
Point start = map[2, 3];//开始位置
Point end = map[6,3];//结束位置
FindPath(start, end);//寻找路径
ShowPath(start,end);
}
// Update is called once per frame
void Update () {
}
private void InitMap()//构造地图
{
for(int x=0;x<mapWith;x++)
{
for(int y=0;y<mapHeight;y++)
{
map[x, y] = new Point(x, y);
}
}
map[4, 2].IsWall = true;//是障碍物
map[4, 3].IsWall = true;
map[4, 4].IsWall = true;
}
private void ShowPath(Point start, Point end)
{
Point temp = end;
while (true)
{
Debug.Log(temp.X + "," + temp.Y);
Color c = Color.gray;
if(temp==start)
{
c = Color.green;
}else if(temp==end)
{
c = Color.red;
}
CreateCube(temp.X, temp.Y, c);
if (temp.Parent == null)
{
break;
}
else
{
temp = temp.Parent;
}
for (int x = 0; x < mapWith; x++)
{
for (int y = 0; y < mapHeight; y++)
{
if(map[x,y].IsWall)
{
CreateCube(x, y, Color.blue);
}
}
}
}
}
private void FindPath(Point Start,Point End)
{
List<Point> openList = new List<Point>();//开启集合
List<Point> closeList = new List<Point>();//关闭集合
openList.Add(Start);//先把开始点加入开启集合
while(openList.Count>0)//知道为空结束循环
{
Point point = FindMinfPoint(openList);//取得f最小的点了
openList.Remove(point);//把这个点在开启集合移除
closeList.Add(point);//增加到关闭集合
List<Point> surround = GetSurroundPoints(point);//得到周围的集合
PointsFlter(surround,closeList);//过滤集合
foreach(Point surroundPoint in surround)
{
if(openList.IndexOf(surroundPoint)>-1)//如果存在
{
float nowG = CalcG(surroundPoint,point);//计算出新的G值
if(nowG<surroundPoint.G)//如果路径更短,就换掉他的父亲
{
surroundPoint.UpdateParent(point, nowG);
}
}
else
{
surroundPoint.Parent = point;
CalcF(surroundPoint, End);
openList.Add(surroundPoint);
}
}
if(openList.IndexOf(End)>-1)//如果目标在开启列表里面说明找到了
{
break;
}
}
}
private void PointsFlter(List<Point> scr,List<Point> close)//过滤集合
{
foreach(Point p in close)
{
if(scr.IndexOf(p)>-1)
{
scr.Remove(p);
}
}
}
private Point FindMinfPoint(List<Point> openList)//寻找最小的f值
{
float f = float.MaxValue;//先让他是最大值
Point temp=null;
foreach(Point p in openList)
{
if(p.F<f)
{
temp = p;//保存找打的位置和他的f值
f = p.F;
}
}
return temp;
}
private List<Point> GetSurroundPoints(Point point)//寻找周围的点
{
Point up = null, down = null, left = null, right = null;//存储当前方块上下左右的方块
Point lu = null, ru = null, ld = null, rd = null;
if (point.Y<mapHeight - 1)//说明方块不是在最上面
{
up = map[point.X, point.Y + 1];//得到上面的方块
}
if(point.Y>0)//说名方块不是在最下面
{
down = map[point.X, point.Y - 1];//得到下面的方块
}
if(point.X>0)
{
left = map[point.X -1, point.Y];//得到最左边的
}
if(point.X<mapWith-1)
{
right = map[point.X + 1, point.Y];//得到最右边的
}
if(up!=null&&left!=null)//如果上面和左面的不为空,则左上不为空
{
lu = map[point.X - 1, point.Y - 1];//左上
}
if(up!=null&&right!=null)
{
ru=map[point.X-1,point.Y+1];//右上
}
if (down != null && left != null)//如果上面和左面的不为空,则左上不为空
{
ld = map[point.X + 1, point.Y - 1];//
}
if (down != null && right != null)
{
rd = map[point.X + 1, point.Y + 1];//右下
}
List<Point> list = new List<Point>();//添加到list集合里面
if(down!=null&&down.IsWall==false)
{
list.Add(down);
}
if (up!= null && up.IsWall == false)
{
list.Add(up);
}
if (left != null && left.IsWall == false)
{
list.Add(left);
}
if (right != null && right.IsWall == false)
{
list.Add(right);
}
if(lu!=null&&lu.IsWall==false&&left.IsWall==false&&up.IsWall==false)
{
list.Add(lu);
}
if (ld != null && ld.IsWall == false && left.IsWall == false && down.IsWall == false)
{
list.Add(ld);
}
if (ru != null && ru.IsWall == false && right.IsWall == false && up.IsWall == false)
{
list.Add(ru);
}
if (rd != null && rd.IsWall == false && right.IsWall == false && down.IsWall == false)
{
list.Add(rd);
}
return list;
}
private float CalcG(Point now,Point parent)//计算G值
{
return Vector2.Distance(new Vector2(now.X, now.Y), new Vector2(parent.X,parent.Y)) + parent.G;//
}
private void CalcF(Point now, Point end)//计算F=G+H
{
float h = Mathf.Abs(end.X - now.X) + Mathf.Abs(end.Y - now.Y);
float g = 0;
if (now.Parent == null)
{
g = 0;
}
else
{
//他到父亲的距离加上父亲到开始点的距离
g = Vector2.Distance(new Vector2(now.X, now.Y), new Vector2(now.Parent.X, now.Parent.Y)) + now.Parent.G;//
}
float f = g + h;
now.F = f;
now.G = g;
now.H = h;
}
private void CreateCube(int x,int y,Color color)
{
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
go.transform.position = new Vector3(x, y, 0);
go.GetComponent<Renderer>().material.color = color;
}
}