A*寻路之旅:用SDL图形化演示

这篇具有很好参考价值的文章主要介绍了A*寻路之旅:用SDL图形化演示。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

欢迎来到小K的数据结构专栏的第十小节,本节将为大家带来A*寻路算法的图形化详解,学了之后寻路不再迷路(✨当然也为大家准备了完整的源码 )~希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🐾

效果如下:

A*寻路算法图形化演示



一、简单介绍

由来
在 A * 算法之前有一种基于启发式探索的方法来提高Dijkstra算法的速度,这个算法叫做A1。后来的改进算法被称为A * 。 * 这个符号是从统计文献中借鉴来的,用来表示相对一个旧有标准的最优估计

启发式探索是利用问题拥有的启发信息来引导搜索,达到减少探索范围,降低问题复杂度的目的

✨A*寻路算法就是启发式探索的一个典型实践,在寻路的过程中,给每个节点绑定了一个估计值(即启发式),在对节点的遍历过程中是采取估计值优先原则,估计值更优的节点会被优先遍历。所以估计函数的定义十分重要,显著影响算法效率。
A*寻路之旅:用SDL图形化演示

那么在上图中我们应该怎么评估出最短路径呐既然要评估,那肯定要有评估规则了,首先明确三个概念,H值,目前点到终点的曼哈顿距离(曼哈顿距离,就是两个位置长度差值和高度差值的和),G值,目前点到起点的消耗代价值,如果只是寻找路径,可以将该值也看成是这两点的曼哈顿距离,F值,H值和G值的和。所以A*寻路算法的评估由公示F=G+H来评估

✨我们先来尝试一下,假设每个格子的直线代价为10,斜线代价为14,则我们评估的起点周围的八个点的代价如下图所示:

A*寻路之旅:用SDL图形化演示

怎么算的呐?我们以(2,2)为例,它到终点的曼哈顿距离我用黄色的矩形框起来了,横4纵4,然后乘上直线代价10,所以H为80,G一眼就可以看出,只有一个斜线代价,所以F为94

二、主要思想

在简单了解了A * 寻路算法了,我们不由得想,该怎么来寻?该用什么数据结构来描述?

  • ✨该怎么来寻?这个问题其实上边已经给出答案了,用F=G+H来评估,在这之前我们需要一个点类型,H比较好求,我们计算出当前点和终点之间的横纵坐标差,然后相加,乘上直线代价就好了,G值呐?我们通过下面的八叉树类型来解决~

    typedef struct Mypos 
    {
    	int row, col;
    	int f, g, h;
    }Mypos;
    //计算H值
    int getH(Mypos* pos, Mypos* endPos)
    {
        int x = ((pos->row > endPos->row) ? (pos->row - endPos->row) : (endPos->row - pos->row));
        int y = ((pos->col > endPos->col) ? (pos->col - endPos->col) : (endPos->col - pos->col));
        return (x + y) * ZXDJ;
    }
    
  • ✨该用什么数据结构?我首先想到的是八叉树,因为每个点周围都有八个点需要试探,下面是一个八叉树类型

    typedef struct MythreeNode 
    {
    	Mypos pos;                                     //点
    	struct MythreeNode* child[CHILD_NUM];          //孩子节点
    	struct MythreeNode* partent;                   //父节点
    	int child_Num;                                  //当前孩子数量
    }MythreeNode;
    
  • ✨具体的寻路过程如下

A*寻路之旅:用SDL图形化演示

第一步,先遍历周围的八个节点,把他们的斜线代价计算出来

第二步,判断能不能走,能走就计算出F,存入树和数组中,不能走直接把该孩子删掉

第三步,从buffer数组中找到最小的F值,走,然后用辅助地图标记走过

第四步,我们要判断找没找到终点,退出循环有两种情况,要么是找到终点了,要么是buffer数组为空了

上述步骤中有一个小问题,就是如果遇到死胡同问题怎么办?比如下图:

A*寻路之旅:用SDL图形化演示

第一步直接走到黄色的圈圈了,发现没路了,怎么办?我们思路回退一下,如果我们走完buffer数组中最小的,再把最小的删了不就可以了,这样下一步就会回到起点,这个问题就解决了

三、附上源码

✨A.h

