在春节放假前两天我偶然看到了A\*算法(A\*算法是一个启发式的地图寻路算法),感觉挺有意思。正好放假前也没有什么事情,就花了一个下午写出算法的骨架,节后又花了半天时间完善屏幕输出的细节并且调试完成。
该实现只是一时兴起的随手而作,没有考虑性能和扩展性等问题。正在学习A\*算法的朋友可以拿去随便折腾。  
                             Email: wang.zhigang@hotmail.com
                             
代码的运行效果如下:

 

```pytho
#!/usr/bin/python​
# vim:set fileencoding=utf-8

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

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

  1. POJ 2449 Remmarguts' Date (SPFA + A星算法) - from lanshui_Yang

    题目大意:给你一个有向图,并给你三个数s.t 和 k ,让你求从点 s 到 点 t 的第 k 短的路径.如果第 k 短路不存在,则输出“-1” ,否则,输出第 k 短路的长度. 解题思路:这道题是一道 ...

  2. 算法起步之A星算法

    原文:算法起步之A星算法 用途: 寻找最短路径,优于bfs跟dfs 描述: 基本描述是,在深度优先搜索的基础上,增加了一个启发式算法,在选择节点的过程中,不是盲目选择,而是有目的的选的,F=G+H,f ...

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

    A *搜索算法称为A星算法.这是一个在图形平面,路径.求出最低通过成本的算法. 经常使用于游戏中的NPC的移动计算,或线上游戏的BOT的移动计算上. 首先:1.在Map地图中任取2个点,開始点和结束点 ...

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

    A*搜寻算法[编辑] 维基百科,自由的百科全书 本条目需要补充更多来源.(2015年6月30日) 请协助添加多方面可靠来源以改善这篇条目,无法查证的内容可能会被提出异议而移除. A*搜索算法,俗称A星 ...

  5. pageRank算法 python实现

    一.什么是pagerank PageRank的Page可是认为是网页,表示网页排名,也可以认为是Larry Page(google 产品经理),因为他是这个算法的发明者之一,还是google CEO( ...

  6. 常见排序算法-Python实现

    常见排序算法-Python实现 python 排序 算法 1.二分法     python    32行 right = length-  :  ]   ):  test_list = [,,,,,, ...

  7. kmp算法python实现

    kmp算法python实现 kmp算法 kmp算法用于字符串的模式匹配,也就是找到模式字符串在目标字符串的第一次出现的位置比如abababc那么bab在其位置1处,bc在其位置5处我们首先想到的最简单 ...

  8. Java开源-astar:A 星算法

    astar A星算法Java实现 一.适用场景 在一张地图中,绘制从起点移动到终点的最优路径,地图中会有障碍物,必须绕开障碍物. 二.算法思路 1. 回溯法得到路径 (如果有路径)采用“结点与结点的父 ...

  9. KMP算法-Python版

                               KMP算法-Python版 传统法: 从左到右一个个匹配,如果这个过程中有某个字符不匹配,就跳回去,将模式串向右移动一位.这有什么难的? 我们可以 ...

  10. A星算法(Java实现)

    一.适用场景 在一张地图中.绘制从起点移动到终点的最优路径,地图中会有障碍物.必须绕开障碍物. 二.算法思路 1. 回溯法得到路径 (假设有路径)採用"结点与结点的父节点"的关系从 ...

随机推荐

  1. 学习c语言的第9天

    #include <stdio.h> int main() { float sum=0,wage=0; int i=1; int num; printf("+++平均工资统计程序 ...

  2. Redis监控方案

    Redis 监控最直接的方法当然就是使用系统提供的 info 命令来做了,你只需要执行下面一条命令,就能获得 Redis 系统的状态报告. redis-cli info 内存使用 如果 Redis 使 ...

  3. PHP导出excel文件

    现在教教你如何导入excel文件: 在我的文件储存里面有一个com文件夹的,将其解压放在ThinkPHP/Library/文件夹里面,然后就是写控制器啦!去调用这个插件: <?php names ...

  4. php去除换行(回车换行)的方法

    php去除换行(回车换行)的三种方法. 代码: <?php     //php 不同系统的换行   //不同系统之间换行的实现是不一样的   //linux 与unix中用 \n   //MAC ...

  5. 通过API函数来控制SQLite数据库增删改查

    person类属性有Intenger id,String name,Intenger  age,相应的构造方法和set get方法. package com.xh.tx.dao; import and ...

  6. vagrant

    puppet chef ansible salt docker https://github.com/ansible/ansiblehttps://github.com/saltstack/salth ...

  7. 菜鸟学习Spring——60s配置XML方法实现简单AOP

    一.概述. 上一篇博客讲述了用注解的形式实现AOP现在讲述另外一种AOP实现的方式利用XML来实现AOP. 二.代码演示. 准备工作参照上一篇博客<菜鸟学习Spring--60s使用annota ...

  8. Git 设置别名[alias]

    工作中我经常设置一下别名... 别名就在[alias]后面,要删除别名,直接把对应的行删掉即可. 而当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig中: $ cat .git ...

  9. Karaf 依赖equinox and felix,karaf 本Apache的很多项目作为基础框架

    6月17日是Apache Karaf作为Apache顶级项目.Karaf是个运行时包,包含了一个OSGi框架(Equinox或Felix).一个命令shell(Felix Gogo)及默认情况下内置的 ...

  10. 无法产生coredump的问题

    我写了一个必然会崩溃的程序,名字为 test :#include "stdlib.h"#include "unistd.h" int main(){ char ...