A* 寻路不采用最短路径

2024-03-02

我的 A* 寻路功能总是能到达预期目的地,但它几乎总是有点偏离路线。这是一个例子:

[我制作了一张漂亮的图片来展示我的问题,但显然直到我的声誉达到 10 后它才会发布;抱歉,我是新人。 :P]

本质上,它会尽可能向左或向上拉动,而不实际向路径添加更多图块。这听起来像是计算 gScore 的问题,或者可能是可以根据相邻图块的 gScore 重新分配图块的父级的部分,但我只是无法弄清楚哪里出了问题。我已经梳理了我的代码数周并浏览了数十篇在线帖子,但我仍然陷入困境。仅供参考,我必须使用的编译器/调试器不支持断点或逐步调试,因此我只能使用简单的文本输出。谁能发现我做错了什么吗?

这是主要功能(注:这都是Angelscript中的。它基于C++,但有一些细微的差别):

    int CARDINAL_COST = 10;
int DIAGONAL_COST = 14;    
array<vector2> findPath(vector2 startPosition, vector2 endPosition)
{
    //Translate the start and end positions into grid coordinates
    startPosition = _level.getTileGridPosition(startPosition);
    endPosition = _level.getTileGridPosition(endPosition);

    //The path to be returned
    array<vector2> path(0);

    //Create the closed
    array<vector2> closedSet(0);

    //Create the open set. These are nodes to be considered.
    array<vector2> openSet(0);
    //Add the startPosition to the open set.
    openSet.insertLast(startPosition);

    //Create the cameFrom (path) array. Each entry hods that tile's parent tile.
    array<array<vector2>> cameFrom;
    cameFrom = array<array<vector2>>(_level.width(), array<vector2>(_level.height()));

    //Create the gScore array. gScore is the cost to get from the start to the current tile.
    array<array<int>> gScore;
    gScore = array<array<int>>(_level.width(), array<int>(_level.height()));
    //Set the start position score to 0
    gScore[startPosition.x][startPosition.y] = 0;

    //Create the fScore array. fScore is the gScore + heuristic cost.
    array<array<int>> fScore;
    fScore = array<array<int>>(_level.width(), array<int>(_level.height()));
    //Set the start position score to the estimated (heuristic) cost.
    //gScore for start is 0, so that's not included in the equation.
    fScore[startPosition.x][startPosition.y] = getHeuristicCost(startPosition, endPosition);

    //Required variables
    bool searchComplete = false;
    vector2 currentTile = startPosition;
    int x = 0;
    int y = 0;
    string tileType = "";
    vector2 nextTile(0,0);
    vector2 neighborTile(0,0);
    int lowestScore = 0;
    int tempScore = 0;
    int index = 0;

    while(!searchComplete)
    {


        //Find the tile in the openSet with the lowest fScore.
        lowestScore = fScore[openSet[0].x][openSet[0].y];
        neighborTile = openSet[0];//May not actually be a "neighbor" in this case, just looking for the lowest fScore.

        for(int i = 0; i < openSet.length(); i++)
        {
            if(fScore[neighborTile.x][neighborTile.y] < lowestScore || i == 0)
            {
                lowestScore = fScore[neighborTile.x][neighborTile.y];
                nextTile.x = neighborTile.x;
                nextTile.y = neighborTile.y;
            }
        }

        //Drop the "nextTile" from the openSet and add it to the closedSet
        index = openSet.find(nextTile);
        openSet.removeAt(openSet.find(nextTile));
        closedSet.insertLast(nextTile);

        //Set the currentTile
        currentTile = nextTile;

        //Get the fScore for each neighboring tile
        for(x = currentTile.x - 1; x <= currentTile.x + 1; x++)
        {
            for(y = currentTile.y - 1; y <= currentTile.y + 1; y++)
            {
                //Safety: make sure x and y aren't out of bounds
                if(x < 0)
                    x = 0;
                else if(x > _level.width())
                    x = _level.width();

                if(y < 0)
                    y = 0;
                else if (y > _level.height())
                    y = _level.height();

                //Set this x,y pair to be the neighborTile
                neighborTile.x = x;
                neighborTile.y = y;

                //Get the tile type
                if(_level.tileArray()[neighborTile.x][neighborTile.y] != null)
                    tileType = _level.tileArray()[neighborTile.x][neighborTile.y].GetString("type");
                else
                    tileType = "";

                //Make sure we aren't looking at the current tile, the tile is not closed, and the tile is a floor or door.
                if(neighborTile != currentTile && closedSet.find(neighborTile) == -1 && (tileType == "floor" || tileType == "door"))
                {
                    //If the neighboring tile is already in the open set, check to see if the currentTile's gScore would be less if that tile was its parent.
                    //If it is, set the it as the currentTile's parent and reset the fScore and gScore for it.
                    if(openSet.find(neighborTile) != -1)
                    {                           
                        if(gScore[neighborTile.x][neighborTile.y] < gScore[cameFrom[currentTile.x][currentTile.y].x][cameFrom[currentTile.x][currentTile.y].y])
                        {
                            cameFrom[currentTile.x][currentTile.y] = neighborTile;

                            //If the tile is a diagonal move
                            if(neighborTile.x - currentTile.x != 0 && neighborTile.y - currentTile.y != 0)
                                gScore[currentTile.x][currentTile.y] = gScore[neighborTile.x][neighborTile.y] + DIAGONAL_COST;
                            else//If the tile is a cardinal (N,S,E,W) move
                                gScore[currentTile.x][currentTile.y] = gScore[neighborTile.x][neighborTile.y] + CARDINAL_COST;

                            fScore[currentTile.x][currentTile.y] = gScore[currentTile.x][currentTile.y] + getHeuristicCost(currentTile, endPosition);
                        }
                    }
                    else//Add this tile to the open set
                    {
                        openSet.insertLast(neighborTile);

                        //Record this tile's parent
                        cameFrom[neighborTile.x][neighborTile.y] = currentTile;

                        //If the tile is a diagonal move
                        if(neighborTile.x - currentTile.x != 0 && neighborTile.y - currentTile.y != 0)
                            gScore[neighborTile.x][neighborTile.y] = gScore[currentTile.x][currentTile.y] + DIAGONAL_COST;
                        else//If the tile is a cardinal (N,S,E,W) move
                            gScore[neighborTile.x][neighborTile.y] = gScore[currentTile.x][currentTile.y] + CARDINAL_COST;

                        //Get the fScore for this tile
                        fScore[neighborTile.x][neighborTile.y] = gScore[neighborTile.x][neighborTile.y] + getHeuristicCost(neighborTile, endPosition);
                    }

                }
            }
        }


        //Check to see if we have arrived at the endTile
        if(currentTile == endPosition)
        {
            searchComplete = true;
            path = reconstructPath(cameFrom, startPosition, endPosition);
        }
        else
        {
            //Check to see if the openSet is empty
            if(openSet.length() == 0)
                searchComplete = true;
        }   

    }//while(!searchComplete)

    return path;
}