#ifndef _A_H_
#define _A_H_
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
#include<assert.h>
#include<SDL.h>
//行列
#define ROWS 10
#define COLS 10
//代价
#define ZXDJ 10
#define XXDJ 14
//最大孩子数量
#define CHILD_NUM 8
//临时数组容量
#define NUMS_SIZE 1024
//路
enum type { road, wall };
//方向
enum Mydirect { p_up, p_down, p_left, p_right, p_upleft, p_upright, p_downleft, p_downright };
//点类型
typedef struct Mypos 
{
	int row, col;
	int f, g, h;
}Mypos;
//八叉树类型
typedef struct MythreeNode 
{
	Mypos pos;                                     //点
	struct MythreeNode* child[CHILD_NUM];          //孩子节点
	struct MythreeNode* partent;                   //父节点
	int child_Num;                                  //当前孩子数量
}MythreeNode;
//获得H值
int getH(Mypos* pos, Mypos* endPos);
//创建八叉树节点
MythreeNode* create_ThreeNode(Mypos* pos);
//判断能不能走
bool Can_Walk(Mypos* pos, bool map[ROWS][COLS], bool Pathmap[ROWS][COLS]);
//加载图片
SDL_Texture* load_BMP(SDL_Renderer* Ren, const char* fillname);
//绘图
void draw_Map(bool map[ROWS][COLS], Mypos* pos, SDL_Renderer* Ren, SDL_Texture** tex);

#endif // _A_H_


✨A.c

#include "A.h"

int getH(Mypos* pos, Mypos* endPos)
{
    int x = ((pos->row > endPos->row) ? (pos->row - endPos->row) : (endPos->row - pos->row));
    int y = ((pos->col > endPos->col) ? (pos->col - endPos->col) : (endPos->col - pos->col));
    return (x + y) * ZXDJ;
}

MythreeNode* create_ThreeNode(Mypos* pos)
{
    MythreeNode* newNode = (MythreeNode*)malloc(sizeof(MythreeNode));
    if (NULL == newNode) return newNode;
    memset(newNode, 0, sizeof(MythreeNode));
    newNode->pos.row = pos->row;
    newNode->pos.col = pos->col;
    newNode->pos.g = pos->g;
    return newNode;
}

bool Can_Walk(Mypos* pos, bool map[ROWS][COLS], bool Pathmap[ROWS][COLS])
{
    //越界
    if (pos->row < 0 || pos->row >= ROWS || pos->col < 0 || pos->col >= ROWS) return false;
    //是墙
    if (map[pos->row][pos->col]) return false;
    //走过
    if (Pathmap[pos->row][pos->col]) return false;
    return true;
}

SDL_Texture* load_BMP(SDL_Renderer* Ren, const char* fillname)
{
    SDL_Surface* sfc = SDL_LoadBMP(fillname);
    if (!sfc)
    {
        SDL_Log("sfc filed %s", SDL_GetError());
        return NULL;
    }
    SDL_Texture* tex = SDL_CreateTextureFromSurface(Ren, sfc);
    if (!tex)
    {
        SDL_Log("tex failed %s", SDL_GetError());
        SDL_FreeSurface(sfc);
        return NULL;
    }
    SDL_FreeSurface(sfc);
    return tex;
}

void draw_Map(bool map[ROWS][COLS], Mypos* pos,SDL_Renderer* Ren,SDL_Texture** tex)
{
    for (int i = 0; i < ROWS; i++)
    {
        for (int j = 0; j < COLS; j++) 
        {
            SDL_Rect rect = { j * 64,i * 64,64,64 };

            if (!map[i][j])
            {
                SDL_RenderCopy(Ren, tex[2], NULL, &rect);
            }
            else if (map[i][j])
            {
                SDL_RenderCopy(Ren, tex[3], NULL, &rect);
            }
            if (pos->row == i && pos->col == j) 
            {
                SDL_RenderCopy(Ren, tex[0], NULL, &rect);
            }
           if (7 == i && 6 == j)
           {
               SDL_RenderCopy(Ren, tex[1], NULL, &rect);
           }

        }
    }
}

✨main.c

A*寻路之旅:用SDL图形化演示

四、总结

本节讲解的数据结构——A*寻路算法,他不仅是一种算法思想,它还是路径规划,游戏中普通人物挂机状态的寻路的灵魂,所以它是值得我们花费时间去掌握的~下节见!文章来源地址https://www.toymoban.com/news/detail-468005.html

