A*(A星)算法python实现

在春节放假前两天我偶然看到了A*算法,感觉挺有意思。正好放假前也没有什么事情,就花了一个下午写出算法的骨架,节后又花了半天时间完善屏幕输出的细节并且调试完成。

该实现只是一时兴起的随手而作,没有考虑性能和扩展性等问题。正在学习A*的朋友可以拿去随便折腾。

Email: [email protected]

代码的运行效果如下:

#!/usr/bin/python?
# vim:set fileencoding=utf-8

# 在春节放假前两天我偶然看到了A*算法,感觉挺有意思。正好放假前
# 也没有什么事情,就花了一个下午写出算法的骨架,节后又花了半天
# 时间完善屏幕输出的细节并且调试完成。
# 该实现只是一时兴起的随手而作,没有考虑性能和扩展性等问题。正
# 在学习A*的朋友可以拿去随便折腾。
#                             email: [email protected]
import sys

_2dmap     = []
start      = None
end        = None
open_list  = {}
close_list = {}
map_border = ()

class Node:
    def __init__(this, father, x, y):
        if x < 0 or x >= map_border[0] or y < 0 or y >= map_border[1]:
            raise Exception("node position can‘t beyond the border!")

        this.father = father
        this.x = x
        this.y = y
        if father != None:
            G2father = calc_G(father, this)
            if not G2father:
                raise Exception("father is not valid!")
            this.G = G2father + father.G
            this.H = calc_H(this, end)
            this.F = this.G + this.H
        else:
            this.G = 0
            this.H = 0
            this.F = 0

    def reset_father(this, father, new_G):
        if father != None:
            this.G = new_G
            this.F = this.G + this.H

        this.father = father

def calc_G(node1, node2):
    x1 = abs(node1.x-node2.x)
    y1 = abs(node1.y-node2.y)
    if (x1== 1 and y1 == 0):
        return 10 # same row
    if (x1== 0 and y1 == 1):
        return 10 # same col
    if (x1== 1 and y1 == 1):
        return 14 # cross
    else:
        return 0

def calc_H(cur, end):
    return abs(end.x-cur.x) + abs(end.y-cur.y)

# NOTE 这个地方可能成为性能瓶颈
def min_F_node():
    if len(open_list) == 0:
        raise Exception("not exist path!")

    _min = 9999999999999999
    _k = (start.x, start.y)
    for k,v in open_list.items():
        if _min > v.F:
            _min = v.F
            _k = k
    return open_list[_k]

# 把相邻节点加入open list, 如果发现终点说明找到了路径
def addAdjacentIntoOpen(node):
    # 将该节点从开放列表移到关闭列表当中。
    open_list.pop((node.x, node.y))
    close_list[(node.x, node.y)] = node

    _adjacent = []
    # 相邻节点要注意边界的情况
    try:
        _adjacent.append(Node(node , node.x - 1 , node.y - 1))
    except Exception,e:
        pass
    try:
        _adjacent.append(Node(node , node.x     , node.y - 1))
    except Exception,e:
        pass
    try:
        _adjacent.append(Node(node , node.x + 1 , node.y - 1))
    except Exception,e:
        pass
    try:
        _adjacent.append(Node(node , node.x + 1 , node.y))
    except Exception,e:
        pass
    try:
        _adjacent.append(Node(node , node.x + 1 , node.y + 1))
    except Exception,e:
        pass
    try:
        _adjacent.append(Node(node , node.x     , node.y + 1))
    except Exception,e:
        pass
    try:
        _adjacent.append(Node(node , node.x - 1 , node.y + 1))
    except Exception,e:
        pass
    try:
        _adjacent.append(Node(node , node.x - 1 , node.y))
    except Exception,e:
        pass

    for a in _adjacent:
        if (a.x,a.y) == (end.x, end.y):
            new_G = calc_G(a, node) + node.G
            end.reset_father(node, new_G)
            print "find path finish!"
            return True
        if (a.x,a.y) in close_list:
            continue

        if (a.x,a.y) not in open_list:
            open_list[(a.x,a.y)] = a
        else:
            exist_node = open_list[(a.x,a.y)]
            new_G = calc_G(a, node) + node.G
            if new_G < exist_node.G:
                exist_node.reset_father(node, new_G)

    return False

def find_the_path(start, end):
    open_list[(start.x, start.y)] = start

    the_node = start
    try:
        while not addAdjacentIntoOpen(the_node):
            the_node = min_F_node()
    except Exception,e:
        # path not exist
        print e
        return False

    return True

#=======================================================================
def print_map():
    print ‘    Y‘,
    for i in xrange(len(_2dmap)):
        print i,
    print
    print ‘  X‘
    row = 0
    for l in _2dmap:
        print ‘%3d‘%row,‘ ‘,
        row = row+1
        for i in l:
            print i,
        print

