本文由恋花蝶发表于http://blog.csdn.net/lanphaday,可以在保证全文完整的前提下任意形式自由传播,但必须保留本声明,违反必究。

最近因为一个任务要用到A*算法,就用C++实现了一份。不过只是用A*来检测从A点到B点有无通路,不必输出路径,后来想把代码贴出来,但又觉得不如实现一个简单的寻路应用好一些,就用python写了一个版本贴上来。
 A*算法不仅仅可以用来寻路,寻路也不仅仅使用A*算法。这是使用学习和使用A*算法最要谨记的一点吧~
 A*算法用以寻路实现算不得是人工智能,他本质上是一种启发式的试探回溯算法,不过业界似乎喜欢把它称为游戏人工智能(GameAI)的一个组成部分,听起来就“豪华”得多了。A*算法需要很大的内存(相对于深度优先搜索),需要很实现比较复杂的逻辑,容易出错。
 A*过程:
 1.将开始节点放入开放列表(开始节点的F和G值都视为0);
 2.重复一下步骤:
  i.在开放列表中查找具有最小F值的节点,并把查找到的节点作为当前节点;
  ii.把当前节点从开放列表删除, 加入到封闭列表;
  iii.对当前节点相邻的每一个节点依次执行以下步骤:
   1.如果该相邻节点不可通行或者该相邻节点已经在封闭列表中,则什么操作也不执行,继续检验下一个节点;
   2.如果该相邻节点不在开放列表中,则将该节点添加到开放列表中, 并将该相邻节点的父节点设为当前节点,同时保存该相邻节点的G和F值;
   3.如果该相邻节点在开放列表中, 则判断若经由当前节点到达该相邻节点的G值是否小于原来保存的G值,若小于,则将该相邻节点的父节点设为当前节点,并重新设置该相邻节点的G和F值.
  iv.循环结束条件:
   当终点节点被加入到开放列表作为待检验节点时, 表示路径被找到,此时应终止循环;
   或者当开放列表为空,表明已无可以添加的新节点,而已检验的节点中没有终点节点则意味着路径无法被找到,此时也结束循环;
 3.从终点节点开始沿父节点遍历, 并保存整个遍历到的节点坐标,遍历所得的节点就是最后得到的路径;

好了,废话不多说,看代码吧,带详尽注释,但可能存在bug~,另:本示例程序未作优化。

参考资料:
http://www.gamedev.net/reference/programming/features/astar/default.asp

http://blog.csdn.net/win32asn/archive/2006/03/17/627098.aspx

