C로 5x5 스파이럴 배열을 채우는 문제를 여러 방식으로 구현해보면서, 각 방식의 원리와 장단점을 정리해본다. 첫 번째로 다룰 방식은 switch문으로 방향을 관리하는 방식이다.(처음 문제를 보고 내가 푼 방식이라 많이 와일드 하다. 나머지 3개는 교재참고, 다른 자료를 참고한 방식이다.)
문제 정의
5x5 정수 배열을 아래처럼 시계방향 나선형으로 1부터 25까지 채우는 게 목표다.
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
방식 설명
핵심 아이디어는 간단하다. 한 방향으로 갈 수 있는 데까지 가고, 막히면(이미 채워진 칸을 만나면) 다음 방향으로 90도 회전한다.
방향은 4가지뿐이므로 enu으로 정의하고, switch로 지금 어느 방향으로 가는 중인지를 분기한다.
각 방향은 for 문 하나로 표현되고, 방향이 바뀔때마다 changeFlag를 다음 방향으로 갱신한다.
이미 채워진 초깃값이 0이라는 점을 이용해 arr[y][x] == 0으로 값을 채울지, 아니면 루프를 종료하고 다음 분기로 넘어갈지 판단한다.
void fillSpiralBySwitch(int arr[SIZE][SIZE]) {
enum {
GORIGHT,
DOWN,
GOLEFT,
UP
};
int changeFlag = GORIGHT;
int value = 0;
int x = 0;
int y = 0;
while (value < SIZE * SIZE) {
switch (changeFlag) {
case GORIGHT: {
for (x; x < SIZE && y >= 0 && y < SIZE; x++) {
if (arr[y][x] == 0)
arr[y][x] = ++value;
else
break;
}
--x;
++y;
changeFlag = DOWN;
break;
}
case DOWN: {
for (y; x >= 0 && x < SIZE && y < SIZE; y++) {
if (arr[y][x] == 0)
arr[y][x] = ++value;
else
break;
}
--y;
--x;
changeFlag = GOLEFT;
break;
}
case GOLEFT: {
for (x; x >= 0 && y >= 0 && y < SIZE; x--) {
if (arr[y][x] == 0)
arr[y][x] = ++value;
else
break;
}
++x;
--y;
changeFlag = UP;
break;
}
case UP: {
for (y; y >= 0 && x >= 0 && x < SIZE; y--) {
if (arr[y][x] == 0)
arr[y][x] = ++value;
else
break;
}
++y;
++x;
changeFlag = GORIGHT;
break;
}
}
}
}
그림

과정
1단계 GORIGHT : (0,0) → (1,0) → (2,0) → (3,0) → (4,0) [1~5 채움]
for 종료 시 x=5, 보정 --x → x=4
++y → y=1
changeFlag = DOWN
2단계 DOWN : (4,1) → (4,2) → (4,3) → (4,4) [6~9 채움]
for 종료 시 y=5, 보정 --y → y=4
--x → x=3
changeFlag = GOLEFT
3단계 GOLEFT : (3,4) → (2,4) → (1,4) → (0,4) [10~13 채움]
for 종료 시 x=-1, 보정 ++x → x=0
--y → y=3
changeFlag = UP
4단계 UP : (0,3) → (0,2) → (0,1) [14~16 채움]
(0,0)은 이미 채워져 있어 break
for 종료 시 y=0, 보정 ++y → y=1
++x → x=1
changeFlag = GORIGHT
5단계 GORIGHT : (1,1) → (2,1) → (3,1) [17~19 채움]
(4,1)은 이미 채워져 있어 break
... (이하 반복, 안쪽으로 계속 좁혀짐)
특징
장점
- 가독성이 나쁘지 않다 : 어느 방향으로 가는지 코드 구조에 드러난다. case만 따라가다 보면 로직 전체를 이해할 수 있다.
- 디버깅 용이 : 방향별로 로직이 분리되어 있어, 특정 방향에서 생기는 문제가 생기면 그 case만 보면 된다.
- 홀수/짝수 크기 지원 : 이미 채워진 칸인지를 값으로 직접 판단하기 때문에, 배열 크기의 홀짝 여부에 로직이 의존하지 않는다.
- 직사각형 확장이 비교적 쉽다 : x, y의 이동 범위가 이미 분리되어 있어서 가로세로 크기를 다르게 둬도 구조 자체는 크게 바뀌지 않는다.
단점
- 코드가 길다 : 방향이 4개면 case도 4개, 로직도 4개가 필요하다.
- for문에 인덱스 보정이 필요하다 : 각 방향의 for문이 조건을 만족하지 못하는 시점(예: x == SIZE)에 끝나기 때문에, case 끝마다 x,y값을 보정하는 보정 코드가 따라붙는다.
- 배열 값에 의존한다 : "0이면 채워지지 않은 칸"이라는 전제로 동작하기 때문에, 채우는 값 자체가 0이거나, 이미 채워진 값을 다시 채우는 경우 동작하지 않는다.
'공부' 카테고리의 다른 글
| 스파이럴(달팽이) 배열 구현하기 - 경계값(Boundary) 방식 (0) | 2026.07.08 |
|---|---|
| 스파이럴(달팽이) 배열 구현하기 - 대칭 축소(nLength) 방식 (0) | 2026.07.08 |
| 선택정렬 (0) | 2026.07.07 |
| 우리는 왜 UTF-8을 써야 하는가 (0) | 2026.07.07 |
| 버블정렬 (0) | 2026.07.06 |