我的启发式使用曼哈顿方法:

    int getHeuristicCost(vector2 startPosition, vector2 endPosition)
{
    //Using Manhattan method:
    int x = abs(startPosition.x - endPosition.x)*10;
    int y = abs(startPosition.y - endPosition.y)*10;

    return x+y;
}

最后,这是我的路径重建函数:

    array<vector2> reconstructPath(array<array<vector2>> &in cameFrom, vector2 &in startPosition, vector2 &in endPosition)
{       
    //Start by adding in the end position
    array<vector2> totalPath(1);
    vector2 currentTile = endPosition;
    totalPath[0] = endPosition;

    int x = endPosition.x;
    int y = endPosition.y;
    int angle = 0;
    while(vector2(x, y) != startPosition)
    {           
        currentTile = cameFrom[x][y];
        totalPath.insertAt(0,currentTile);
        x = currentTile.x;
        y = currentTile.y;
    }

    return totalPath;
}

    for(int i = 0; i < openSet.length(); i++)
    {
        if(fScore[neighborTile.x][neighborTile.y] < lowestScore || i == 0)
        {
            lowestScore = fScore[neighborTile.x][neighborTile.y];
            nextTile.x = neighborTile.x;
            nextTile.y = neighborTile.y;
        }
    }

这个循环只是看neighborTile一遍又一遍。您是否想回顾一下以下元素openSet?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

