A*(A星)算法Go lang实现
之前发表一个A*的python实现,连接:点击打开链接
最近正在学习Go语言,基本的语法等东西已经掌握了。但是纸上得来终觉浅,绝知此事要躬行嘛。必要的练手是一定要做的。正好离写python版的A*不那么久远。这个例子复杂度中等。还可以把之前用python实现是没有考虑的部分整理一下。
这一版的GO实现更加模块化了,同时用二叉堆来保证了openlist的查找性能。可以说离应用到实现工程中的要求差距不太远了。
package main
import (
"container/heap"
"fmt"
"math"
"strings"
)
import "strconv"
type _Point struct {
x int
y int
view string
}
//========================================================================================
// 保存地图的基本信息
type Map struct {
points [][]_Point
blocks map[string]*_Point
maxX int
maxY 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 row
m.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 {
_Point
father *_AstarPoint
gVal int
hVal int
fVal 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 []*_AstarPoint
func (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 := *this
n := len(old)
x := old[n-1]
*this = old[0 : n-1]
return x
}
//========================================================================================
type SearchRoad struct {
theMap *Map
start _AstarPoint
end _AstarPoint
closeLi map[string]*_AstarPoint
openLi OpenList
openSet map[string]*_AstarPoint
TheRoad []*_AstarPoint
}
func NewSearchRoad(startx, starty, endx, endy int, m *Map) *SearchRoad {
sr := &SearchRoad{}
sr.theMap = m
sr.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.father
existAP.father = curPoint
existAP.calcGVal()
// 如果新的节点的G值还不如老的节点就恢复老的节点
if existAP.gVal > oldGVal {
// restore father
existAP.father = oldFather
existAP.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呈现 ...
随机推荐
- Dalvik opcodes
原文地址: http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html Dalvik opcodes Author: Gabor Paller V ...
- jquery学习笔记(4)--实现table隔行变色以及单选框选中
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> &l ...
- python实现决策树
1.决策树的简介 http://www.cnblogs.com/lufangtao/archive/2013/05/30/3103588.html 2.决策是实现的伪代码 “读入训练数据” “找出每个 ...
- 在openSUSE13.2上gem install rails -v 4.1成功,但是之后不存在rails命令解决
解决方案为,不要用sudo gem install就好了,卧槽
- 银行卡BIN码大全
BIN号即银行标识代码的英文缩写.BIN由6位数字表示,出现在卡号的前6位,由国际标准化组织(ISO)分配给各从事跨行转接交换的银行卡组织.银行卡的卡号是标识发卡机构和持卡人信息的号码,由以下三部分组 ...
- JavaScript高级程序设计之Date类型
ECMAScript 中的 Date 类型是在早期 Java 的 java.util.Date 类基础上构建的. Date 类型使用自 UTC (国际协调时间)1970年1月1日午夜(零时)开始经过的 ...
- Oracle用户,权限,角色以及登录管理 scoot 授权
Oracle用户,权限,角色以及登录管理 1. sys和system用户的区别 system用户只能用normal身份登陆em.除非你对它授予了sysdba的系统权限或者syspoer系统权限. sy ...
- 10个 iOS 用户暂可以嘲笑 Android 的特点
Android 与 iOS 设备之间的争斗从未停止,毕竟一切高科技产品的理念和实际表现方式都不相同.就拿 Android 来说,很多功能令用户并 不太开心,甚至是令人愤怒,下面让我们来简单的盘点 10 ...
- xcode 产生指定颜色的图片imageWithColor
是在万能的stackOverflow上找到的答案,留下了, 原地址:http://stackoverflow.com/questions/6496441/creating-a-uiimage-from ...
- [转]gdb结合coredump定位崩溃进程
[转]gdb结合coredump定位崩溃进程 http://blog.sina.com.cn/s/blog_54f82cc201013tk4.html Linux环境下经常遇到某个进程挂掉而找不到原因 ...