在锯齿状的2D网格上向外螺旋

时间:2016-08-10 19:49:06

标签: arrays algorithm matrix multidimensional-array grid

我的问题与其他问题非常相似:

Looping in a spiral

On a two dimensional grid is there a formula I can use to spiral coordinates in an outward pattern?

但是,如果您的网格/矩阵不规则,您会怎么做?

我正在制作一款游戏,其中有一些“座位”,由2D网格代表。在每一个奇数行上,座位/单元格少一个。渲染时,这些行偏移½座位。我需要一个算法,输出最近的座位,相对于我输入的任何座位坐标,按降序排列,如下所示(蓝色单元格是起始坐标,半透明单元格位于网格外):

Visual representation

座位网格存储为锯齿状的多维数组,因此之前的可视化有点误导。从“算法”的角度来看,它实际上看起来更像是这样(同样,蓝色单元格是起始坐标,半透明单元格位于数组边界之外):

Real representation

输出类似于

[0,0][1,0][0,1][-1,1][-1,0][-1,-1][0,-1][1,-1][2,0][1,1]...

1 个答案:

答案 0 :(得分:2)

这是一种迭代方法,将螺旋分解为螺旋的每个循环7个子级别,一个子级别从前一个螺旋级别移出,6个子级别跟踪前一个边界的六边形路径电平:

static void spiralLoop(int startx, int starty, int levels)
{
    int level = 1, sublevel = 0, sublevelstep = 0;
    int x = startx, y = starty;
    while(level <= levels)
    {
        System.out.println("["+x+","+y+"]");

        switch(sublevel)
        {
            case 0:
                x++; // stepping up from previous (next innermost) loop
                break;
            case 1:
                x+=(y&1);y++; // up and right
                break;
            case 2:
                x-=(~y&1);y++; // up and left
                break;
            case 3:
                x--; // left
                break;
            case 4:
                x-=(~y&1);y--; // down and left
                break;
            case 5:
                x+=(y&1);y--; // down and right
                break;
            case 6:
                x++; // right
                break;
            default:
                break;
        }

        if(sublevel == 0) // (3)
            sublevel = 1;
        if(++sublevelstep >= level) // (1)
        {
            sublevelstep = 0;
            if(++sublevel > 6) // (2)
            {
                level++;
                sublevel = 0;
            }
        }
    }
}

(1)每个六边形边的长度(子级台阶的数量)等于水平(从一个开始)。每次迭代后,步数增加,如果已达到子级的末尾,则子级递增,步骤重置为0.

(2)如果等级已经完成(子等级> 6),则等级递增,子等级重置为0.

(3)每个级别的第一个子级别(从上一级别向上移动)仅持续一次迭代。

它不会检查当前位置是否在网格之外,但是添加起来很简单。

传入起始x,y位置,并用于初始化x和y。这些值用于确定当前行是奇数还是偶数,这会影响位置的更新方式。

要向左对角移动,仅在y为偶数时递减x。要沿对角线方向移动,仅当y为奇数时才增加x。见下文:

row 0:    0 1 2 3 4 5 6 7 8 9
row 1:     0 1 2 3 4 5 6 7 8
row 2:    0 1 2 3 4 5 6 7 8 9
row 3:     0 1 2 3 4 5 6 7 8
row 4:    0 1 2 3 4 5 6 7 8 9
row 5:     0 1 2 3 4 5 6 7 8