def mark_path(node):
    if node.father == None:
        return

    _2dmap[node.x][node.y] = ‘#‘
    mark_path(node.father)

def preset_map():
    global start,end,map_border
    _2dmap.append(‘S X . . . . . . . . . . . . . X . . . .‘.split())
    _2dmap.append(‘. X . . . . . . . . . . . . . X . . . .‘.split())
    _2dmap.append(‘. X . . . . . . . . . . . . . X . . . .‘.split())
    _2dmap.append(‘. . . . . . . . . . . . . . . X . . . .‘.split())
    _2dmap.append(‘. . . . . . . . . . . . . . . X . . . .‘.split())
    _2dmap.append(‘. . . . . . . . . . . . . . . . . . . .‘.split())
    _2dmap.append(‘. . . . . . . . . . . . . . . X X X X .‘.split())
    _2dmap.append(‘. . . . . . . . . . . . . . . X . . . .‘.split())
    _2dmap.append(‘. . . . . . . . . . . . . . . X . X X X‘.split())
    _2dmap.append(‘. . . . . . . . . . . . . . . X . X . .‘.split())
    _2dmap.append(‘. . . . . . . . . . . . . . . X . . . .‘.split())
    _2dmap.append(‘. . . . . . . . . . . . . . . X . X . .‘.split())
    _2dmap.append(‘. . . . . . . . . . . . . . . X . X . .‘.split())
    _2dmap.append(‘. . . . . . . . . . . . . . . X . X . .‘.split())
    _2dmap.append(‘. . . . . . . . . . . . . . . X . X . .‘.split())
    _2dmap.append(‘. . . . . . . . . . . . . . . X . X . E‘.split())
    map_border = (len(_2dmap),len(_2dmap[0]))

    row_index = 0
    for row in _2dmap:
        col_index = 0
        for n in row:
            if n == ‘X‘:
                block_node = Node(None, row_index, col_index)
                close_list[(block_node.x, block_node.y)] = block_node
            elif n == ‘S‘:
                start = Node(None, row_index, col_index)
            elif n == ‘E‘:
                end = Node(None, row_index, col_index)
            col_index = col_index + 1
        row_index = row_index + 1

if __name__==‘__main__‘:
    if len(sys.argv) < 3:
        preset_map()
    else:
        x = int(sys.argv[1])
        y = int(sys.argv[2])
        map_border = (x,y)

        _start = raw_input(‘pls input start point:‘)
        _end   = raw_input(‘pls input end point:‘)
        _start = _start.split(‘,‘)
        _end   = _end.split(‘,‘)
        _start = (int(_start[0]), int(_start[1]))
        _end   = (int(_end[0]), int(_end[1]))
        start = Node(None, _start[0], _start[1])
        end = Node(None, _end[0], _end[1])
        # gen map
        _2dmap = [[‘.‘ for i in xrange(y)] for i in xrange(x) ]
        # put start and end
        _2dmap[_start[0]][_start[1]] = ‘S‘
        _2dmap[_end[0]][_end[1]]     = ‘E‘
        # input blocks
        while True:
            _block = raw_input(‘input block:‘)
            if not _block:
                break

            _block = _block.split(‘,‘)
            _block = (int(_block[0]), int(_block[1]))
            _2dmap[_block[0]][_block[1]] = ‘X‘
            block_node = Node(None, _block[0], _block[1])
            close_list[(block_node.x, block_node.y)] = block_node

    print "orignal map:"
    print_map()

    if find_the_path(start, end):
        mark_path(end.father)
        print "found road as follow:"
        print_map()
时间: 2024-10-16 09:53:08

A*(A星)算法python实现的相关文章

【机器学习算法-python实现】采样算法的简单实现

1.背景 采样算法是机器学习中比较常用,也比较容易实现的(出去分层采样).常用的采样算法有以下几种(来自百度知道): 一.单纯随机抽样(simple random sampling) 将调查总体全部观察单位编号,再用抽签法或随机数字表随机抽取部分观察单位组成样本. 优点:操作简单,均数.率及相应的标准误计算简单. 缺点:总体较大时,难以一一编号. 二.系统抽样(systematic sampling) 又称机械抽样.等距抽样,即先将总体的观察单位按某一顺序号分成n个部分,再从第一部分随机抽取第k

【机器学习算法-python实现】矩阵去噪以及归一化

1.背景 项目需要,打算用python实现矩阵的去噪和归一化.用numpy这些数学库没有找到很理想的函数,所以一怒之下自己用标准库写了一个去噪和归一化的算法,效率有点低,不过还能用,大家如果有需要可以拿去. (1)去噪算法:根据概率论的知识,如果一组数据服从正态分布,我们设均值是n,方差是v,那么对于每个离散数值有百分之九十二以上的概率会在(n-3*v,n+3*v)的区间内.所以这里的去噪功能主要是实现如果超出了区间就将这个值标记为区间所能容忍最大值. (2)归一化:找到输入队列最大值max,最

