前言:这是很久之前写游戏的时候想到的实现方法,现在重新放上来。寻路算法写得好挫啊,现在写的话肯定好看很多,但我懒得改了……
This is a Simple weighted Hexagon (Cellular topology) Data structure base on double dimensional array. 这是一个非常简单的带权六边形数据结构 基于二维数组实现
每个六边形地图都由许多六边形格子组成,格子拥有的属性详见HexagonGrid的注释
如图这是一个5*4的地图,以中间那个格子为例,有六个方向。
如果用二维数组表示,各个格子的坐标如图,通过分析可知,只需判断列的奇偶,就可以确定六个方向的坐标。
详细函数见HexagonMap.h的注释
通过各个格子的权重,计算从某个格子到某个格子的最短路径。 算法需要一个队列作为辅助,详细如下:
首先给定一个格子,该格子入队。 当队列不为空 { 第一个格子出队,将该格子标记。 按顺时针,计算从该格子到该格子的六个方向所需的最短路程(weight),记录在该格子的TotalWeight中。 按顺时针,该格子的六个方向入队。 新建一个辅助队列,将原队列里有效的格子复制到新队列。(超出边界或已标记的为无效格子)。 }
然后将上述算法以逆时针进行一遍。函数返回一个HexagonMap的指针,该地图的格子的TotalWeight即最短路程。
例: 假设所有格子权重均为1,以(4,2)为起点,则:
因为算法原因所以从(4,2)到(4,2)的路程为2。
以上所有图片都是用QML画的。
附上github地址:一个基于二维数组的六边形(蜂窝拓扑)数据结构。(欢迎点赞^_^)
附上核心代码:
HexagonGrid.h
#ifndef HEXAGONGRID_H
#define HEXAGONGRID_H
template
class HexagonGrid{
public:
T Data;//存储数据
int Weight;//权重
int X;//坐标
int Y;
int TotalWeight;//到这里路程
public:
HexagonGrid(){
Weight=1;
X=0;
Y=0;
TotalWeight=0;
}
};
#endif // HEXAGONGRID_H
#ifndef HEXAGONMAP_H
#define HEXAGONMAP_H
#include "HexagonGrid.h"
#include
/*简单封装了STL的queue*/
template
class Queue{
private:
std::vector __List;
public:
Queue(){}
~Queue(){__List.clear();}
void EnQueue( T x);
T DeQueue();
bool IsEmpty();
int GetSize()const;
T& operator[](int i);
};
template
void Queue::EnQueue( T x){
__List.push_back(x);
}
template
T Queue::DeQueue(){
T temp;
temp=__List.at(0);
__List.erase(__List.begin());
return temp;
}
template
bool Queue::IsEmpty(){
return __List.empty();
}
template
int Queue::GetSize() const{
return __List.size();
}
template
T &Queue::operator[](int i){
return __List.at(i);
}
/***************************/
template
class HexagonMap{
public:
//格子二维数组(Queue应该为Vector)篇章有限,直接用Queue
//因为封装的queue重载了[]运算符,这直接用类似二维数组的方法访问元素
Queue > >map;
int Width;//地图大小
int Height;
public:
HexagonMap(int x,int y){//新建一个地图
Width=x-1;
Height=y-1;
for(int i=0;i > abc;
map.EnQueue(abc);
for(int j=0;j temp;
map[i].EnQueue(temp);
map[i][j].X=i;
map[i][j].Y=j;
}
}
}
HexagonMap(const HexagonMap& tempmap){//复制
Width=tempmap.Width;
Height=tempmap.Height;
map=tempmap.map;
}
HexagonGrid getGrid(int x,int y){//获取格子
return map[x][y];
}
HexagonGrid getu(int x,int y){//获取给定格子的上方格子
HexagonGrid temp;
if(y==0)return temp;//如果到了边界,则返回一个空格子
return map[x][y-1];
}
HexagonGrid getd(int x,int y){//获取给定格子的下方格子
HexagonGrid temp;
if(y==Height)return temp;//如果到了边界,则返回一个空格子
return map[x][y+1];
}
HexagonGrid getlu(int x,int y){//获取给定格子的左上方格子
HexagonGrid temp;
if(x==0||(y==0&&x%2==0))return temp;//如果到了边界,则返回一个空格子
if(x%2==1)
return map[x-1][y];
else
return map[x-1][y-1];
}
HexagonGrid getru(int x,int y){//获取给定格子的右上方格子
HexagonGrid temp;
if(x==Width||(y==0&&x%2==0))return temp;//如果到了边界,则返回一个空格子
if(x%2==1)
return map[x+1][y];
else
return map[x+1][y-1];
}
HexagonGrid getld(int x,int y){//获取给定格子的左下方格子
HexagonGrid temp;
if(x==0||(y==Height&&x%2==1))return temp;//如果到了边界,则返回一个空格子
if(x%2==1)
return map[x-1][y+1];
else
return map[x-1][y];
}
HexagonGrid getrd(int x,int y){//获取给定格子的右下方格子
HexagonGrid temp;
if(x==Width||(y==Height&&x%2==1))return temp;//如果到了边界,则返回一个空格子
if(x%2==1)
return map[x+1][y+1];
else
return map[x+1][y];
}
void marku(int x,int y){//计算去到上方的路程
if(y==0)return;
if(map[x][y-1].TotalWeight==0)//如果上方还没有标记过
map[x][y-1].TotalWeight=map[x][y].TotalWeight+map[x][y-1].Weight;
else{
int temp=map[x][y].TotalWeight+map[x][y-1].Weight;
if(temp
#include
#include"HexagonMap.h"
using namespace std;
int main(){
/*测试用*/
HexagonMap* map;
map=new HexagonMap(3,4);
map=map->findWay(2,3);
cout<map[0][0].TotalWeight<