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呈现 ...
随机推荐
- AeroSpike 资料
文档总览:http://www.aerospike.com/docs/ JAVA AeroSpike知识总览:http://www.aerospike.com/docs/client/java/sta ...
- PHP 定时任务|Cron
一. Crontab 介绍 crontab命令的功能是在一定的时间间隔调度一些命令的执行.在/etc目录下有一个crontab文件,这里存放有系统运行的一些调度程序.每个用户可以建立自己的调度cro ...
- 在xml中添加array
在values建立arrays(名字可自定义)的xml: <?xml version="1.0" encoding="utf-8"?> <re ...
- Eclipse插件推荐:UCDetector: Unnecessary Code Detector
正如其名,检查不必要的代码. 下载地址为:http://sourceforge.net/projects/ucdetector/files/latest/download?source=files 官 ...
- 十天学会单片机Day5 IIC总线AT2402芯片(EEPROM)应用
1.采用串行总线技术可以使系统的硬件设计大大简化.系统的体积减小.可靠性提高.同时,系统的更改和扩充极为容易. 常用的串行扩展总线有: IIC (Inter IC BUS)总线.单总线(1-WIRE ...
- python杂记-4(迭代器&生成器)
#!/usr/bin/env python# -*- coding: utf-8 -*-#1.迭代器&生成器#生成器#正确的方法是使用for循环,因为generator也是可迭代对象:g = ...
- 【FAQ】【JSP】HTTP Status 500 - Summary(问题排查时候应该仔细分析所有的错误打印说明)
Question 1.HTTP Status 500 - Unable to compile class for JSP:'***' cannot be resolved to a type 原因分析 ...
- VPN错误800、错误789
VPN突然无法连接解决方法: 1. 单击“开始”,单击“运行”,键入“regedit”,然后单击“确定” 2. 找到下面的注册表子项,然后单击它:HKEY_LOCAL_MACHINE\System\C ...
- hdu 2544 最短路
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=2544 最短路 Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shi ...
- jquery 简单弹出层
预定义html代码:没有 所有代码通过js生成和移除. 预定义css .z-popup-overlay{ width:100%; min-height: 100%; height:800px; pos ...