# -*- coding: utf-8 -*-
import math#地图
tm = [
'############################################################',
'#..........................................................#',
'#.............................#............................#',
'#.............................#............................#',
'#.............................#............................#',
'#.......S.....................#............................#',
'#.............................#............................#',
'#.............................#............................#',
'#.............................#............................#',
'#.............................#............................#',
'#.............................#............................#',
'#.............................#............................#',
'#.............................#............................#',
'#######.#######################################............#',
'#....#........#............................................#',
'#....#........#............................................#',
'#....##########............................................#',
'#..........................................................#',
'#..........................................................#',
'#..........................................................#',
'#..........................................................#',
'#..........................................................#',
'#...............................##############.............#',
'#...............................#........E...#.............#',
'#...............................#............#.............#',
'#...............................#............#.............#',
'#...............................#............#.............#',
'#...............................###########..#.............#',
'#..........................................................#',
'#..........................................................#',
'############################################################']#因为python里string不能直接改变某一元素,所以用test_map来存储搜索时的地图
test_map = []#########################################################
class Node_Elem:"""开放列表和关闭列表的元素类型,parent用来在成功的时候回溯路径"""def __init__(self, parent, x, y, dist):self.parent = parentself.x = xself.y = yself.dist = distclass A_Star:"""A星算法实现类"""#注意w,h两个参数,如果你修改了地图,需要传入一个正确值或者修改这里的默认参数def __init__(self, s_x, s_y, e_x, e_y, w=60, h=30):self.s_x = s_xself.s_y = s_yself.e_x = e_xself.e_y = e_yself.width = wself.height = hself.open = []self.close = []self.path = []#查找路径的入口函数def find_path(self):#构建开始节点p = Node_Elem(None, self.s_x, self.s_y, 0.0)while True:#扩展F值最小的节点self.extend_round(p)#如果开放列表为空,则不存在路径,返回if not self.open:return#获取F值最小的节点idx, p = self.get_best()#找到路径,生成路径,返回if self.is_target(p):self.make_path(p)return#把此节点压入关闭列表,并从开放列表里删除self.close.append(p)del self.open[idx]def make_path(self,p):#从结束点回溯到开始点,开始点的parent == Nonewhile p:self.path.append((p.x, p.y))p = p.parentdef is_target(self, i):return i.x == self.e_x and i.y == self.e_ydef get_best(self):best = Nonebv = 1000000 #如果你修改的地图很大,可能需要修改这个值bi = -1for idx, i in enumerate(self.open):value = self.get_dist(i)#获取F值if value < bv:#比以前的更好,即F值更小best = ibv = valuebi = idxreturn bi, bestdef get_dist(self, i):# F = G + H# G 为已经走过的路径长度, H为估计还要走多远# 这个公式就是A*算法的精华了。return i.dist + math.sqrt((self.e_x-i.x)*(self.e_x-i.x)+ (self.e_y-i.y)*(self.e_y-i.y))*1.2def extend_round(self, p):#可以从8个方向走xs = (-1, 0, 1, -1, 1, -1, 0, 1)ys = (-1,-1,-1,  0, 0,  1, 1, 1)#只能走上下左右四个方向
#        xs = (0, -1, 1, 0)
#        ys = (-1, 0, 0, 1)for x, y in zip(xs, ys):new_x, new_y = x + p.x, y + p.y#无效或者不可行走区域,则勿略if not self.is_valid_coord(new_x, new_y):continue#构造新的节点node = Node_Elem(p, new_x, new_y, p.dist+self.get_cost(p.x, p.y, new_x, new_y))#新节点在关闭列表,则忽略if self.node_in_close(node):continuei = self.node_in_open(node)if i != -1:#新节点在开放列表if self.open[i].dist > node.dist:#现在的路径到比以前到这个节点的路径更好~#则使用现在的路径self.open[i].parent = pself.open[i].dist = node.distcontinueself.open.append(node)def get_cost(self, x1, y1, x2, y2):"""上下左右直走,代价为1.0,斜走,代价为1.4"""if x1 == x2 or y1 == y2:return 1.0return 1.4def node_in_close(self, node):for i in self.close:if node.x == i.x and node.y == i.y:return Truereturn Falsedef node_in_open(self, node):for i, n in enumerate(self.open):if node.x == n.x and node.y == n.y:return ireturn -1def is_valid_coord(self, x, y):if x < 0 or x >= self.width or y < 0 or y >= self.height:return Falsereturn test_map[y][x] != '#'def get_searched(self):l = []for i in self.open:l.append((i.x, i.y))for i in self.close:l.append((i.x, i.y))return l#########################################################
def print_test_map():"""打印搜索后的地图"""for line in test_map:print ''.join(line)def get_start_XY():return get_symbol_XY('S')def get_end_XY():return get_symbol_XY('E')def get_symbol_XY(s):for y, line in enumerate(test_map):try:x = line.index(s)except:continueelse:breakreturn x, y#########################################################
def mark_path(l):mark_symbol(l, '*')def mark_searched(l):mark_symbol(l, ' ')def mark_symbol(l, s):for x, y in l:test_map[y][x] = sdef mark_start_end(s_x, s_y, e_x, e_y):test_map[s_y][s_x] = 'S'test_map[e_y][e_x] = 'E'def tm_to_test_map():for line in tm:test_map.append(list(line))def find_path():s_x, s_y = get_start_XY()e_x, e_y = get_end_XY()a_star = A_Star(s_x, s_y, e_x, e_y)a_star.find_path()searched = a_star.get_searched()path = a_star.path#标记已搜索区域mark_searched(searched)#标记路径mark_path(path)print "path length is %d"%(len(path))print "searched squares count is %d"%(len(searched))#标记开始、结束点mark_start_end(s_x, s_y, e_x, e_y)if __name__ == "__main__":#把字符串转成列表tm_to_test_map()find_path()print_test_map()

