基于二维数组的六边形地图数据结构的实现(蜂窝拓补)

前言:这是很久之前写游戏的时候想到的实现方法,现在重新放上来。寻路算法写得好挫啊,现在写的话肯定好看很多,但我懒得改了……



Hexagon-Data-structure

This is a Simple weighted Hexagon (Cellular topology) Data structure base on double dimensional array. 这是一个非常简单的带权六边形数据结构 基于二维数组实现

About HexagonGrid

每个六边形地图都由许多六边形格子组成,格子拥有的属性详见HexagonGrid的注释

About HexagonMap

如图这是一个5*4的地图,以中间那个格子为例,有六个方向。

如果用二维数组表示,各个格子的坐标如图,通过分析可知,只需判断列的奇偶,就可以确定六个方向的坐标。 

详细函数见HexagonMap.h的注释

About FindWay 寻路

通过各个格子的权重,计算从某个格子到某个格子的最短路径。 算法需要一个队列作为辅助,详细如下:

首先给定一个格子,该格子入队。 当队列不为空 { 第一个格子出队,将该格子标记。 按顺时针,计算从该格子到该格子的六个方向所需的最短路程(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

HexagonMap.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* findWay(int x,int y){

        HexagonMap* map=new HexagonMap(*this);
        HexagonMap* mapmark=new HexagonMap(*this);

        Queue > a;
        HexagonGrid abc=map->getGrid(x,y);
        a.EnQueue(abc);

        while(a.IsEmpty()!=true){
            HexagonGrid temp=a.DeQueue();

            mapmark->map[temp.X][temp.Y].TotalWeight=-1;

            map->marku(temp.X,temp.Y);
            map->markru(temp.X,temp.Y);
            map->markrd(temp.X,temp.Y);
            map->markd(temp.X,temp.Y);
            map->markld(temp.X,temp.Y);
            map->marklu(temp.X,temp.Y);

            a.EnQueue(map->getu(temp.X,temp.Y));
            a.EnQueue(map->getru(temp.X,temp.Y));
            a.EnQueue(map->getrd(temp.X,temp.Y));
            a.EnQueue(map->getd(temp.X,temp.Y));
            a.EnQueue(map->getld(temp.X,temp.Y));
            a.EnQueue(map->getlu(temp.X,temp.Y));

            int size=a.GetSize();
            Queue > b;
            for(int i=0;i temp1=a.DeQueue();
                if((temp1.X!=0||temp1.Y!=0)&&mapmark->map[temp1.X][temp1.Y].TotalWeight==0)
                    b.EnQueue(temp1);
            }
            a=b;
        }


        mapmark=new HexagonMap(*this);

        Queue > a1;
        HexagonGrid abc1=map->getGrid(x,y);
        a1.EnQueue(abc1);
        while(a1.IsEmpty()!=true){
            HexagonGrid temp=a1.DeQueue();

            mapmark->map[temp.X][temp.Y].TotalWeight=-1;


            map->marklu(temp.X,temp.Y);
            map->markld(temp.X,temp.Y);
            map->markd(temp.X,temp.Y);
            map->markrd(temp.X,temp.Y);
            map->markru(temp.X,temp.Y);
            map->marku(temp.X,temp.Y);

            a1.EnQueue(map->getlu(temp.X,temp.Y));
            a1.EnQueue(map->getld(temp.X,temp.Y));
            a1.EnQueue(map->getd(temp.X,temp.Y));
            a1.EnQueue(map->getrd(temp.X,temp.Y));
            a1.EnQueue(map->getru(temp.X,temp.Y));
            a1.EnQueue(map->getu(temp.X,temp.Y));

            int size=a1.GetSize();
            Queue > b1;
            for(int i=0;i temp1=a1.DeQueue();
                if((temp1.X!=0||temp1.Y!=0)&&mapmark->map[temp1.X][temp1.Y].TotalWeight==0)
                    b1.EnQueue(temp1);
            }
            a1=b1;

        }
        return map;
    }
    /******详见ReadMe!!!!!******/

};


#endif // HexagonMap_H




main.cpp

#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<


你可能感兴趣的:(【——其他内容——】)