A 星寻路算法实现的细节

本站文章均为 ftyszyx 原创,转载务必在明显处注明: 原文链接: http://blog.csdn.net/ftyszyx/article/details/9019763

最近学习了A星寻路算法,于是自己照着网上的思路写了一个,发现理论看起来简单,但是真正实现起来,发现很多细节没有注意到,导致最终错误,因此在此记录,以备以后查用。

首先说下A星算法的思路:

添加起始节点到open列表中

循环做以下事情:(退出循环的条件是,open列表为空,获得者S为终点)

1.      将方块添加到open列表中,该列表有最小的和值。且将这个方块称为S吧。

2.      将S从open列表移除,然后添加S到closed列表中。

3.      对于与S相邻的每一块可通行的方块T:

·        如果T在closed列表中:不管它。

·        如果T不在open列表中:添加它然后计算出它的和值。

·        如果T已经在open列表中:当我们使用当前生成的路径到达那里时,检查F 和值是否更小。如果是,更新它的和值和它的前继。

 退出循环后,在close列表中,延目的节点的父节点一直反溯到起始节点,即可求得最终路径。


这里面,我觉得要注意以下几点:

1、open和close的数据结构推荐用list,因为程序执行过程中要经常的做插入节点操作

2、open列表的排序,我觉得用插入排序较好(因为插入新节点时,open列表原来的数据是有序的),可以在节点插入open列表时进行,

3、在open列表增加新节点时,如果插入时发现原列表中有节点的f值和自己相同,应该将新插入的节点放在前面(原则就是排在前面的尽量是最近插入的节点)

4、退出循环时,是通过close列表的最后一个节点(也就 是终点)回溯到起点求得路径,而不是把close表中的所有节点当作路径。这点要注意,我就在这里范过错。


下面附上自己的一些部分代码:

主要有三个函数findpath:寻路入口函数    JudgeNode:判断相信方块,主要实现上面的第3步  addToOpen:将节点加入到open表中(插入排序)

findpath()
{
//加入第一个结点
       AstarItem * temp1 = new AstarItem();
m_open->addObject(temp1);
temp1->setpos(m_curRow,m_curCol);
temp1->setg(0);
int ag = getH(m_curRow,m_curCol);
temp1->seth(ag);
temp1->setfid(0);
temp1->setf(ag);
 //遍历寻找路径
while(m_open->count() !=0)
{//open里面没数据
//在open里面找最小的f值
AstarItem * min=(AstarItem *)m_open->objectAtIndex(0);
int minCol=min->getcol();
int minRow=min->getrow();
//将该节点加入到close中,并从open中移除
m_close->addObject(min);
m_open->removeObjectAtIndex(0);
if (minCol==m_aimCol &&
minRow==m_aimRow)
{
//到终点了
foundpath=true;
break;
}

//查找与s相邻的区块
  int fatherid = m_close->count() - 1;
  //对周围的8个相邻节点做判断
  
  JudgeNode(minRow-1,minCol,fatherid);
  JudgeNode(minRow,minCol-1,fatherid);
  JudgeNode(minRow,minCol+1,fatherid);
  JudgeNode(minRow+1,minCol,fatherid);
//  if(checkmap())
  /*
  JudgeNode(minRow+1,minCol+1,fatherid);
  JudgeNode(minRow-1,minCol-1,fatherid);
  JudgeNode(minRow-1,minCol+1,fatherid);
  JudgeNode(minRow+1,minCol-1,fatherid);
  */
}
//算法结束


 //获得路径
if(foundpath == false)
{
  m_path=NULL;
}
else
{//延着终点节点遍历
m_path = new CCArray();
  AstarItem * temp2=(AstarItem * )(m_close->lastObject());
 // m_path->addObject(temp2);
  while(temp2->getfid()!=0)
  {
  m_path->insertObject(temp2,0);
  //取下一个
  temp2=(AstarItem *)(m_close->objectAtIndex(temp2->getfid())) ;
  }
  m_path->insertObject(temp2,0);
  m_path->insertObject(temp1,0);//第一个点
}
}


//判断周围的结点
void JudgeNode(int row,int col,int fatherid)
{
 int tempindex;
  if(true!=checkmap(row,col))
  {//不合格的位置
return ;
  }
  if(checkclose(row,col)==true)
  {//close表中有就跳过
 return;
  }
  tempindex=checkOpen(row,col,fatherid); 
  if(tempindex!=-1)
  {
  //原来就在open列表中,更新open列表的值
 int g = getG( row, col,fatherid);
 int h = getH( row,col);
 if (((AstarItem *)m_open->objectAtIndex(tempindex))->getf()>g+h)
 {
 //说明新的路径更短
 ((AstarItem *)m_open->objectAtIndex(tempindex))->setf(g+h);
((AstarItem *)m_open->objectAtIndex(tempindex))->setg(g);
((AstarItem *)m_open->objectAtIndex(tempindex))->seth(h);
((AstarItem *)m_open->objectAtIndex(tempindex))->setfid(fatherid);
 }
 return;
  }
  else
  {
 //直接将此节点加入
 addToOpen(row,col,fatherid);
  }
}

