面试中算法(A星寻路算法)

news2024/11/17 19:19:28

一、问题需求:

     迷宫寻路游戏中,有一些小怪物要攻击主角,现在希望你给这些小怪物加上聪 明的AI (Artificial Intelligence,人工智能),让它们可以自动绕过迷宫中的障碍物,寻找到主角的所在。

A星寻路算法 (A*search algorithm),是一种用于寻找有效路径的算法。

迷宫游戏的场景通常都是由小方格组成的。假设我们有一个6x7大小的迷宫

绿色的格子是起点红色的格子是终点,中间的3个紫色格子是一堵墙

A星寻路算法通过计算和量化行走的各个方向的代价,来选择最优路径。
公式:F = G + H
G:从起点走到当前格子的成本,也就是已经花费了多少步。

H:在不考虑障碍的情况下,从当前格子走到目标格子的距离,也就是离目标还有多远。

F:G和H的综合评估,也就是从起点到达当前格子,再从当前格子到达目标格子的总步数。

每个方格都标上了 F , G , H 的值,就像起点右边的方格那样,左上角是 F ,左下角是 G ,右下角是 H 。

二、操作步骤:

两个集合如下:

 open_list――可到达的格子

 close_list—―已到达的格子

第1轮寻路历程 

第1步:把起点放入open_list可到达格子的集合。 

open_list:grid(2,1)

close_list:

第2步:找出open_list中F值最小的方格作为当前方格。虽然我们没有直接计算起点方格的F值,但此时open_list中只有唯一的方格grid (2,1),把当前格子移出open_list,放入close_list。代表这个格子已到达并检查过了。

open_list:

close_list:grid(2,1)

 

第3步:找出当前方格(刚刚检查过的格子)上、下、左、右所有可到达的格子,看它们是否在open_list或close_list当中。如果不在,则将它们加入open_list,计算出相应的G、H、F值,并把当前格子作为它们的“父节点”。

我们需要一次又一次重复刚才的第 2步和第3步,直到找到终点为止。

第2轮寻路历程

第1步,找出open_list中F值最小的方格,即方格grid (2,2),将它作为当前方格,并把当前方格移出open_list,放入close_list。代表这个格子已到达并检查过了。

第2步,找出当前方格上、下、左、右所有可到达的格子,看它们是否在open_list或 close_list当中。如果不在,则将它们加入open_list,计算出相应的G、H、F值,并把当前格子作为它们的“父节点”。 为什么这一次open_list只增加了2个新格子呢?因为grid (2,3)是墙壁,自然不用考虑,而grid (2,1)在close_list中,说明已经检查过了,也不用考虑。

第3轮寻路历程

第1步,找出open_list中F值最小的方格。由于此时有多个方格的F值相等,任意选择一个即可,如将grid (2,3)作为当前方格,并把当前方格移出open_list,放入close_list。代表这个格子已到达并检查过了。

第2步,找出当前方格上、下、左、右所有可到达的格子,看它们是否在open_list当中。如果不在,则将它们加入open_list,计算出相应的G、H、F值,并把当前格子作为它们的“父节点”。

剩下的操作就是以前面的方式继续迭代,直到open_list中出现终点方格为止。

''''
 pip install colorama

'''
from colorama import init, Fore, Back, Style

def a_star_search(start, end):
    # 初始化
    # 待访问的格子
    open_list = []
    # 已访问的格子
    close_list = []
    # 把起点加入open_list
    open_list.append(start)
    # 主循环,每一轮检查一个当前方格节点
    while len(open_list) > 0:
        # 在open_list中查找 F值最小的节点作为当前方格节点
        current_grid = find_min_gird(open_list)
        # 当前方格节点从openList中移除
        open_list.remove(current_grid)
        # 当前方格节点进入 closeList
        close_list.append(current_grid)
        # 找到所有邻近节点
        neighbors = find_neighbors(current_grid, open_list, close_list)
        for grid in neighbors:
            # 邻近节点不在openList中,标记父亲、G、H、F,并放入openList
            grid.init_grid(current_grid, end)
            open_list.append(grid)
        # 如果终点在openList中,直接返回终点格子
        for grid in open_list:
            if (grid.x == end.x) and (grid.y == end.y):
                return grid
    # openList用尽,仍然找不到终点,说明终点不可到达,返回空
    return None


def find_min_gird(open_list=[]):
    # 找到openList中F值最小的节点
    return min(open_list, key=lambda x: x.f)


def find_neighbors(grid, open_list=[], close_list=[]):
    grid_list = []
    # 上下左右四个方向
    if is_valid_grid(grid.x, grid.y-1, open_list, close_list):
        grid_list.append(Grid(grid.x, grid.y-1))
    if is_valid_grid(grid.x, grid.y+1, open_list, close_list):
        grid_list.append(Grid(grid.x, grid.y+1))
    if is_valid_grid(grid.x-1, grid.y, open_list, close_list):
        grid_list.append(Grid(grid.x-1, grid.y))
    if is_valid_grid(grid.x+1, grid.y, open_list, close_list):
        grid_list.append(Grid(grid.x+1, grid.y))
    return grid_list