A* 寻路不采用最短路径 的相关文章

  • 为什么存在 async 关键字

    浏览 msdn 9 频道视频时 我发现以下未答复的评论 希望有人能解释一下 我不明白 async 关键字的意义 为什么不直接允许 任何时候方法返回任务时都会使用await关键字 就像迭代器一样 可以在任何返回 IEnumerable 的方法
  • 通过增加索引之和来生成排序组合的有效方法

    对于启发式算法 我需要一个接一个地评估特定集合的组合 直到达到停止标准 由于它们很多 目前我正在使用以下内存高效迭代器块生成它们 受到 python 的启发 itertools combinations http docs python o
  • clang 格式换行符在错误的位置

    给出以下代码行 get abc manager get platform status abc platform status sw update status fill update status actions allowed stat
  • 在 VS2017 下使用 Conan 和 CMake 项目进行依赖管理

    我正在尝试使用 CMake 与 VS2017 集成为 C 设置一个开发环境 以便在 Linux x64 下进行编译 为了更好地管理依赖关系 我选择使用 Conan 但我对这个软件还很陌生 我想知道让 VS2017 识别项目依赖关系的最佳方法
  • 如何使用 zlib 制作 .zip 文件

    我正在阅读zlib的文档 它相当详细 但我读到了这一行 输出数据将位于zlib格式 与 gzip 或zip formats http www zlib net zlib how html http www zlib net zlib how
  • 将字节数组转换为托管结构

    更新 这个问题的答案帮助我编写了开源项目GitHub 上的 AlicanC 现代战争 2 工具 https github com AlicanC AlicanC s Modern Warfare 2 Tool 你可以看到我是如何阅读这些数据
  • C 程序从连接到系统的 USB 设备读取数据

    我正在尝试从连接到系统 USB 端口的 USB 设备 例如随身碟 获取数据 在这里 我可以打开设备文件并读取一些随机原始数据 但我想获取像 minicom teraterm 这样的数据 请让我知道我可以使用哪些方法和库来成功完成此操作以及如
  • ASP.NET Core 与现有的 IoC 容器和环境?

    我想运行ASP NET 核心网络堆栈以及MVC在已托管现有应用程序的 Windows 服务环境中 以便为其提供前端 该应用程序使用 Autofac 来处理 DI 问题 这很好 因为它已经有一个扩展Microsoft Extensions D
  • mprotect 之后 malloc 导致分段错误

    在使用 mprotect 保护内存区域后第一次调用 malloc 时 我遇到分段错误 这是执行内存分配和保护的代码片段 define PAGESIZE 4096 void paalloc int size Allocates and ali
  • 无法解析远程名称 - webclient

    我面临这个错误 The remote name could not be resolved russgates85 001 site1 smarterasp net 当我请求使用 Web 客户端读取 html 内容时 出现错误 下面是我的代
  • TcpClient 在异步读取期间断开连接

    我有几个关于完成 tcp 连接的问题 客户端使用 Tcp 连接到我的服务器 在接受客户端后listener BeginAcceptTcpClient ConnectionEstabilishedCallback null 我开始阅读netw
  • libxml2 xmlChar * 到 std::wstring

    libxml2似乎将所有字符串存储在 UTF 8 中 如xmlChar xmlChar This is a basic byte in an UTF 8 encoded string It s unsigned allowing to pi
  • 使用 WF 的多线程应用程序的错误处理模式?

    我正在写一个又长又详细的问题 但只是放弃了它 转而选择一个更简单的问题 但我在这里找不到答案 应用程序简要说明 我有一个 WPF 应用程序 它生成多个线程 每个线程执行自己的 WF 处理线程和 WF 中的错误 允许用户从 GUI 端进行交互
  • C++ 错误 - “成员初始值设定项表达式列表被视为复合表达式”

    我收到一个我不熟悉的 C 编译器错误 可能是一个非常愚蠢的错误 但我不能完全指出它 Error test cpp 27 error member initializer expression list treated as compound
  • WPF。如何从另一个窗口隐藏/显示主窗口

    我有两个窗口 MainWindow 和 Login 显示登录的按钮位于主窗口 this Hide Login li new Login li Show 登录窗口上有一个检查密码的按钮 如果密码正确 我如何显示主窗口 将参数传递给 MainW
  • ASP.NET JQuery AJAX POST 返回数据,但在 401 响应内

    我的应用程序中有一个网页 需要调用我设置的 Web 服务来返回对象列表 这个调用是这样设置的 document ready function var response ajax type POST contentType applicati
  • 使用 iTextSharp 5.3.3 和 USB 令牌签署 PDF

    我是 iTextSharp 和 StackOverFlow 的新手 我正在尝试使用外部 USB 令牌在 C 中签署 PDF 我尝试使用从互联网上挖掘的以下代码 Org BouncyCastle X509 X509CertificatePar
  • C语言声明数组没有初始大小

    编写一个程序来操纵温度详细信息 如下所示 输入要计算的天数 主功能 输入摄氏度温度 输入功能 将温度从摄氏度转换为华氏度 独立功能 查找华氏度的平均温度 我怎样才能在没有数组初始大小的情况下制作这个程序 include
  • 服务器响应 PASV 命令返回的地址与建立 FTP 连接的地址不同

    System Net WebException 服务器响应 PASV 命令返回的地址与建立 FTP 连接的地址不同 在 System Net FtpWebRequest CheckError 在 System Net FtpWebReque
  • 如何使用 C# 以低分辨率形式提供高分辨率图像

    尝试使用 300dpi tif 图像在网络上显示 目前 当用户上传图像时 我正在动态创建缩略图 如果创建的页面引用宽度为 500x500px 的高分辨率图像 我可以使用相同的功能即时转换为 gif jpg 吗 将创建的 jpg 的即将分辨率