用python实现基本A*算法相关推荐

  1. Python版本的数据结构书_《用Python解决数据结构与算法问题》

    源于经典 数据结构作为计算机从业人员的必备基础,Java, c 之类的语言有很多这方面的书籍,Python 相对较少, 其中比较著名的一本 problem-solving-with-algorithm ...

  2. python实现洗牌算法_洗牌算法及 random 中 shuffle 方法和 sample 方法浅析

    对于算法书买了一本又一本却没一本读完超过 10%,Leetcode 刷题从来没坚持超过 3 天的我来说,算法能力真的是渣渣.但是,今天决定写一篇跟算法有关的文章.起因是读了吴师兄的文章 <扫雷与 ...

  3. python实现快排算法(quicksort)

    python实现快排算法(quicksort) 快速排序是对冒泡排序的一种改进.它的基本思想是:通过一次排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一不部分的所有数据都要小,然后 ...

  4. 【Python排序搜索基本算法】之拓扑排序

    [Python排序搜索基本算法]之拓扑排序 版权声明:本文为博主原创文章,未经博主允许不得转载.

  5. python数据结构推荐书-「算法与数据结构」从入门到进阶吐血整理推荐书单

    推荐一下「算法与数据结构」从入门到进阶的书单. 一.入门系列 这些书籍通过图片.打比方等通俗易懂的方法来讲述,让你能达到懂一些基础算法,线性表,堆栈,队列,树,图,DP算法,背包问题等,不要求会实现, ...

  6. python语言入门w-Python算法基础

    有穷性:算法的有穷性是指算法必须能在执行有限个步骤之后终止: 确切性:算法的每一步骤必须有确切的定义: 输入项:一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0个输入是指算法本身定出了初始条 ...

  7. gbdt 算法比随机森林容易_用Python实现随机森林算法

    CDA数据分析师 出品 拥有高方差使得决策树(secision tress)在处理特定训练数据集时其结果显得相对脆弱.bagging(bootstrap aggregating 的缩写)算法从训练数据 ...

  8. python分割数字_对python数据切割归并算法的实例讲解

    当一个 .txt 文件的数据过于庞大,此时想要对数据进行排序就需要先将数据进行切割,然后通过归并排序,最终实现对整体数据的排序.要实现这个过程我们需要进行以下几步:获取总数据行数:根据行数按照自己的需 ...

  9. Python实现 logistic 回归算法

    Python实现 logistic 回归算法 1.算法介绍 模型描述: sigmoid函数: 原理: 优化目标:最小化 sigmoid(f(x)) 和真实标签的差别(有不同的 cost functio ...

  10. 八十八、Python | 十大排序算法系列(下篇)

    @Author:Runsen @Date:2020/7/10 人生最重要的不是所站的位置,而是内心所朝的方向.只要我在每篇博文中写得自己体会,修炼身心:在每天的不断重复学习中,耐住寂寞,练就真功,不畏 ...

最新文章

  1. vs2019下载和更新速度非常慢的解决方案
  2. ORM 和 JDBC有何不一样
  3. Thread Safety in the Standard C++ Library
  4. Windows Server 2008 R2之二从介质安装 AD DS
  5. 下载配置Gradle
  6. python3连接MSSQL数据库 中文乱码怎么解决?
  7. 无刷直流电机的基本工作原理
  8. 达梦 DCA 培训总结
  9. t恤衫尺码对照表_T恤衫
  10. 【测试理论】三、测试流程管理
  11. 使用财务系统所用到的会计基础知识(一)
  12. 《南方周末》今日发文揭开了这场抢票插件阻击战的内幕
  13. vue的自定义指令 - Directive
  14. DEDECMS站点内容怎么自动更新到新浪微博
  15. H5游戏视力测试-玩到第八关都是大神
  16. 苹果摆脱对中国制造的依赖?iPhone14的拆解结果显示恰恰相反,更离不开中国制造了...
  17. 电商用户价值分析(应用RFM模型)
  18. 通过蓝奏云与云端检测来实现软件自动更新
  19. JavaScript学习笔记(九)(验证框架,layer弹出层)
  20. 手把手教你开发人工智能微信小程序(1):线性回归模型

热门文章

  1. 大洗牌中的中国服务业:这个冬天远比你想象中寒冷
  2. 深度学习之四:常用模型和方法
  3. 实战SSM_O2O商铺_20【商铺编辑】View层开发
  4. 实战SSM_O2O商铺_12【商铺注册】View层之前台页面
  5. 实战SSM_O2O商铺_03项目结构规划及Maven配置
  6. 学习笔记——使用下划线命名的规则
  7. plsql存储过程修改后怎么保存_证件照上传不成功,教你修改分辨率、调整照片大小...
  8. 2021-01-13 Matlab求解微分代数方程 (DAE)
  9. python通过pyinstaller打包软件将GUI项目打包成exe文件
  10. 卡尔曼滤波器原理和matlab实现