首页 > 代码库 > 蜂窝网格的坐标以及寻路

蜂窝网格的坐标以及寻路

蜂窝网格就是这样的六边形格子

技术分享
仔细观察的话,可以发现,蜂窝网格和四边形网格的区别就在于,蜂窝网格把偶数行的格子都错开了。
假设一个格子在四边形网格中的坐标是(x,y),那么它在蜂窝网格的坐标应该是:
(sqrt3 * (x + (y % 2) / 2) , y * 3 / 2)
这样就能把蜂窝网格用一个二维数组保存起来了。
接下去是一个寻路算法,我们需要找出以一个格子为起点,一定移动力下所有可以到达的格子,就像上面那张图里展示的那样:
public class hextile{
public static float sqrt3=1.7320508075689f;
public int x, y,m;//格子的坐标,以及移动到这个格子上的剩余行动力
public hextile pre;//表示是从哪个格子移动到这个格子上的,为Null的话表示没有
int max=20;//二维数组的上界,暂时定为了20*20的矩形蜂窝方阵
///构造函数
public hextile(int x,int y,hextile pre,int m){
this.x = x;
this.y = y;
this.pre = pre;
this.m = m;
}
//返回蜂窝一周的六个蜂窝,理论上要另写一个函数判断是否越界了的,这里直接在方法里判断了
public List around(int i){
List list = new List ();
if (this.x > 0)
list.Add (new hextile (this.x - 1, this.y, this,this.m-i));
if (this.x < max-1)
list.Add (new hextile (this.x + 1, this.y, this,this.m-i));
if ((this.y < max-1) && (this.x - 1 + this.y % 2 >= 0))
list.Add (new hextile (this.x - 1 + this.y % 2, this.y + 1, this,this.m-i));
if ((this.y < max-1) && (this.x + this.y % 2 < max))
list.Add (new hextile (this.x + this.y % 2, this.y + 1, this,this.m-i));
if ((this.y > 0) && (this.x - 1 + this.y % 2 >= 0))
list.Add (new hextile (this.x - 1 + this.y % 2, this.y - 1, this,this.m-i));
if ((this.y > 0) && (this.x + this.y % 2 < max))
list.Add (new hextile (this.x + this.y % 2, this.y - 1, this,this.m-i));
return(list);
}
//返回以此对象为起点,移动力为m的蜂窝,arr为移动力阻碍数组
public List findarea(int[,] arr){
List list = new List ();//输出用的链表
List a = new List ();//a记录每个需要寻路的节点
a.Add(this);
list.Add (this);
//枚举移动力,一定要倒过来枚举,因为涉及到了链表元素的删除
for (int i = this.m; i > 0; i--) 
{
//对移动力等于当前枚举数的格子进行操作
for (int j = a.Count - 1; j >= 0; j--)
//对应移动力才能进行操作
if (a[j].m==i)
//有多余移动力则获取该格子周围一圈的格子
if (a[j].m>=arr[a[j].x,a[j].y]){
//获取该格子周围一圈的格子
List l = a [j].around(arr[a[j].x,a[j].y]);
for (int u = 0; u < l.Count; u++) {
bool bo = true;
//判断该格子是否能加入输出list
for (int o = 0; o < list.Count; o++) {
if ((list[o].x==l[u].x)&&(list[o].y==l[u].y)){
bo = false;
//如果是更优路线
if (list [o].m < l [u].m) {
list.RemoveAt (o);
list.Add (l [u]);
a.Add (l [u]);
break;
}
}
}
if (bo) {
list.Add (l [u]);
a.Add (l[u]);
}
}
//操作完毕,将该格子从待操作列表中删除
a.RemoveAt (j);
}
}
return(list);
}
}

 

蜂窝网格的坐标以及寻路