사용자 입력에 따라 N x N 크기의 2차원 배열을 생성하고, 이를 달팽이 모양으로 숫자로 채우는 C++ 프로그램 구현
이 문제를 제대로 구현하기 위해 반드시 익혀야 하는 개념들을 정리하면 다음과 같습니다:
2차원 배열
배열[y][x] 형식으로 좌표를 행(y)과 열(x) 기준으로 탐색.좌표 이동 제어
시계방향 방향 제어
배열 범위와 중복 체크
출력 정렬(iomanip)
setw, setfill 사용.| 용어 | 설명 |
|---|---|
| 2차원 배열 | 행과 열로 구성된 배열로, arr[y][x] 형태로 접근 |
| 열거형(enum) | 방향을 이름으로 명확히 정의하여 가독성과 유지보수성을 향상시키는 사용자 정의 자료형 |
| 시계방향 | RIGHT → DOWN → LEFT → UP 순서로 반복되는 방향 흐름 |
| 유효성 검사 | 현재 좌표가 배열 범위 내에 있고 아직 방문하지 않았는지 확인하는 과정 |
| iomanip | C++에서 출력 포맷을 정렬하는 기능을 제공하는 헤더 (setw, setfill 등 포함) |
const int MAX = 100;
int board[MAX][MAX];
int N;
MAX: 배열의 최대 크기. 미리 넉넉하게 할당해 두어 동적 할당을 피함.board: 숫자가 채워질 실제 2차원 배열.N: 배열의 실제 크기, 사용자로부터 입력 받음.enum DIR {
RIGHT = 0,
DOWN = 1,
LEFT = 2,
UP = 3
};
RIGHT → DOWN → LEFT → UP 순환을 가능하게 하며, 정수로 처리 가능.bool CanGo(int y, int x) {
if (y < 0 || y >= N) return false; // 배열 위 또는 아래 경계 초과
if (x < 0 || x >= N) return false; // 배열 좌 또는 우 경계 초과
if (board[y][x] != 0) return false; // 이미 숫자가 채워진 칸
return true;
}
void PrintBoard() {
for (int y = 0; y < N; y++) {
for (int x = 0; x < N; x++) {
std::cout << std::setfill('0') << std::setw(2) << board[y][x] << " ";
}
std::cout << std::endl;
}
}
setw(2): 숫자 너비를 2칸으로 고정setfill('0'): 빈칸을 0으로 채워 가독성 향상 (3 → 03)01 02 03
08 09 04
07 06 05
void SetBoard() {
int dir = RIGHT;
int num = 1;
int y = 0, x = 0;
while (true) {
board[y][x] = num;
if (num == N * N) break;
int nextX = x, nextY = y;
switch (dir) {
case RIGHT: nextX = x + 1; break;
case DOWN: nextY = y + 1; break;
case LEFT: nextX = x - 1; break;
case UP: nextY = y - 1; break;
}
if (CanGo(nextY, nextX)) {
x = nextX;
y = nextY;
num++;
} else {
switch (dir) {
case RIGHT: dir = DOWN; break;
case DOWN: dir = LEFT; break;
case LEFT: dir = UP; break;
case UP: dir = RIGHT; break;
}
}
}
}
dx, dy 배열 사용void SetBoard() {
int dir = RIGHT;
int num = 1;
int y = 0, x = 0;
int dx[] = { 1, 0, -1, 0 }; // RIGHT, DOWN, LEFT, UP
int dy[] = { 0, 1, 0, -1 };
while (true) {
board[y][x] = num;
if (num == N * N) break;
int nextY = y + dy[dir];
int nextX = x + dx[dir];
if (CanGo(nextY, nextX)) {
y = nextY;
x = nextX;
num++;
} else {
dir = (dir + 1) % 4; // 방향 순환
}
}
}
dx, dy 배열을 통해 좌표 연산을 수식으로 표현함으로써, switch문 제거.(dir + 1) % 4로 수학적으로 처리해 코드 최적화.int main() {
std::cin >> N;
SetBoard();
PrintBoard();
return 0;
}
N을 입력받아, 그 크기에 맞는 달팽이 배열을 구성하고 출력합니다.아래는 최적화된 코드로 구성된 달팽이 배열 생성 프로그램의 전체 소스 코드입니다.
#include <iostream>
#include <iomanip>
using namespace std;
const int MAX = 100;
int board[MAX][MAX]; // 달팽이 배열 저장
int N; // 배열 크기
// 유효한 이동인지 검사
bool CanGo(int y, int x) {
if (y < 0 || y >= N) return false;
if (x < 0 || x >= N) return false;
if (board[y][x] != 0) return false;
return true;
}
// 달팽이 배열 채우기
void SetBoard() {
int dir = 0; // 0: RIGHT, 1: DOWN, 2: LEFT, 3: UP
int num = 1; // 시작 숫자
int y = 0, x = 0; // 시작 위치
int dx[] = { 1, 0, -1, 0 }; // x축 이동량
int dy[] = { 0, 1, 0, -1 }; // y축 이동량
while (true) {
board[y][x] = num;
if (num == N * N) break;
int nextY = y + dy[dir];
int nextX = x + dx[dir];
if (CanGo(nextY, nextX)) {
y = nextY;
x = nextX;
num++;
} else {
dir = (dir + 1) % 4; // 방향 회전
}
}
}
// 결과 출력
void PrintBoard() {
for (int y = 0; y < N; y++) {
for (int x = 0; x < N; x++) {
cout << setfill('0') << setw(2) << board[y][x] << " ";
}
cout << endl;
}
}
int main() {
cin >> N; // 사용자로부터 크기 입력
SetBoard(); // 배열 채우기
PrintBoard(); // 결과 출력
return 0;
}
1. 사용자로부터 배열 크기 N을 입력받음
2. board[N][N] 배열 생성 (초기값 0)
3. SetBoard() 함수 실행:
- 시작 위치 (0,0)에 1을 채움
- 현재 방향으로 다음 좌표 탐색
- 갈 수 있으면 이동 및 숫자 증가
- 못 가면 방향을 오른쪽으로 회전
- N*N개의 숫자 모두 채워질 때까지 반복
4. PrintBoard() 함수 실행:
- 이중 반복문으로 2차원 배열 출력
- 숫자는 자릿수 맞춰 정렬해서 출력
| 방향 | dx | dy | 설명 |
|---|---|---|---|
| RIGHT(0) | +1 | 0 | 오른쪽 이동 |
| DOWN(1) | 0 | +1 | 아래로 이동 |
| LEFT(2) | -1 | 0 | 왼쪽 이동 |
| UP(3) | 0 | -1 | 위로 이동 |
시작 위치: (0,0)
01 → 02 → 03 → 04
↓
12 ← 13 ← 14 05
↑ ↓
11 16 ← 15 06
↑ ↑ ↑ ↓
10 ← 09 ← 08 ← 07
board[y][x] != 0)4
01 02 03 04
12 13 14 05
11 16 15 06
10 09 08 07
setw(2), setfill('0')을 이용해 두 자리로 정렬endl)은 각 행(row)마다 수행board[y][x] 순으로 접근하나요?행(y), 열(x) 순서로 선언되므로, board[y][x]가 올바른 접근 방식입니다.dir = (dir + 1) % 4를 사용하나요?CanGo() 함수는 꼭 필요할까요?| 항목 | 요점 |
|---|---|
| 2차원 배열 순회 | board[y][x] 형태로 접근, 이중 반복문 사용 |
| 방향 제어 | dx[], dy[]를 통해 이동 방향 수식화 |
| 방향 전환 | (dir + 1) % 4로 간결하게 처리 |
| 유효성 검사 | CanGo() 함수로 경계와 중복 체크를 통합 |
| 출력 정렬 | setw, setfill을 사용해 가독성 향상 |
✅ 이 문제는 단순한 배열 채우기 이상의 시뮬레이션 알고리즘 설계 연습입니다. 이 구조를 잘 익혀두면, 로봇 시뮬레이션, 미로 탐색, 퍼즐 게임 등의 고급 문제에서도 같은 패턴을 재사용할 수 있습니다.