当前位置: 首页 > news >正文

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

一、问题需求:

     迷宫寻路游戏中,有一些小怪物要攻击主角,现在希望你给这些小怪物加上聪 明的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, Styledef a_star_search(start, end):# 初始化# 待访问的格子open_list = []# 已访问的格子close_list = []# 把起点加入open_listopen_list.append(start)# 主循环,每一轮检查一个当前方格节点while len(open_list) > 0:# 在open_list中查找 F值最小的节点作为当前方格节点current_grid = find_min_gird(open_list)# 当前方格节点从openList中移除open_list.remove(current_grid)# 当前方格节点进入 closeListclose_list.append(current_grid)# 找到所有邻近节点neighbors = find_neighbors(current_grid, open_list, close_list)for grid in neighbors:# 邻近节点不在openList中,标记父亲、G、H、F,并放入openListgrid.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 Nonedef 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_listdef 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 Falsereturn Truedef contain_grid(grids, x, y):for grid in grids:if (grid.x == x) and (grid.y == y):return Truereturn Falseclass Grid:def __init__(self, x, y):self.x = xself.y = yself.f = 0self.g = 0self.h = 0self.parent = Nonedef init_grid(self, parent, end):self.parent = parentself.g = parent.g + 1self.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()

      

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • tomcat--安全配置多虚拟机
  • 2024年,游戏行业还值得进入吗?
  • 在ARM开发板上,栈大小设置为2MB(常用设置)里面存放的数据
  • 盲人社区生活支持体系:织就一张温暖的网
  • 蓝桥杯嵌入式国赛笔记(2):拓展板按键程序设计
  • pwa动态修改manifest.json(start_url)
  • PHP发票真假API、医疗电子票据查验、发票识别接口开发示例
  • 元组推导式
  • Keras深度学习框架第二十九讲:在自定义训练循环中应用KerasTuner超参数优化
  • qt 布局学习笔记
  • 气膜体育馆主要能耗解析—轻空间
  • 2024,java开发,已经炸了吗?
  • Python 开心消消乐
  • C# 实现腾讯云点播之媒体上传常用接口
  • java中的类加载器
  • 2017-08-04 前端日报
  • Consul Config 使用Git做版本控制的实现
  • CSS居中完全指南——构建CSS居中决策树
  • IDEA常用插件整理
  • javascript 哈希表
  • java中的hashCode
  • NSTimer学习笔记
  • Protobuf3语言指南
  • Spark VS Hadoop:两大大数据分析系统深度解读
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • 关于List、List?、ListObject的区别
  • ------- 计算机网络基础
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 使用API自动生成工具优化前端工作流
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 函数计算新功能-----支持C#函数
  • ​​​【收录 Hello 算法】9.4 小结
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • ‌前端列表展示1000条大量数据时,后端通常需要进行一定的处理。‌
  • # dbt source dbt source freshness命令详解
  • #etcd#安装时出错
  • #laravel 通过手动安装依赖PHPExcel#
  • (2024)docker-compose实战 (8)部署LAMP项目(最终版)
  • (2024,Vision-LSTM,ViL,xLSTM,ViT,ViM,双向扫描)xLSTM 作为通用视觉骨干
  • (3)nginx 配置(nginx.conf)
  • (39)STM32——FLASH闪存
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (Java数据结构)ArrayList
  • (JS基础)String 类型
  • (SERIES12)DM性能优化
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (十六)一篇文章学会Java的常用API
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • .desktop 桌面快捷_Linux桌面环境那么多,这几款优秀的任你选
  • .NET C# 使用GDAL读取FileGDB要素类
  • .NET CF命令行调试器MDbg入门(一)
  • .net core webapi Startup 注入ConfigurePrimaryHttpMessageHandler