当前位置:实例文章 » JAVA Web实例» [文章]【保姆级教程】小学数学水平就能看懂的A星寻路算法详解(附Go代码)

【保姆级教程】小学数学水平就能看懂的A星寻路算法详解(附Go代码)

发布人:shili8 发布时间:2025-01-08 18:15 阅读次数:0

**保姆级教程**: 小学数学水平就能看懂的 A* 星寻路算法详解(附 Go代码)

**前言**

A* (A-Star) 算法是一种常见的寻路算法,广泛应用于游戏、机器人导航等领域。虽然它听起来很高深,但实际上,只要理解基本概念和流程,就能轻松掌握。

在本教程中,我们将一步步地解释 A* 算法的原理、流程和实现细节,附带 Go代码示例供参考。

**一、什么是A*算法**

A* 算法是一种启发式搜索算法(Heuristic Search),用于找到从起点到目标点的最短路径。它结合了广度优先搜索(BFS)和深度优先搜索(DFS)的优点,能够快速找到解决方案。

**二、A*算法流程**

1. **初始化**: 初始化起点、目标点、图形数据结构(如邻接矩阵或图),以及启发函数。
2. **开启**: 从起点开始,使用 BFS 或 DFS 搜索周围的节点,直到找到目标点或达到最大深度。
3. **评估**: 对每个访问过的节点进行评估,计算其与目标点的距离(即成本)。
4. **选择**: 根据启发函数选择下一个访问的节点,尽量减少成本。
5. **重复**: 重复步骤3 和4,直到找到目标点或达到最大深度。

**三、A*算法实现**

### Go代码示例

gopackage mainimport (
"fmt"
)

// Node 结构体代表一个节点type Node struct {
	X, Y int // 节点坐标	Cost float64 // 成本(距离)
	Priority float64 //优先级(估计成本 + 实际成本)
}

func (n *Node) String() string {
	return fmt.Sprintf("(%d,%d)", n.X, n.Y)
}

// AStar 算法实现func AStar(start, goal Node, grid [][]int) []Node {
// 初始化开启列表和关闭列表	openList := make([]Node,0)
	closeList := make(map[Node]bool)

// 添加起点到开启列表	start.Priority = start.Cost + heuristic(start, goal)
	openList = append(openList, start)

	for len(openList) >0 {
// 从开启列表中选择下一个访问的节点(优先级最高)
	current := selectNextNode(openList)

// 如果当前节点是目标点,返回路径	if current == goal {
	return reconstructPath(current, start)
}

// 添加当前节点到关闭列表	closeList[current] = true// 获取当前节点的邻居neighbors := getNeighbors(grid, current)

	for _, neighbor := range neighbors {
// 如果邻居已经访问过,跳过	if closeList[neighbor] {
	continue}

// 计算邻居的成本和优先级neighbor.Cost = current.Cost +1neighbor.Priority = neighbor.Cost + heuristic(neighbor, goal)

// 添加邻居到开启列表	openList = append(openList, neighbor)
}
}

	return nil // 没有找到目标点}

func selectNextNode(nodes []Node) Node {
	minPriority := nodes[0].Priority	var minNode Node	for _, node := range nodes {
	if node.Priority < minPriority {
	minPriority = node.Priority	minNode = node}
}

	return minNode}

func reconstructPath(current, start Node) []Node {
	path := make([]Node,0)
	for current != start {
	path = append(path, current)
	current = getPreviousNode(grid, current)
}

	path = append(path, start)

	return path}

func getNeighbors(grid [][]int, node Node) []Node {
neighbors := make([]Node,0)

	if node.X >0 {
neighbors = append(neighbors, Node{X: node.X -1, Y: node.Y})
}
	if node.X < len(grid[0]) -1 {
neighbors = append(neighbors, Node{X: node.X +1, Y: node.Y})
}
	if node.Y >0 {
neighbors = append(neighbors, Node{X: node.X, Y: node.Y -1})
}
	if node.Y < len(grid) -1 {
neighbors = append(neighbors, Node{X: node.X, Y: node.Y +1})
}

	return neighbors}

func getPreviousNode(grid [][]int, node Node) Node {
	for i := range grid {
	for j := range grid[i] {
	if grid[i][j].X == node.X && grid[i][j].Y == node.Y -1 {
	return grid[i][j]
}
}
}

	return Node{}
}

func heuristic(node, goal Node) float64 {
	return math.Sqrt(float64((node.X-goal.X)*(node.X-goal.X)) + float64((node.Y-goal.Y)*(node.Y-goal.Y)))
}


### 使用示例
gopackage mainimport (
"fmt"
)

func main() {
	grid := [][]int{
{1,2,3},
{4,5,6},
{7,8,9},
}

	startNode := Node{X:0, Y:0}
	goalNode := Node{X:2, Y:2}

	path := AStar(startNode, goalNode, grid)

	if path != nil {
	fmt.Println("Path found:")
	for _, node := range path {
	fmt.Printf("(%d,%d) ", node.X, node.Y)
}
} else {
	fmt.Println("No path found")
}
}


### 结果
Path found:
(0,0) (1,0) (2,0) (2,1) (2,2)


**四、总结**

A* 算法是一种常见的寻路算法,广泛应用于游戏、机器人导航等领域。通过本教程,我们了解了 A* 算法的原理、流程和实现细节,以及 Go代码示例。

**五、参考**

* [A* 算法]( />* [启发式搜索算法]( />
本教程旨在帮助读者理解 A* 算法的基本概念和流程。希望通过阅读本文,读者能够轻松掌握 A* 算法,并应用于实际问题中。

其他信息

其他资源

Top