C#实现A*算法

在游戏开发中,AI的最基本问题之一就是寻路算法或称路径规划算法,在三 年前,我曾实现过 基于“图算法”的最短路径规划算法,然而在游 戏中,我们通常将地图抽象为有单元格构成的矩形,如:

这个微型地图 由3*3的单元格构成,当然,实际游戏中的地图通常比它大很多,这里只是给出 一个示例。

由于游戏地图通常由单元格构成,所以,基于“图算法 ”的路径规划便不再那么适用,我们需要采用基于单元格的路径规划算法 。A*算法是如今游戏所采用的寻路算法中相当常用的一种算法,它可以保证在任 何起点和任何终点之间找到最佳的路径(如果存在的话),而且,A*算法相当有 效。

关于A*算法的原理的详细介绍,可以参考 这篇文章。当你明白A*算 法的原理之后,在来看接下来的A*算法的实现就会比较容易了。

现在, 让我们转入正题,看看如何在C#中实现A*算法。

首先,我们把地图划分 为单元格,如此,一个地图就可以由(M行*N列)个单元格构成。我们使用 AStarNode类来抽象单元格,表示一个节点,而节点的位置用Point表示,其X坐 标表示Column Index,Y坐标表示Line Index。AStarNode的定义如下:

Code

[copy to clipboard]CODE:

/// <summary>
  /// AStarNode 用于保存规划到当前节点时的各个 Cost值以及父节点。
  /// zhuweisky 2008.10.18
  /// </summary>
  public class AStarNode
  {
     #region Ctor
    public AStarNode(Point loc, AStarNode previous, int _costG, int _costH)
    {
       this.location = loc;
      this.previousNode = previous;
      this.costG = _costG;
      this.costH = _costH;
    }
    #endregion
    #region Location
    private Point location = new Point(0, 0);
    /// <summary>
    /// Location 节点所在的位置, 其X值代表ColumnIndex,Y值代表LineIndex
    /// </summary>
    public Point Location
    {
      get { return location; }
    }
     #endregion
    #region PreviousNode
    private AStarNode previousNode = null;
    /// <summary>
    /// PreviousNode 父节点,即是由哪个节点导航到当前节点的。
    /// </summary>
    public AStarNode PreviousNode
    {
      get { return previousNode; }
    }
    #endregion
     #region CostF
    /// <summary>
    /// CostF 从起点导航经过本节点然后再到目的节点的估算总代价。
    /// </summary>
    public int CostF
    {
       get
      {
        return this.costG + this.costH;
      }
    }
     #endregion
    #region CostG
    private int costG = 0;
    /// <summary>
    /// CostG 从起点导 航到本节点的代价。
    /// </summary>
     public int CostG
    {
      get { return costG; }
    }
    #endregion
    #region CostH
    private int costH = 0;
    /// <summary>
    /// CostH 使用启发式方法估算的从本节点到目的节点的代价。
    /// </summary>
    public int CostH
     {
      get { return costH; }
    }
     #endregion
    #region ResetPreviousNode
    /// <summary>
    /// ResetPreviousNode 当从起点到达本节点 有更优的路径时,调用该方法采用更优的路径。
    /// </summary>
    public void ResetPreviousNode(AStarNode previous, int _costG)
    {
       this.previousNode = previous;
      this.costG = _costG;
    }
    #endregion
    public override string ToString()
    {
      return this.location.ToString();
    }
  }

时间: 2024-12-04 01:30:14

C#实现A*算法的相关文章

python实现马耳可夫链算法实例分析

  本文实例讲述了python实现马耳可夫链算法的方法.分享给大家供大家参考.具体分析如下: 在<程序设计实践>(英文名<The Practice of Programming>)的书中,第三章分别用C语言,C++,AWK和Perl分别实现了马耳可夫链算法,来通过输入的文本,"随机"的生成一些有用的文本. 说明: 1. 程序使用了字典,字典和散列可不是一个东西,字典是键值对的集合,而散列是一种能够常数阶插入,删除,不过可以用散列来实现字典. 2. 字典的setd