//添加一个节点到open中  插入时按从小到大排列
//注意,如果遇到相等的值,就将最新的元素插在前面。
bool addToOpen(int row,int col,int id)
{
    //向open列表中加入点

    AstarItem * temp = new AstarItem();
temp->setpos(row,col);
temp->setfid(id);
int g = getG( row,col, id);
int h = getH(row,col);
temp->setg(g);
temp->seth(h);
temp->setf(g + h);
int i=m_open->count()-1;
// 从后向前遍历
while(i>=0)
{

if(((AstarItem*)(m_open->objectAtIndex(i)))->getf()>=temp->getf())//当前位置的点比我大,就找下一个
{
i--;
continue;
}
else//找到一个f值小于等于自己的
{
i++;//插在这个数后面
break;
}
}
if (i<0)
{
i=0;
}
m_open->insertObject(temp,i);
return true;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python代码实现A算法可以使用以下代码:def astar(start, goal): closedset = set() openset = set([start]) came_from = {} gscore = {start: 0} fscore = {start: heuristic_cost_estimate(start, goal)} while openset: current = min(openset, key=fscore.get) if current == goal: return reconstruct_path(came_from, current) openset.remove(current) closedset.add(current) for neighbor in get_neighbors(current): if neighbor in closedset: continue tentative_gscore = gscore[current] + dist_between(current, neighbor) if neighbor not in openset: openset.add(neighbor) elif tentative_gscore >= gscore[neighbor]: continue came_from[neighbor] = current gscore[neighbor] = tentative_gscore fscore[neighbor] = gscore[neighbor] + heuristic_cost_estimate(neighbor, goal) return False ### 回答2: A算法是一种常用的径规划算法,可以在给定的地图中找到最短径。下面是用Python实现A算法的代码示例: ```python import heapq # 定义节点类 class Node: def __init__(self, row, col, g, h): self.row = row self.col = col self.g = g self.h = h def __lt__(self, other): return self.g + self.h < other.g + other.h # 计算启发式代价(h值) def heuristic(row, col, target_row, target_col): return abs(target_row - row) + abs(target_col - col) # A算法 def astar_search(start, target, grid): directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] # 上下左右四个方向 rows, cols = len(grid), len(grid[0]) visited = set() # 已访问的节点集合 pq = [] # 优先队列,用来选择下一个节点 heapq.heappush(pq, start) while pq: curr_node = heapq.heappop(pq) row, col = curr_node.row, curr_node.col visited.add((row, col)) if row == target.row and col == target.col: return curr_node.g for d in directions: new_row, new_col = row + d[0], col + d[1] if 0 <= new_row < rows and 0 <= new_col < cols and grid[new_row][new_col] != 1: new_g = curr_node.g + 1 new_h = heuristic(new_row, new_col, target.row, target.col) new_node = Node(new_row, new_col, new_g, new_h) if (new_row, new_col) not in visited: heapq.heappush(pq, new_node) return -1 # 示例 grid = [[0, 0, 0], [1, 1, 0], [0, 0, 0]] start = Node(0, 0, 0, 0) target = Node(2, 2, 0, 0) result = astar_search(start, target, grid) print(result) ``` 以上代码实现了A算法,并可用于找给定地图中起点到目标点的最短径。其中,`grid`是二维列表表示地图,在地图中,0表示可通过的节点,1表示不可通过的节点。`start`表示起点,`target`表示目标点。通过调用`astar_search`函数,将起点、目标点和地图作为参数进行传递,即可得到最短径的长度。 ### 回答3: A算法是一种常用于找最短径的算法,广泛应用于游戏开发、径规划等领域。下面是使用Python实现A算法的代码: ```python # 定义地图和起终点 map = [ [0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 0] ] start = (1, 1) # 起点坐标 goal = (6, 5) # 终点坐标 # 定义辅助函数 def heuristic(pos1, pos2): # 估算两点之间的距离(启发函数) x1, y1 = pos1 x2, y2 = pos2 return abs(x1 - x2) + abs(y1 - y2) def get_neighbors(pos): # 获取当前位置的邻近位置 x, y = pos neighbors = [] for dx in [-1, 0, 1]: for dy in [-1, 0, 1]: if dx == dy == 0: # 排除当前位置 continue new_x, new_y = x + dx, y + dy if 0 <= new_x < len(map) and 0 <= new_y < len(map[0]) and map[new_x][new_y] == 0: neighbors.append((new_x, new_y)) return neighbors # 定义A算法函数 def astar_search(start, goal): # 初始化起点和终点 open_list = [start] # 待探索的节点 came_from = {} # 记录径中每个节点的上一个节点 g_score = {start: 0} # 起点到每个节点的实际代价 f_score = {start: heuristic(start, goal)} # 起点到每个节点的估算代价(f_score = g_score + h_score) while open_list: current = min(open_list, key=lambda x: f_score[x]) # 获取f_score最小的节点 if current == goal: # 已到达终点 path = [] while current in came_from: path.append(current) current = came_from[current] path.append(start) path.reverse() return path open_list.remove(current) for neighbor in get_neighbors(current): g_temp = g_score[current] + 1 # 节点到邻近节点的代价为1 if neighbor not in g_score or g_temp < g_score[neighbor]: came_from[neighbor] = current g_score[neighbor] = g_temp f_score[neighbor] = g_temp + heuristic(neighbor, goal) if neighbor not in open_list: open_list.append(neighbor) return [] # 未找到径 # 在地图上运行A算法 path = astar_search(start, goal) print("径: ", path) ``` 该代码首先定义了一个地图,使用0表示可行走的区域,使用1表示障碍物。将起点和终点设定好后,通过`heuristic`函数计算两点间的估算距离。`get_neighbors`函数用于获取当前位置的邻近位置。 `astar_search`函数是实现A算法的核心部分。其中,`open_list`用于存放待探索的节点,`came_from`用于记录径中每个节点的上一个节点,`g_score`用于记录起点到每个节点的实际代价,`f_score`用于记录起点到每个节点的估算代价。算法使用一个循环不断探索下一个最有可能的节点,直到找到终点或无法找到径为止。 最后,在地图上运行A算法,并输出结果径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值