A 寻路算法,用于在 六边形网格

2026-03-04 14:40:24

我们要实现一个 A 寻路算法,用于在 六边形网格 上:

  1. 找出从起点到终点的最短路径;
  2. 考虑移动距离限制(如最多走 5 步);
  3. 支持地形代价(如山地更难走)、敌人阻挡;
  4. 实现“可移动范围”显示(类似游戏中的蓝色高亮区域)。

🧩 一、六边形网格基础

1. 六边形坐标系统

常用两种表示方式:

  1. 轴向坐标(Axial Coordinates)
  2. 立方体坐标(Cube Coordinates)

我们使用 轴向坐标q, r),因为简单且适合 A。

🔹 坐标示例(轴向)

text

编辑




(0,1)
(-1,1) (0,0) (1,0)
(-1,0) (0,-1)
(1,-1)

🔹 六边形邻居

每个六边形有 6 个邻居,方向如下:

python

编辑




directions = [
(1, 0), # 右
(1, -1), # 右下
(0, -1), # 左下
(-1, 0), # 左
(-1, 1), # 左上
(0, 1) # 右上
]
注意:实际布局取决于六边形是“平顶”还是“尖顶”,这里假设为“平顶”。

💡 二、A 在六边形上的实现(Python)

python

编辑




import heapq
from typing import List, Tuple, Optional

class HexGrid:
def __init__(self, width: int, height: int):
self.width = width
self.height = height
# grid[r][q] 表示位置 (q, r) 的状态
# 0: 可通行, 1: 障碍物, 2: 敌人, 3: 友军
self.grid = [[0 for _ in range(width)] for _ in range(height)]
def is_valid(self, q: int, r: int) -> bool:
return 0 <= q < self.width and 0 <= r < self.height
def is_blocked(self, q: int, r: int) -> bool:
if not self.is_valid(q, r):
return True
return self.grid[r][q] == 1 # 障碍物不可通行
def get_cost(self, q: int, r: int) -> float:
"""返回移动到该格子的代价"""
if not self.is_valid(q, r):
return float('inf')
terrain = self.grid[r][q]
if terrain == 0: # 平地
return 1.0
elif terrain == 1: # 障碍
return float('inf')
elif terrain == 2: # 敌人
return 2.0 # 可移动但代价更高
elif terrain == 3: # 友军
return 1.0 # 可移动
return 1.0

def a_star_hex(grid: HexGrid, start: Tuple[int, int], goal: Tuple[int, int], max_steps: int = 5) -> Optional[List[Tuple[int, int]]]:
"""
六边形网格上的 A* 寻路
:param grid: HexGrid 对象
:param start: 起点 (q, r)
:param goal: 终点 (q, r)
:param max_steps: 最大移动步数(如 5)
:return: 路径列表 或 None
"""
# 方向:六个邻居
directions = [(1, 0), (1, -1), (0, -1), (-1, 0), (-1, 1), (0, 1)]

def heuristic(a: Tuple[int, int], b: Tuple[int, int]) -> int:
"""六边形曼哈顿距离(也叫 Chebyshev 距离)"""
q1, r1 = a
q2, r2 = b
return (abs(q1 - q2) + abs(q1 + r1 - q2 - r2) + abs(r1 - r2)) // 2

open_set = []
heapq.heappush(open_set, (0, 0, start))
came_from = {}
g_score = {start: 0}
f_score = {start: heuristic(start, goal)}

while open_set:
_, current_g, current = heapq.heappop(open_set)

if current == goal:
path = []
while current in came_from:
path.append(current)
current = came_from[current]
path.append(start)
return path[::-1]

# 如果已走超过最大步数,跳过
if current_g >= max_steps:
continue

for dq, dr in directions:
neighbor = (current[0] + dq, current[1] + dr)
nq, nr = neighbor

if not grid.is_valid(nq, nr) or grid.is_blocked(nq, nr):
continue

tentative_g = current_g + grid.get_cost(nq, nr)

if tentative_g >= max_steps:
continue # 超过最大移动距离,跳过

if neighbor not in g_score or tentative_g < g_score[neighbor]:
came_from[neighbor] = current
g_score[neighbor] = tentative_g
f_score[neighbor] = tentative_g + heuristic(neighbor, goal)
heapq.heappush(open_set, (f_score[neighbor], tentative_g, neighbor))

return None # 无路径

🎮 三、如何实现“可移动范围”?

在游戏中,点击武将时会显示一个蓝色区域,表示他能移动到的所有格子。


声明:该内容由作者自行发布,观点内容仅供参考,不代表平台立场;如有侵权,请联系平台删除。
标签:
边缘 AI
多模态大模型