def is_valid_grid(x, y, open_list=[], close_list=[]):
        # 是否超过边界
        if x < 0 or x >= len(MAZE) or y < 0 or y >= len(MAZE[0]):
            return False
        # 是否有障碍物
        if MAZE[x][y] == 1:
            return False
        # 是否已经在open_list中
        if contain_grid(open_list, x, y):
            return False
        # 是否已经在closeList中
        if contain_grid(close_list, x, y):
            return False
        return True


def contain_grid(grids, x, y):
    for grid in grids:
        if (grid.x == x) and (grid.y == y):
            return True
    return False


class Grid:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.f = 0
        self.g = 0
        self.h = 0
        self.parent = None

    def init_grid(self, parent, end):
        self.parent = parent
        self.g = parent.g + 1
        self.h = abs(self.x - end.x) + abs(self.y - end.y)
        self.f = self.g + self.h


# 迷宫地图
MAZE = [
    [0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 1, 0, 0, 0],
    [0, 0, 0, 1, 0, 0, 0],
    [0, 0, 0, 1, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0]
]

if __name__ == '__main__':
    # 设置起点和终点
    start_grid = Grid(2, 1)
    # end_grid = Grid(2, 5)
    end_grid = Grid(3, 4)
    # 搜索迷宫终点
    result_grid = a_star_search(start_grid, end_grid)
    # 回溯迷宫路径
    path = []
    while result_grid is not None:
        path.append(Grid(result_grid.x, result_grid.y))
        result_grid = result_grid.parent
    # 输出迷宫和路径,路径用星号表示
    for i in range(0, len(MAZE)):
        for j in range(0, len(MAZE[0])):
            if contain_grid(path, i, j):
                print(Fore.RED + "*, "+Fore.RESET, end='')
            else:
                print(str(MAZE[i][j]) + ", ", end='')
        print()

      

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1700022.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

flink程序本地运行:No ExecutorFactory found to execute the application

1.问题描述 在idea中运行flink job程序出现如下错误&#xff1a; Exception in thread "main" java.lang.IllegalStateException: No ExecutorFactory found to execute the application. at org.apache.flink.core.execution.DefaultExecutorServiceLoader.getE…

Linux基础 (十):Linux 信号的使用

目录 一、信号的基本概念 二、信号处理常见方式概览 三、修改信号的响应方式 – signal() 3.1 简单复习结束前台进程 3.2 改变SIGINT信号的响应方式 3.3 自定义方式改变进程对信号的响应 3.4 进程对信号作出两种响应 四、发送信号 – kill() 五、利用信号解决僵死进程…

Apache CXF Aegis databinding SSRF 高危漏洞修复

一、漏洞修复 Apache CXF Aegis databinding SSRF漏洞 Spring Web UriComponentsBuilder URL解析不当漏洞 二、修复步骤 1、Apache CXF Aegis databinding SSRF漏洞修复 步骤&#xff1a; 进入服务器搜索 databinding find -name *databinding* 发现版本是3.1.6 果断…

springboot项目中图片上传之后需要重启工程才能看到图片?

需求背景 最近在做一个用户自定义上传头像的小需求&#xff0c;用户上传头像然后需要立马回显。 需求是很常见的、正当的需求。如果不使用到对象存储这类服务&#xff0c;我们把用户头像的图片文件仅存在本地就可以了。我们在开发的过程中为了工程管理方便通常下意识会将图片…

list的模拟实现(一)

嗨喽大家好&#xff0c;时隔许久阿鑫又给大家带来了新的博客&#xff0c;list的模拟实现&#xff08;一&#xff09;&#xff0c;下面让我们开始今天的学习吧&#xff01; list的模拟实现&#xff08;一&#xff09; 1.list splice接口的使用 2.list尾插的实现 3.list的迭代…

瑞昱半导体AMB82 MINI(RTL8735B)Arduino 方法介绍

介绍瑞昱半导体&#xff08;Realtek &#xff09;AMB82-Mini 物联网 AI开发板 Ameba是一个易于编程的平台&#xff0c;用于开发各种物联网应用程序。AMB82 MINI配备了各种外设接口&#xff0c;包括WiFi、BLE、GPIO INT、I2C、UART、SPI、PWM、ADC。通过这些接口&#xff0c;AM…

Reids高频面试题汇总总结

一、Redis基础 Redis是什么? Redis是一个开源的内存数据存储系统,它可以用作数据库、缓存和消息中间件。Redis支持多种数据结构,如字符串、哈希表、列表、集合、有序集合等,并提供了丰富的操作命令来操作这些数据结构。Redis的主要特点是什么? 高性能:Redis将数据存储在内…

C语言代码错误(一)

