Unity之A*算法

Astar.cs

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

public class Astar : MonoBehaviour {

    private const int mapWidth = 8;
    private const int mapHeight = 6;
    private Point[,] map = new Point[mapWidth, mapHeight];

	void Start () {
        InitMap();
        Point start = map[2, 3];
        Point end = map[6, 3];
        //测试
        //List list = GetSurroundPoints(map[3, 3]);
        //foreach(Point p  in list)
        //{
        //    Debug.Log(p.X + "- "+ p.Y);
        //}
        FindPath(start, end);
        ShowPath(start, end);
    }
	
    private void InitMap(){
        for(int x = 0; x < mapWidth; 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 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 = FindMinOfPoint(openList);
            openList.Remove(point);
            closeList.Add(point);
            List<Point> surroundPoints = GetSurroundPoints(point);
            PointFilter(surroundPoints, closeList);
            foreach(Point surroundPoint in surroundPoints)
            {
                if(openList.IndexOf(surroundPoint) > -1)
                {
                    float nowG = CalcG(surroundPoint, point);
                    if(nowG < surroundPoint.G)
                    {
                        surroundPoint.UpdateParent(surroundPoint, nowG);
                    }
                }
                else
                {
                    surroundPoint.Parent = point;
                    CalcF(surroundPoint, end);
                    openList.Add(surroundPoint);
                }
            }
            //判断end是否在列表中
            if(openList.IndexOf(end) != -1)
            {
                break;
            }
        }
    }

    private void ShowPath(Point start, Point end)
    {
        Point temp = end;
        Color c;
        Debug.Log(temp.Parent.X + "," + temp.Parent.Y);
        //while (true)
        //{
        //    //Debug.Log(temp.X + "," + temp.Y);
        //    if(temp == start)
        //    {
        //        c = Color.green;
        //    }else if(temp == end)
        //    {
        //        c = Color.red;
        //    }
        //    else
        //    {
        //        c = Color.gray;
        //    }
        //    CreateCube(temp.X, temp.Y, c);
        //    if (temp.Parent == null)
        //        break;
        //    temp = temp.Parent;
        //}
        for (int x = 0; x < mapWidth; x++)
        {
            for (int y = 0; y < mapHeight; y++)
            {
                if(map[x, y].IsWall)
                {
                    CreateCube(x, y, Color.blue);
                }
            }
        }
    }

    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;
    }

    //过滤
    private void PointFilter(List<Point> src, List<Point> closeList)
    {
        foreach(Point p in closeList)
        {
            if(src.IndexOf(p) != -1)
            {
                src.Remove(p);
            }
        }
    }
    private List<Point> GetSurroundPoints(Point point)
    {
        Point up = null, down = null, left = null, right = null, 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 < mapWidth - 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>();
        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 != null && left.IsWall == false && up != null && up.IsWall == false)
        {
            list.Add(lu);
        }
        if (ru != null && ru.IsWall == false && right != null && right.IsWall == false && up != null && up.IsWall == false)
        {
            list.Add(ru);
        }
        if (ld != null && ld.IsWall == false && left != null && left.IsWall == false && down != null && down.IsWall == false)
        {
            list.Add(ld);
        }
        if (rd != null && rd.IsWall == false && right != null && right.IsWall == false && down != null && down.IsWall == false)
        {
            list.Add(rd);
        }
        return list;

    }

    private Point FindMinOfPoint(List<Point> openList)
    {
        float f = float.MaxValue;
        Point temp = null;
        foreach(Point p in openList)
        {
            if(p.F < f)
            {
                temp = p;
                f = p.F;
            }
        }
        return temp;
    }

    private float CalcG(Point now, Point parent)
    {
        return Vector2.Distance(new Vector2(now.X, now.Y), new Vector2(parent.X, parent.Y)) + now.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;
    }
}

Point.cs

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;
    }
    public void UpdateParent(Point parent, float g)
    {
        this.Parent = parent;
        this.G = g;
        this.F = G + H;
    }
}

你可能感兴趣的:(算法,Unity3D)