随机推荐

  • 在 django 中使用 pika 的 Rabbitmq 监听器

    我有一个 django 应用程序 我想使用来自rabbit mq 的消息 我希望监听器在启动 django 服务器时开始使用 我正在使用 pika 库连接到rabbitmq 提供一些代码示例确实会有帮助 首先 您需要在 django 项目开
  • Chrome 扩展程序:无法加载 JavaScript 文件

    我发布了有关我的 Chrome 扩展程序的另一个问题here https stackoverflow com questions 28303597 tumblr dashboard modifications per chrome exte
  • 使用 apply 函数填充 NA 矩阵

    我想使用 apply 函数填充一个空矩阵 例如我的目的是简化下面的代码 tmp lt matrix NA 10 10 tmp 1 lt sample 1 500 10 tmp 2 lt sample 1 500 10 tmp 10 lt s
  • 在 PHP 中获取 SCOPE_IDENTITY()

    一直在尝试获取 SCOPE IDENTITY 插入数据库的最后一个 ID 并将其作为变量存储在我的 PHP 函数中 看了我在 stackoverflow 上可能找到的所有答案 但我仍然没有找到答案 这就是我目前所拥有的 Confirm bo
  • 创建现有 SOAP Web 服务的 REST 包装器

    我有一个 NET Web 服务 它是一个 SOAP 服务 我想将其转换为 REST 服务 我必须使用哪些选项来创建该中间件才能 接受请求并致电肥皂服务 翻译 SOAP 服务返回的结果 将响应返回给请求者 你有两个选择 1 只需创建一个具有两
  • 仅协议方案支持跨源请求,我该怎么办?

    我无法向 php 发送信息 它被阻止了 仅协议方案支持跨源请求 http data chrome chrome extension https 我使用了不同的 只有三分之一的电脑可以使代码工作 document on ready funct
  • Azure 服务总线主题分区

    我正在尝试向使用两者创建的主题发送消息启用重复检测 and 启用分区选项已选中 我不设置SessionId and PartitionKey我的属性BrokeredMessage实例 根据this https learn microsoft
  • 在 Android 中使用 AES/CBC/PKCS5Padding 解密不正确

    我在 Android v2 2 API 8 中编写了以下代码 其中输入纯文本 代码使用用户密码和随机盐对其进行加密 然后解密 运行代码后 我只得到部分正确的纯文本 例如用户输入 Msg 1 5 to encrypt 解密结果为 Msg15t
  • 将字节数组解码为Java中已压缩的位图

    我按以下方式压缩位图 Bitmap bmpSig getMyBitMap int size bmpSig getWidth bmpSig getHeight ByteArrayOutputStream out new ByteArrayOu
  • 如何在 dart 中创建安全的 http 服务器?

    我正在尝试将 dart http 服务器设置为仅使用 https 运行 所以我认为我需要使用HttpServer bindSecure https api dartlang org apidocs channels stable dartd
  • 在 shell 中导出函数

    请告诉我如何在父 shell bash sh 或 ksh 中导出函数 以便该函数可供从父进程启动的所有子进程使用 The export fBash 特有的功能 parent bin bash plus1 echo 1 1 echo plus
  • 无法在 Windows 计算机上安装 sasl-0.1.3 python 包

    我正在尝试在 Windows 7 64 位机器 上安装 sasl 0 1 3 python 包 它出现 C1083 致命错误 看起来 saslwrapper cpp 无法在 c 模块中包含 sasl sasl h 库 请帮助我解决问题 如果
  • boost::32 和 64 位进程之间的进程间共享内存

    我试图让 boost interprocess 在 32 位和 64 位进程之间共享内存 此错误跟踪器条目 https svn boost org trac boost ticket 5230表明这在我使用的 Boost 1 49 中可能是
  • 在模板中表达左移或右移的优雅方式

    我目前有一个模板函数 根据其模板参数 A 和 B 可以向左或向右移动值 template
  • 以编程方式设置 MailItem 的后续标志来完成?

    我试图找出如何在 Outlook 2007 中通过 VBA 将 MailItem 的后续标志设置为完成 谷歌搜索返回了大量在 Outlook 2003 及之前版本中有效的方法 例如 更改 MailItem 的 FlagStatus 属性的值
  • 如何处理静态存储持续时间警告?

    我是一个试图从书本上学习 C 的新手 下面的代码可以正常工作并产生预期的输出 但是定义的两行有警告engine and randomInt 使用静态存储持续时间初始化 引擎 可能会引发无法捕获的异常 如果我将第 7 行和第 8 行放在mai
  • .NET 错误关闭串口 BaseStream 错误仅在端口打开时出现

    我正在使用 NET System IO Ports SerialPort 并按照本文中的建议使用 BaseStreamIf you must使用 NET System IO Ports SerialPort http www sparxen
  • 对角块矩阵行之间的组合列表

    我有以下 R 矩阵 它是 2x3 和 3x3 子矩阵的组合 它可以是 2 个以上具有不同维度的子矩阵 例如 m1xp 和 m2xp 和 m3xp 其中 m1 m2 m3 A2 lt list rbind c 1 1 1 c 1 1 1 rb
  • 曲面细分的理论和算法

    我有以下问题 以下是我在屏幕上绘制立方体的方法 void drawCube glClear GL COLOR BUFFER BIT GL DEPTH BUFFER BIT Clear color and depth buffers glPu
  • A* 寻路不采用最短路径

    我的 A 寻路功能总是能到达预期目的地 但它几乎总是有点偏离路线 这是一个例子 我制作了一张漂亮的图片来展示我的问题 但显然直到我的声誉达到 10 后它才会发布 抱歉 我是新人 P 本质上 它会尽可能向左或向上拉动 而不实际向路径添加更多图