スクエアスパイラル
これは、最適に実行される単一の関数のコンパクトなソリューションです(配列内の各場所に1回だけアクセスします)。
static int anMoveXDir[] = { 1, 0, -1, 0 };
static int anMoveYDir[] = { 0, 1, 0, -1 };
static void DoSpiral(int *panGrid, int nWidth, int nHeight)
{
int nSideSel, nSideIdx, nMoveDir, nXPosn, nYPosn, nCounter;
int anSideLen[2];
anSideLen[0] = nWidth;
anSideLen[1] = nHeight - 1;
nMoveDir = 0; /* start off at (0, 0) in array, */
nXPosn = 0; /* facing east, and count from 1 */
nYPosn = 0;
nCounter = 1;
for (nSideSel = 0; anSideLen[nSideSel & 1]; anSideLen[nSideSel++ & 1]--)
for (nSideIdx = anSideLen[nSideSel & 1]; nSideIdx; nSideIdx--)
{
panGrid[(nYPosn * nWidth) + nXPosn] = nCounter++;
if (nSideIdx == 1)
nMoveDir = (nMoveDir + 1) & 3;
nXPosn += anMoveXDir[nMoveDir];
nYPosn += anMoveYDir[nMoveDir];
}
}
x
このアルゴリズムは、幅と高さの長方形または正方形の配列を指定した単純なルールで機能しますy
。次に、配列をウォークして正方形のスパイラルを作成するには、次の手順を使用します。
x + (y - 1) + (x - 1) + (y - 2) + (x - 2) + (y - 3) + (x - 3) + ... + 0
上記の関数は、単に上記のシーケンスに従います。アレイの左上を東に向けて開始し、ステップを歩き、右に90度回転し、ステップx
を歩き、右に90度曲がり、ステップ(y - 1)
を歩き(x - 1)
ます。x
y
以下のテストプログラムに挿入することで、上記の関数をテストできます。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define GRID_WIDTH 7
#define GRID_HEIGHT 11
void main()
{
int nXPosn, nYPosn;
int anGrid[GRID_WIDTH * GRID_HEIGHT];
int *pnValue;
DoSpiral(anGrid, GRID_WIDTH, GRID_HEIGHT);
for (pnValue = anGrid, nYPosn = 0; nYPosn < GRID_HEIGHT; nYPosn++, printf("\n"))
for (nXPosn = 0; nXPosn < GRID_WIDTH; printf("%4i", *pnValue++), nXPosn++);
}
出力は次のようになります(上記のプログラムに示されている7x11グリッドの場合)。
1 2 3 4 5 6 7
32 33 34 35 36 37 8
31 56 57 58 59 38 9
30 55 72 73 60 39 10
29 54 71 74 61 40 11
28 53 70 75 62 41 12
27 52 69 76 63 42 13
26 51 68 77 64 43 14
25 50 67 66 65 44 15
24 49 48 47 46 45 16
23 22 21 20 19 18 17