【机器学习算法-python实现】协同过滤(cf)的三种方法实现

(转载请注明出处:http://blog.csdn.net/buptgshengod) 1.背景 协同过滤(collaborative filtering)是推荐系统常用的一种方法.cf的主要思想就是找出物品相似度高的归为一类进行推荐.cf又分为icf和ucf.icf指的是item collaborative filtering,是将商品进行分析推荐.同理ucf的u指的是user,他是找出知趣相似的人,进行推荐.通常来讲icf的准确率可能会高一些,通过这次参加天猫大数据比赛,我觉得只有在数据量非

A*搜寻算法(A星算法)

A*搜寻算法[编辑] 维基百科,自由的百科全书 本条目需要补充更多来源.(2015年6月30日) 请协助添加多方面可靠来源以改善这篇条目,无法查证的内容可能会被提出异议而移除. A*搜索算法,俗称A星算法.这是一种在图形平面上,有多个节点的路径,求出最低通过成本的算法.常用于游戏中的NPC的移动计算,或在线游戏的BOT的移动计算上. 该算法综合了BFS(Breadth First Search)和Dijkstra算法的优点:在进行启发式搜索提高算法效率的同时,可以保证找到一条最优路径(基于评估函

基于HTML5的WebGL呈现A星算法的3D可视化

http://www.hightopo.com/demo/astar/astar.html 最近搞个游戏遇到最短路径的常规游戏问题,一时起兴基于HT for Web写了个A*算法的WebGL 3D呈现,算法基于开源 https://github.com/bgrins/javascript-astar 的javascript实现,其实作者也有个不错的2D例子实现 http://www.briangrinstead.com/files/astar/ ,只不过觉得所有A*算法的可视化实现都是平面的不够

【机器学习算法-python实现】svm支持向量机(2)—简化版SMO算法

(转载请注明出处:http://blog.csdn.net/buptgshengod) 1.背景知识 通过上一节我们通过引入拉格朗日乗子得到支持向量机变形公式.详细变法可以参考这位大神的博客--地址 参照拉格朗日公式F(x1,x2,...λ)=f(x1,x2,...)-λg(x1,x2...).我们把上面的式子变型为: 约束条件就变成了: 下面就根据最小优化算法SMO(Sequential Minimal Optimization).找出距离分隔面最近的点,也就是支持向量集.如下图的蓝色点所示.

Cocos2d-x 3.1.1 学习日志16--A星算法(A*搜索算法)学问

A *搜索算法称为A星算法.这是一个在图形平面,路径.求出最低通过成本的算法. 经常使用于游戏中的NPC的移动计算,或线上游戏的BOT的移动计算上. 首先:1.在Map地图中任取2个点,開始点和结束点 2.首先推断该点是不是不能够穿越的点,或者是已经再close中了 3.假设2步骤为真.什么都不做,假设为假,那么我们就进行加入了 4.假设在加入的时候,发现该点在open中不存在.那么我们直接加入,并且视之为当前节点,假设该点              存在open中,那么我们比較G值,假设发现当

A星算法入门之入ing...

几天以来的瞎折腾,能算入门么? 漫漫几千里,A星算法这么走. 测试程序: public class AStarTest { /** * @param args */ public static void main(String[] args) { int[][] mySearchArea = new int[][] { {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 0, 1, 1, 1}, {1, 1, 1, 1, 0, 1, 1, 1}, {1, 1, 1, 1

【机器学习算法-python实现】K-means无监督学习实现分类

1.背景 无监督学习的定义就不多说了,不懂得可以google.因为项目需要,需要进行无监督的分类学习. K-means里面的K指的是将数据分成的份数,基本上用的就是算距离的方法. 大致的思路就是给定一个矩阵,假设K的值是2,也就是分成两个部分,那么我们首先确定两个质心.一开始是找矩阵每一列的最大值max,最小值min,算出range=max-min,然后设质心就是min+range*random.之后在逐渐递归跟进,其实要想明白还是要跟一遍代码,自己每一步都输出一下看看跟自己想象的是否一样. (

A星算法(Java实现)

一.适用场景 在一张地图中.绘制从起点移动到终点的最优路径,地图中会有障碍物.必须绕开障碍物. 二.算法思路 1. 回溯法得到路径 (假设有路径)採用"结点与结点的父节点"的关系从终于结点回溯到起点,得到路径. 2. 路径代价的估算:F = G+H A星算法的代价计算使用了被称作是启示式的代价函数. 先说明一下各符号意义:G表示的是从起点到当前结点的实际路径代价(为啥叫实际?就是已经走过了,边走边将代价计算好了).H表示当前结点到达终于结点的预计代价(为啥叫预计?就是还没走过,不知道前