到了这里,关于A*寻路之旅:用SDL图形化演示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • CAD处理控件Aspose.CAD功能演示:在 C#中以编程方式搜索 DWG 图形文件中的文本

    Aspose.CAD 是一个独立的类库,以加强 Java应用程序处理和渲染CAD图纸,而不需要AutoCAD或任何其他渲染工作流程。该CAD类库允许将DWG, DWT, DWF, DWFX, IFC, PLT, DGN, OBJ, STL, IGES, CFF2文件、布局和图层高质量地转换为PDF和光栅图像格式。 Aspose API支持流行文件格式处理,并

    2024年02月04日
    浏览(47)
  • 【Python自然语言处理+tkinter图形化界面】实现智能医疗客服问答机器人实战(附源码、数据集、演示 超详细)

    需要源码和数据集请点赞关注收藏后评论区留言私信~~~ QA问答是Question-and-Answer的缩写,根据用户提出的问题检索答案,并用用户可以理解的自然语言回答用户,问答型客服注重一问一答处理,侧重知识的推理。 从应用领域视角,可将问答系统分为限定域问答系统和开放域问

    2023年04月12日
    浏览(67)
  • 性能优化3-分帧寻路+寻路任务统一管理

    当项目里的地图越来越大,一些性能上的问题开始逐渐出现,比如寻路。玩家在操控角色移动的时候,指引需要实时更新,同时一些npc也需要做移动,容易出现cpu占用率短时间过高,甚至掉帧的情况。 去年底的时候,由于希望在性能优化方面做一些研究,在论坛找到了江南百

    2023年04月19日
    浏览(30)
  • Unity 中的简单A*寻路 (AStar寻路)实现

    本文实现的A*算法,未经过大量的优化,后续文章会进一步实现优化 后篇:A*优化讨论 结点类: 结点管理类: 单例模板: 测试脚本: 新建一个场景,将测试脚本挂载在任意物体上 新建一个画布,并添加一个按钮。其它ui元素可随意设定 将按钮关联Init方法 后续优化文章:

    2024年02月03日
    浏览(54)
  • [音视频] SDL 渲染

    SDL_INIT # 初始化 SDL 库 SDL_CreateWIndow # 创建窗口 SDL_CreateRenderer # 创建渲染器 需要指定渲染窗口 SDL_CreateTexture # 需要指定纹理的上下文 和 数据修改频率 SDL_UpdateTexuture # 把 cpu 数据拷贝到 gpu 纹理中 SDL_RenderClear # 清空窗口纹理 SDL_RenderCopy # 把更新后的纹理拷贝到窗口纹理上 SDL_

    2024年02月10日
    浏览(95)
  • SDL的知识

    SDL是什么,能干什么,为什么我们要学习它?_为什么学 sdl 游戏编程-CSDN博客 SDL2 基础(一)SDL2入门 - 掘金 (juejin.cn) “SDL库的作用说白了就是封装了复杂的视音频底层操作,简化了视音频处理的难度。 ”  SDL 全称 “Simple DirectMedia Layer” 。 SDL是一个开放源代码的跨平台多媒

    2024年01月23日
    浏览(27)
  • 深入探索SDL游戏开发

    前言 欢迎来到小K的SDL专栏第二小节,本节将为大家带来基本窗口构成、渲染器、基本图形绘制、贴图、事件处理等的详细讲解,看完以后,希望对你有帮助 一、简单窗口 ✨第一步,我们先包含SDL图形库的头文件 ✨第二步,我们需要初始化SDL2库 注意主函数的形参,必须是一

    2024年02月07日
    浏览(41)
  • “深入探索SDL游戏开发“

    前言 欢迎来到小K的SDL专栏第二小节,本节将为大家带来基本窗口构成、渲染器、基本图形绘制、贴图、事件处理等的详细讲解,看完以后,希望对你有帮助 一、简单窗口 ✨第一步,我们先包含SDL图形库的头文件 ✨第二步,我们需要初始化SDL2库 注意主函数的形参,必须是一

    2024年02月05日
    浏览(34)
  • SDL—威胁建模PASTA

    已经在之前的篇章里学习了STRIDE,可以参考: SDL—设计 SDL—威胁建模STRIDE VerSprite Security公司在2012年提出的PASTA(Process for Attack Simulation and Threat Analysis)通过风险为中心的威胁建模方法,针对应用程序或系统环境识别可行的威胁模式。 以风险为中心,量化可能影响业务或系

    2024年02月01日
    浏览(53)
  • SDL—威胁建模STRIDE

    专门拎出来一片来学习威胁建模的详细内容,主要是关注不同的威胁建模方法以及威胁建模实际落地的情况。这里特指的软件安全流程。本篇只针对STRIDE以及它的一个补充进行描述。 威胁建模指的是通过分析和思考,识别目标可能出现的漏洞和风险,实际上威胁建模的目的就

    2024年02月09日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包