今天在写选择排序代码时&#xff0c;在测试数据发现不能显示结果 1、代码如下&#xff1a; #include <stdio.h>int main(void) {int i, j; // 循环变量int MinIndex; // 保存最小的值的下标int buf; // 互换数据时的临时变量int n;printf("你想输入多少个数据n:\n…

ElasticSearch插件版本与ES版本不对应的解决方案

一、背景 最近需要给es安装ik、hanlp分词器和ingest-attachment管道&#xff0c;服务器已有的es版本为8.5.3&#xff08;似乎太新了&#xff09;&#xff0c;hanlp和ingest-attachment都没有这么高的版本&#xff0c;因此只能下载相对老的版本&#xff0c;然后自己修改配置文件…

C#同花顺下单 模拟操作版接口实现

C#同花顺下单 模拟操作版接口的实现 采用C#编程语言实现&#xff0c;对同花顺下单界面自动控制&#xff0c;将实现方法封装为DLL可以任意使用&#xff0c;支持几乎所有券商&#xff0c;不需要更换特定的券商。 比如当下最流行的QMT量化软件&#xff0c;仍然受限于特定的券商&a…

springboot小结1

什么是springboot ​ Spring Boot是为了简化Spring应用的创建、运行、调试、部署等而出现的&#xff0c;使用它可以做到专注于Spring应用的开发&#xff0c;而无需过多关注XML的配置。 ​ 简单来说&#xff0c;它提供了一堆依赖打包Starter&#xff0c;并已经按照使用习惯解决…

利用element实现简单右键

利用element-plus中的el-menu实现简单右键 实现如下 <template><main class"mainClass" contextmenu"showMenu($event)"> </main><el-menu:default-active"1"class"el-menu-demo"mode"vertical":col…

【Qt】Qt入门

思维导图 学习目标 这一系列是学习Qt&#xff0c;在C中&#xff0c;会发现有不少岗位的要求是熟悉Qt&#xff0c;所以Qt的学习是不能推迟的。 一、Qt的概述 1.1 Qt的特点 Qt是一个跨平台的C应用程序开发框架&#xff1a; 具有短平快的优秀特质&#xff1a;投资少&#xff0…

大模型额外篇章二:基于chalm3或Llama2-7b训练酒店助手模型

文章目录 一、代码部分讲解二、实际部署步骤(CHALM3训练步骤)1)注册AutoDL官网实名认证2)花费额度挑选GPU3)准备实验环境4)开始执行脚本5)从浏览器访问6)可以开始提问7)开始微调模型8)测试训练后的模型三、基于Llama2-7b的训练四、额外补充1)修改参数后2)如果需要访问…

windows安装SQL Server

1、下载 下载网页&#xff1a;SQL Server 下載 | Microsoft 2022版下载地址&#xff1a;https://go.microsoft.com/fwlink/p/?linkid2215158&clcid0x404&culturezh-tw&countrytw 下载结果&#xff1a;SQL2022-SSEI-Dev.exe 打开选第三个&#xff0c;下载介质&…

Cohere继Command-R+之后发布大模型Aya-23,性能超越 Gemma、Mistral 等,支持中文

前言 近年来&#xff0c;多语言大模型&#xff08;MLLM&#xff09;发展迅速&#xff0c;但大多数模型的性能依然存在显著差距&#xff0c;尤其是在非英语语言方面表现不佳。为了推动多语言自然语言处理技术的发展&#xff0c;Cohere团队发布了新的多语言指令微调模型家族——…

微信小程序文本框输入显示已经输入的字数

我们遇到这样的需求&#xff0c;就是微信小程序的输入框下面需要显示输入的字数&#xff1a; 我们通常会使用bindinput事件&#xff0c;让显示的字数等于value的长度&#xff0c;看下面的图&#xff1a; 但在实践中&#xff0c;真机测试中&#xff0c;我们会发现以下问题: 这个…

【C++】——入门基础知识超详解

目录 ​编辑 1.C关键字 2. 命名空间 2.1 命名空间定义 2.2 命名空间使用 命名空间的使用有三种方式&#xff1a; 注意事项 3. C输入&输出 示例 1&#xff1a;基本输入输出 示例 2&#xff1a;读取多个值 示例 3&#xff1a;处理字符串输入 示例 4&#xff1a;读…

2024年5月27日 十二生肖 今日运势

小运播报&#xff1a;2024年5月27日&#xff0c;星期一&#xff0c;农历四月二十 &#xff08;甲辰年己巳月辛卯日&#xff09;&#xff0c;法定工作日。 红榜生肖&#xff1a;羊、蛇、狗 需要注意&#xff1a;鼠、鸡、龙 喜神方位&#xff1a;西南方 财神方位&#xff1a;…

vue3 vite项目配置了proxy代理情况下查看真实的接口调用地址

vite配置了proxy代理情况下如何查看真实的接口调用地址? 使用vite进行代理 在vite.config.ts配置了代理 在浏览器查看请求头和响应头发现只有代理前的url&#xff0c;没有显示代理后的路径 然后发现一个bypass函数&#xff0c;但是此函数只能修改res响应头的数据&#xff0…