A*(A星)算法Go lang实现
之前发表一个A*的python实现,连接:点击打开链接
最近正在学习Go语言,基本的语法等东西已经掌握了。但是纸上得来终觉浅,绝知此事要躬行嘛。必要的练手是一定要做的。正好离写python版的A*不那么久远。这个例子复杂度中等。还可以把之前用python实现是没有考虑的部分整理一下。
这一版的GO实现更加模块化了,同时用二叉堆来保证了openlist的查找性能。可以说离应用到实现工程中的要求差距不太远了。
package mainimport ("container/heap""fmt""math""strings")import "strconv"type _Point struct {x inty intview string}//========================================================================================// 保存地图的基本信息type Map struct {points [][]_Pointblocks map[string]*_PointmaxX intmaxY int}func NewMap(charMap []string) (m Map) {m.points = make([][]_Point, len(charMap))m.blocks = make(map[string]*_Point, len(charMap)*2)for x, row := range charMap {cols := strings.Split(row, " ")m.points[x] = make([]_Point, len(cols))for y, view := range cols {m.points[x][y] = _Point{x, y, view}if view == "X" {m.blocks[pointAsKey(x, y)] = &m.points[x][y]}} // end of cols} // end of rowm.maxX = len(m.points)m.maxY = len(m.points[0])return m}func (this *Map) getAdjacentPoint(curPoint *_Point) (adjacents []*_Point) {if x, y := curPoint.x, curPoint.y-1; x >= 0 && x < this.maxX && y >= 0 && y < this.maxY {adjacents = append(adjacents, &this.points[x][y])}if x, y := curPoint.x+1, curPoint.y-1; x >= 0 && x < this.maxX && y >= 0 && y < this.maxY {adjacents = append(adjacents, &this.points[x][y])}if x, y := curPoint.x+1, curPoint.y; x >= 0 && x < this.maxX && y >= 0 && y < this.maxY {adjacents = append(adjacents, &this.points[x][y])}if x, y := curPoint.x+1, curPoint.y+1; x >= 0 && x < this.maxX && y >= 0 && y < this.maxY {adjacents = append(adjacents, &this.points[x][y])}if x, y := curPoint.x, curPoint.y+1; x >= 0 && x < this.maxX && y >= 0 && y < this.maxY {adjacents = append(adjacents, &this.points[x][y])}if x, y := curPoint.x-1, curPoint.y+1; x >= 0 && x < this.maxX && y >= 0 && y < this.maxY {adjacents = append(adjacents, &this.points[x][y])}if x, y := curPoint.x-1, curPoint.y; x >= 0 && x < this.maxX && y >= 0 && y < this.maxY {adjacents = append(adjacents, &this.points[x][y])}if x, y := curPoint.x-1, curPoint.y-1; x >= 0 && x < this.maxX && y >= 0 && y < this.maxY {adjacents = append(adjacents, &this.points[x][y])}return adjacents}func (this *Map) PrintMap(path *SearchRoad) {fmt.Println("map's border:", this.maxX, this.maxY)for x := 0; x < this.maxX; x++ {for y := 0; y < this.maxY; y++ {if path != nil {if x == path.start.x && y == path.start.y {fmt.Print("S")goto NEXT}if x == path.end.x && y == path.end.y {fmt.Print("E")goto NEXT}for i := 0; i < len(path.TheRoad); i++ {if path.TheRoad[i].x == x && path.TheRoad[i].y == y {fmt.Print("*")goto NEXT}}}fmt.Print(this.points[x][y].view)NEXT:}fmt.Println()}}func pointAsKey(x, y int) (key string) {key = strconv.Itoa(x) + "," + strconv.Itoa(y)return key}//========================================================================================type _AstarPoint struct {_Pointfather *_AstarPointgVal inthVal intfVal int}func NewAstarPoint(p *_Point, father *_AstarPoint, end *_AstarPoint) (ap *_AstarPoint) {ap = &_AstarPoint{*p, father, 0, 0, 0}if end != nil {ap.calcFVal(end)}return ap}func (this *_AstarPoint) calcGVal() int {if this.father != nil {deltaX := math.Abs(float64(this.father.x - this.x))deltaY := math.Abs(float64(this.father.y - this.y))if deltaX == 1 && deltaY == 0 {this.gVal = this.father.gVal + 10} else if deltaX == 0 && deltaY == 1 {this.gVal = this.father.gVal + 10} else if deltaX == 1 && deltaY == 1 {this.gVal = this.father.gVal + 14} else {panic("father point is invalid!")}}return this.gVal}func (this *_AstarPoint) calcHVal(end *_AstarPoint) int {this.hVal = int(math.Abs(float64(end.x-this.x)) + math.Abs(float64(end.y-this.y)))return this.hVal}func (this *_AstarPoint) calcFVal(end *_AstarPoint) int {this.fVal = this.calcGVal() + this.calcHVal(end)return this.fVal}//========================================================================================type OpenList []*_AstarPointfunc (self OpenList) Len() int { return len(self) }func (self OpenList) Less(i, j int) bool { return self[i].fVal < self[j].fVal }func (self OpenList) Swap(i, j int) { self[i], self[j] = self[j], self[i] }func (this *OpenList) Push(x interface{}) {// Push and Pop use pointer receivers because they modify the slice's length,// not just its contents.*this = append(*this, x.(*_AstarPoint))}func (this *OpenList) Pop() interface{} {old := *thisn := len(old)x := old[n-1]*this = old[0 : n-1]return x}//========================================================================================type SearchRoad struct {theMap *Mapstart _AstarPointend _AstarPointcloseLi map[string]*_AstarPointopenLi OpenListopenSet map[string]*_AstarPointTheRoad []*_AstarPoint}func NewSearchRoad(startx, starty, endx, endy int, m *Map) *SearchRoad {sr := &SearchRoad{}sr.theMap = msr.start = *NewAstarPoint(&_Point{startx, starty, "S"}, nil, nil)sr.end = *NewAstarPoint(&_Point{endx, endy, "E"}, nil, nil)sr.TheRoad = make([]*_AstarPoint, 0)sr.openSet = make(map[string]*_AstarPoint, m.maxX+m.maxY)sr.closeLi = make(map[string]*_AstarPoint, m.maxX+m.maxY)heap.Init(&sr.openLi)heap.Push(&sr.openLi, &sr.start) // 首先把起点加入开放列表sr.openSet[pointAsKey(sr.start.x, sr.start.y)] = &sr.start// 将障碍点放入关闭列表for k, v := range m.blocks {sr.closeLi[k] = NewAstarPoint(v, nil, nil)}return sr}func (this *SearchRoad) FindoutRoad() bool {for len(this.openLi) > 0 {// 将节点从开放列表移到关闭列表当中。x := heap.Pop(&this.openLi)curPoint := x.(*_AstarPoint)delete(this.openSet, pointAsKey(curPoint.x, curPoint.y))this.closeLi[pointAsKey(curPoint.x, curPoint.y)] = curPoint//fmt.Println("curPoint :", curPoint.x, curPoint.y)adjacs := this.theMap.getAdjacentPoint(&curPoint._Point)for _, p := range adjacs {//fmt.Println("\t adjact :", p.x, p.y)theAP := NewAstarPoint(p, curPoint, &this.end)if pointAsKey(theAP.x, theAP.y) == pointAsKey(this.end.x, this.end.y) {// 找出路径了, 标记路径for theAP.father != nil {this.TheRoad = append(this.TheRoad, theAP)theAP.view = "*"theAP = theAP.father}return true}_, ok := this.closeLi[pointAsKey(p.x, p.y)]if ok {continue}existAP, ok := this.openSet[pointAsKey(p.x, p.y)]if !ok {heap.Push(&this.openLi, theAP)this.openSet[pointAsKey(theAP.x, theAP.y)] = theAP} else {oldGVal, oldFather := existAP.gVal, existAP.fatherexistAP.father = curPointexistAP.calcGVal()// 如果新的节点的G值还不如老的节点就恢复老的节点if existAP.gVal > oldGVal {// restore fatherexistAP.father = oldFatherexistAP.gVal = oldGVal}}}}return false}//========================================================================================func main() {presetMap := []string{". . . . . . . . . . . . . . . . . . . . . . . . . . .",". . . . . . . . . . . . . . . . . . . . . . . . . . .",". . . . . . . . . . . . . . . . . . . . . . . . . . .","X . X X X X X X X X X X X X X X X X X X X X X X X X X",". . . . . . . . . . . . . . . . . . . . . . . . . . .",". . . . . . . . . . . . . . . . . . . . . . . . . . .",". . . . . . . . . . . . . . . . . . . . . . . . . . .",". . . . . . . . . . . . . . . . . . . . . . . . . . .",". . . . . . . . . . . . . . . . . . . . . . . . . . .",". . . . . . . . . . . . . . . . . . . . . . . . . . .",". . . . . . . . . . . . . . . . . . . . . . . . . . .","X X X X X X X X X X X X X X X X X X X X X X X X . X X",". . . . . . . . . . . . . . . . . . . . . . . . . . .",". . . . . . . . . . . . . . . . . . . . . . . . . . .",". . . . . . . . . . . . . . . . . . . . . . . . . . .",". . . . . . . . . . . . . . . . . . . . . . . . . . .",". . . . . . . . . . . . . . . . . . . . . . . . . . .",". . . . . . . . . . . . . . . . . . . . . . . . . . .",". . . . . . . . . . . . . . . . . . . . . . . . . . .",}m := NewMap(presetMap)m.PrintMap(nil)searchRoad := NewSearchRoad(0, 0, 18, 10, &m)if searchRoad.FindoutRoad() {fmt.Println("找到了, 你看!")m.PrintMap(searchRoad)} else {fmt.Println("找不到路径!")}}
A*(A星)算法Go lang实现的更多相关文章
- POJ 2449 Remmarguts' Date (SPFA + A星算法) - from lanshui_Yang
题目大意:给你一个有向图,并给你三个数s.t 和 k ,让你求从点 s 到 点 t 的第 k 短的路径.如果第 k 短路不存在,则输出“-1” ,否则,输出第 k 短路的长度. 解题思路:这道题是一道 ...
- 算法起步之A星算法
原文:算法起步之A星算法 用途: 寻找最短路径,优于bfs跟dfs 描述: 基本描述是,在深度优先搜索的基础上,增加了一个启发式算法,在选择节点的过程中,不是盲目选择,而是有目的的选的,F=G+H,f ...
- Cocos2d-x 3.1.1 学习日志16--A星算法(A*搜索算法)学问
A *搜索算法称为A星算法.这是一个在图形平面,路径.求出最低通过成本的算法. 经常使用于游戏中的NPC的移动计算,或线上游戏的BOT的移动计算上. 首先:1.在Map地图中任取2个点,開始点和结束点 ...
- A*搜寻算法(A星算法)
A*搜寻算法[编辑] 维基百科,自由的百科全书 本条目需要补充更多来源.(2015年6月30日) 请协助添加多方面可靠来源以改善这篇条目,无法查证的内容可能会被提出异议而移除. A*搜索算法,俗称A星 ...
- Java开源-astar:A 星算法
astar A星算法Java实现 一.适用场景 在一张地图中,绘制从起点移动到终点的最优路径,地图中会有障碍物,必须绕开障碍物. 二.算法思路 1. 回溯法得到路径 (如果有路径)采用“结点与结点的父 ...
- A星算法(Java实现)
一.适用场景 在一张地图中.绘制从起点移动到终点的最优路径,地图中会有障碍物.必须绕开障碍物. 二.算法思路 1. 回溯法得到路径 (假设有路径)採用"结点与结点的父节点"的关系从 ...
- JAVA根据A星算法规划起点到终点二维坐标的最短路径
工具类 AStarUtil.java import java.util.*; import java.util.stream.Collectors; /** * A星算法工具类 */ public c ...
- AStar A* A星 算法TypeScript版本
一 演示效果 二 参考教程 <ActionScript3.0 高级动画教程> + 源码 http://download.csdn.net/download/zhengchengpeng/ ...
- 基于HTML5的WebGL呈现A星算法3D可视化
http://www.hightopo.com/demo/astar/astar.html 最近搞个游戏遇到最短路径的常规游戏问题,一时起兴基于HT for Web写了个A*算法的WebGL 3D呈现 ...
随机推荐
- 关于MongoDb Replica Set的故障转移集群——理论篇
自从10 gen用Replica Set取代Master/Slave方案后生活其实已经容易多了,但是真正实施起来还是会发现各种各样的小问题,如果不小心一样会栽跟头. 在跟Replica Set血拼几天 ...
- redis的安装过程基本配置及遇到问题的解决
下载软件包 在centos下如果没有wget先安装 wgetyum -y install wgetwget http://download.redis.io/releases/redis-3.0.0. ...
- arcgis api for javascript 3.16开发(一)
原来一直都在用Flex开发arcgis的地图接口,用的时间很长,用的习惯也顺手,可Flex这个开发工具已经基本要淘汰了,并且地图借助flash的方式加载在浏览器里已经不能适应webgis的快速开发需求 ...
- 一个封装好的CSV文件操作C#类代码
using System.Data; using System.IO; namespace DotNet.Utilities { /// <summary> /// CSV文件转换类 // ...
- virtualenv 安装
virtualenv 是一个创建隔离的Python环境的工具. virtualenv要解决的根本问题是库的版本和依赖,以及权限问题.假设你有一个程序,需要LibFoo的版本1,而另一个程序需要版本2, ...
- Python学习教程(learning Python)--3.3.2 Python的关系运算
如果if的condition不用布尔表达式来做条件判断而采用关系表达式,实际上关系表达式运算的结果要么是True要么是False.下面我们先了解一些有关关系运算符的基础知识,如下表所示. 做个小程序测 ...
- java学习资源汇总
http://www.tutorialspoint.com/jsp/jsp_standard_tag_library.htm
- C# 页面抓取类
抓取网站页面的内容,简单的类应用,代码如下: /// <summary> /// 获取页面内容 /// </summary> /// <param name=" ...
- SOCKET 地址
地址格式: 函数bind和getsockname使用通用数据类型:struct sockaddr*来指向socket地址. #incude <sys/socket.h> struct so ...
- hdu 1867 A + B for you again
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1867 A + B for you again Description Generally speaki ...