在 n×n 矩陣中 (n ≤ 8),將 1 到 n² 按**順時針螺旋** (右→下→左→上→右...) 填入,從右上角開始向左。輸出矩陣。
範例 n=4:
10 11 12 1 9 16 13 2 8 15 14 3 7 6 5 4
#include <stdio.h>
#include <string.h>
#define MAX_N 8
int main() {
int n;
if(scanf("%d", &n) != 1 || n < 1 || n > MAX_N) return 1;
int a[MAX_N][MAX_N];
memset(a, 0, sizeof(a));
// 方向向量: 下、左、上、右 (順時針)
int dr[4] = {1, 0, -1, 0};
int dc[4] = {0, -1, 0, 1};
int r = 0, c = n - 1; // 起始: 右上角
int dir = 0; // 初始方向: 下
for(int val = 1; val <= n * n; val++) {
a[r][c] = val;
// 計算下一位置
int nr = r + dr[dir];
int nc = c + dc[dir];
// 檢查是否需要轉向
if(nr < 0 || nr >= n || nc < 0 || nc >= n || a[nr][nc] != 0) {
dir = (dir + 1) % 4; // 切換方向
nr = r + dr[dir];
nc = c + dc[dir];
}
r = nr; c = nc;
}
// 輸出
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
printf("%4d", a[i][j]);
}
printf("\n");
}
return 0;
}
| 關鍵點 | 說明 |
|---|---|
| 起始位置 | (0, n-1) 右上角,題目要求 |
| 初始方向 | 向下 (dr=1, dc=0) |
| 方向順序 | 下→左→上→右 (順時針螺旋) |
| 轉向條件 | 越界 或 目標已非零 |
| 陣列初始化 | memset 歸零,0 表示未填 |
| 輸出格式 | %4d 對齊,適應 n=8 時最大 64 |
int top = 0, bottom = n-1, left = 0, right = n-1;
int val = 1;
while(val <= n*n) {
for(int c = right; c >= left; c--) a[top][c] = val++; // ←
if(++top > bottom) break;
for(int r = top; r <= bottom; r++) a[r][left] = val++; // ↓
if(++left > right) break;
for(int c = left; c <= right; c++) a[bottom][c] = val++; // →
if(--bottom < top) break;
for(int r = bottom; r >= top; r--) a[r][right] = val++; // ↑
if(--right < left) break;
}
此法通過四個邊界變數收縮,邏輯更直觀,但需仔細處理邊界更新順序。
n=3: 7 8 1 6 9 2 5 4 3 n=5: 21 22 23 24 1 20 37 38 25 2 19 36 41 26 3 18 35 40 27 4 17 16 15 14 5
蛇形/螺旋填數是「方向向量 + 狀態機」或「邊界收縮」兩大經典解法的完美練習題。關鍵在於:正確識別起始點、初始方向、轉向條件、邊界處理。方向向量法通用性強,易擴展至 3D 螺旋、任意路徑追蹤。