unityA* 寻路算法,使用OnGUI()函数

A*(A-Star)算法是一种静态路网中求解最短路最有效的直接搜索方法。
注意是最有效的直接搜索算法。之后涌现了很多预处理算法(ALT,CH,HL等等),在线查询效率是A*算法的数千甚至上万倍。
公式表示为: f(n)=g(n)+h(n)
其中 f(n) 是从初始点经由节点n到目标点的估价函数,
g(n) 是在状态空间中从初始节点到n节点的实际代价,
h(n) 是从n到目标节点最佳路径的估计代价。
保证找到最短路径(最优解的)条件,关键在于估价函数f(n)的选取:
估价值h(n)<= n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。并且如果h(n)=d(n),即距离估计h(n)等于最短距离,那么搜索将严格沿着最短路径进行, 此时的搜索效率是最高的。
如果 估价值>实际值,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。



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

/// <summary>
/// 格子类型
/// </summary>
public enum GridType
{
    Normal,
    Obstacle,
    Start,
    End
}
/// <summary>
/// 为了实现格子的排序,继承ICompareable
/// </summary>
public class MapGrid:IComparable
{
    /// <summary>
    /// 记录坐标
    /// </summary>
    public int x;
    public int y;

    /// <summary>
    /// 总消耗
    /// </summary>
    public int f;
    /// <summary>
    /// 当前到起点的消耗
    /// </summary>
    public int g;
    //当前到终点的消耗
    public int h;

    public GridType type;
    /// <summary>
    /// 父节点
    /// </summary>
    public MapGrid fatherNode;

    /// <summary>
    /// 排序
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public int CompareTo(object obj)
    {
        MapGrid grid = (MapGrid)obj;
        if(this .f <grid .f)
        {
            //升序
            return -1;
        }
        if(this .f >grid .f)
        {
            //降序
            return 1;
        }
        return 0;
    }
}


public class AStar : MonoBehaviour {
    
    public int row = 5;
    public int col = 10;
    //格子大小
    public int size = 70;

    public MapGrid[,] grids;
    public ArrayList openList;
    public ArrayList closeList;

    //开始和结束的位置
    private int xStart = 2;
    private int yStart = 1;
    private int xEnd = 2;
    private int yEnd = 5;

    private Stack<string> fatherNodeLocation;

    void Init()
    {
        grids = new MapGrid[row, col];

        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < col; j++)
            {
                //初始化格子,记录格子的坐标
                grids[i, j] = new MapGrid();
                grids[i, j].x = i;
                grids[i, j].y = j;
            }
        }
        //开始点和其h的值
        grids[xStart, yStart].type = GridType.Start;
        grids[xStart, yStart].h = Manhatten(xStart, yStart);

        grids[xEnd, yEnd].type = GridType.End;

        fatherNodeLocation = new Stack<string>();

        for (int i = 1; i <= 3; i++)
        {
            grids[i, 3].type = GridType.Obstacle;
        }

        openList = new ArrayList();
        openList.Add(grids[xStart, yStart]);

        closeList = new ArrayList();
    }

    private int Manhatten(int x,int y)
    {
        return (int)(Math.Abs(xEnd - x) + Math.Abs(yEnd - y)) * 10;
    }

    void Start()
    {
        Init();
    }

    void DrawGrid()
    {
        for (int i = 0; i < row ; i++)
        {
            for (int j = 0; j < col ; j++)
            {
                Color color = Color.yellow;
                if(grids [i,j].type ==GridType .Start )
                {
                    color = Color.green;
                }
                else if(grids [i,j].type ==GridType .Start )
                {
                    color = Color.red;
                }
                else if (grids [i,j].type ==GridType .Obstacle )
                {
                    color = Color.blue;
                }
                else if(closeList .Contains (grids [i,j]))
                {
                    color = Color.yellow;
                }
                else
                {
                    color = Color.grey;
                }

                GUI.backgroundColor = color;
                GUI.Button(new Rect(j * size, i * size, size, size), FGH(grids[i, j]));
            }
        }
    }

    private string FGH(MapGrid grid)
    {
        string str = "F" + grid.f + "\n";
        str += "G" + grid.g + "\n";
        str += "H" + grid.h + "\n";
        str += "(" + grid.x + "," + grid.y + ")";
        return str;
    }

    void OnGUI()
    {
        DrawGrid();
        for (int i = 0; i < openList .Count ; i++)
        {
            GUI.Button(new Rect(i * size, (row + 1) * size, size, size), FGH((MapGrid)openList[i]));
        }

        for (int j = 0; j < closeList .Count ; j++)
        {
            GUI.Button(new Rect(j * size, (row + 1) * size, size, size), FGH((MapGrid)closeList[j]));
        }

        if(GUI .Button (new Rect (col *size ,size ,size ,size ),"next"))
        {
            NextStep();
        }
    }

    private void NextStep()
    {
        if (openList.Count == 0)
        {
            print("over !");
            return;
        }

        MapGrid grid=(MapGrid )openList [0];
        if(grid.type ==GridType .End )
        {
            print ("find");
            ShowFatherNode(grid);
            return ;
        }

        for (int i = -1; i <=1; i++)
        {
            for (int j = -1; j <=1; j++)
            {
                int x = grid.x + i;
                int y = grid.y + j;

                if(x>=0&&x<row &&y>=0&&y<col&&
                    grids [x,y].type !=GridType .Obstacle &&
                    !closeList .Contains (grids[x,y]))
                {
                    int g = grid.g + (int)(Math.Sqrt((Math.Abs(i) + Math.Abs(j))) * 10);
                    if(grids[x,y].g==0||grids [x,y].g>g)
                    {
                        grids[x, y].g = g;
                        grids[x, y].fatherNode = grid;
                    }

                    grids[x, y].h = Manhatten(x, y);
                    grids[x, y].f = grids[x, y].g + grids[x, y].h;

                    if(!openList .Contains (grids[x,y]))
                    {
                        openList.Add(grids[x, y]);
                    }

                    openList.Sort();
                }
            }
        }

        closeList.Add(grid);
        openList.Remove(grid);
    }

    private void ShowFatherNode(MapGrid grid)
    {
        if(grid.fatherNode !=null )
        {
            string str = grid.fatherNode.x + "," + grid.fatherNode.y;
            fatherNodeLocation.Push(str);
            ShowFatherNode(grid.fatherNode);
        }

        if(fatherNodeLocation .Count !=0)
        {
            print(fatherNodeLocation.Pop());
        }
    }
}



原文链接:点击打开链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值