php-perl哈希算法实现

 php-perl哈希实现算法–DJBX33A(Daniel J. Bernstein, Times 33 with Addition)APR哈希默认算法  代码如下: APR_DECLARE_NONSTD(unsigned int) apr_hashfunc_default(const char *char_key,                                                       apr_ssize_t *klen) {     unsigned i

openssl使用DSA算法生成签名

  命令: openssl> dgst -dss1 -sign C.pri -out signature.bin s.txt 解释 C.pri是DSA算法生成的私钥文件 s.txt是制作签名的原文 signature.bin是生成的签名文件 php中可以使用下面的方法察看签名内容  代码如下   <?php echo bin2hex(file_get_contents('signature.bin')); ?> 参考内容 消息摘要算法 支持的算法包括:MD2, MD4, MD5, MDC

求按百分比抽取数据算法

问题描述 求按百分比抽取数据算法 我有个需求 要求用百分比抽取数据以达到数据审阅的目的 我做了一个简单的程序但达不到要求 <?php header('Content-Type: text/html; charset=utf-8'); //抽取算法 for($kou=1;$kou<=100;$kou++){ $kou_count=0; for($i=1;$i<=100;$i++){ $key=($i)%(100/$kou); if( intval( $key ) == 0){ //echo

请教各位算法大神,acm一道题:赋权无向图的最小权值遍历用什么算法(存在负权值)?

问题描述 请教各位算法大神,acm一道题:赋权无向图的最小权值遍历用什么算法(存在负权值)? 1C 如题,问题是这样的:有一赋权无向连通图,可以从任意一结点出发,求遍历所有结点的最小权值路线.结束点也是任意的,每个节点也没有访问次数的限制,但必须每个节点都要被访问到.,想问一下用什么算法呢? 解决方案 可以参考djstera算法,求最短路径~借鉴其中的标记功能,只不过结束状态标志是所有节点均已遍历. 解决方案二: 可以参考djstera算法,求最短路径~借鉴其中的标记功能,只不过结束状态标志是所

RSA算法介绍

2.1.1     算法实现 首先, 找出三个数, p, q, r,其中 p, q 是两个相异的质数, r 是与 (p-1)(q-1) 互质的数.p, q, r 这三个数便是 private key 接著, 找出 m, 使得 rm == 1 mod (p-1)(q-1) 这个 m 一定存在, 因为 r 与 (p-1)(q-1) 互质, 用辗转相除法就可以得到了 再来, 计算 n = pq m, n 这两个数便是 public key 编码过程是, 若资料为 a, 将其看成是一个大整数, 假设 a

PHP 四种基本排序算法的代码实现(1)

许多人都说算法是程序的核心,算法的好坏决定了程序的质量.作为一个初级phper,虽然很少接触到算法方面的东西.但是对于基本的排序算法还是应该掌握的,它是程序开发的必备工具.这里介绍冒泡排序,插入排序,选择排序,快速排序四种基本算法,分析一下算法的思路. 前提:分别用冒泡排序法,快速排序法,选择排序法,插入排序法将下面数组中的值按照从小到大的顺序进行排序. $arr(1,43,54,62,21,66,32,78,36,76,39); 1. 冒泡排序 思路分析:在要排序的一组数中,对当前还未排好的序

二叉树遍历算法之一:前序遍历

递归实现前序遍历 二叉树的前序遍历是指从根节点出发,按照先根节点,再左子树,后右子树的方法遍历二叉树中的所有节点,使得每个节点都被访问一次. 当调用遍历算法的时候前序遍历的具体过程如下: 首先访问根节点,如果根节点不为空,执行输出语句,打印根节点的值. 如果左子树不为空,则访问根节点的左孩子,并输出根节点做孩子的值 继续访问根节点的左孩子的左孩子,如果不为空则继续输出该左孩子的值: 如果这时左孩子为空,说明该节点是叶子节点,则按照先左孩子后右孩子的访问方式访问其左右孩子,如果不为空就打印输出 左

图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用

图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 B(G).其中 T(G)是遍历图时所经过的边的集合,B(G) 是遍历图时未经过的边的集合.显然,G1(V, T) 是图 G 的极小连通子图,即子图G1 是连通图 G 的生成树. 深度优先生成森林   右边的是深度优先生成森林: 连通图的生成树不一定是唯一的,不同的遍历图的方法得到不同的生成树;从不

不用递归实现论坛树型结构的算法

递归|树型结构|算法 <jsp:useBean id="mybbs" scope="session" class="netzero.mydb" /> <%@ page contentType="text/html;charset=gb2312" %> <%@ page import="java.io.*" %> <%@ page import="java.