본문 바로가기
알고리즘

AOJ - 93 달팽이 찍기 [java] - 시뮬레이션

by 발빠진 쥐 2026. 5. 25.

 

패턴 분석

N=5:

*****   행0: 전체 *
....*   행1: ..(N-2)개 + *
***.*   행2: ***  +  .*
*...*   행3: * + ... + *
*****   행4: 전체 *

N=7:

*******  행0
......*  행1
*****.*  행2
*...*.*  행3
*.***.*  행4
*.....*  행5
*******  행6

규칙: 오른쪽 위 모서리에서 시작해서 반시계 방향으로 안쪽으로 말려드는 달팽이.


알고리즘

시뮬레이션 - 달팽이가 실제로 기어가는 경로를 그대로 따라가면 됩니다.

방향 순서: 왼쪽 → 아래 → 오른쪽 → 위 를 반복하면서 *를 찍고, 벽이나 이미 찍은 곳에 닿으면 방향 전환.


import java.util.*;
import java.io.*;

public class Main {

    static int N;
    static char[][] grid;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        N = Integer.parseInt(br.readLine().trim());

        grid = new char[N][N];

        // 전체 '.'으로 초기화
        for (char[] row : grid) Arrays.fill(row, '.');

        // 달팽이 경로대로 * 찍기
        drawSnail();

        // 출력
        StringBuilder sb = new StringBuilder();
        for (char[] row : grid) {
            sb.append(new String(row)).append('\n');
        }
        System.out.print(sb);
    }

    static void drawSnail() {
        // 시작 위치: 오른쪽 위 모서리 (0행, N-1열)
        int row = 0;
        int col = N - 1;

        // 반시계 방향: 왼쪽, 아래, 오른쪽, 위 순서
        // {행 변화, 열 변화}
        int[][] dirs = {
            { 0, -1},  // 왼쪽
            { 1,  0},  // 아래
            { 0,  1},  // 오른쪽
            {-1,  0}   // 위
        };
        int dirIndex = 0; // 처음엔 왼쪽으로 출발

        // 전체 칸 수만큼 반복
        int total = N * N;
        for (int i = 0; i < total; i++) {
            grid[row][col] = '*';

            // 다음 위치 계산
            int nextRow = row + dirs[dirIndex][0];
            int nextCol = col + dirs[dirIndex][1];

            // 다음 위치가 벽이거나 이미 방문한 곳이면 방향 전환
            if (!canMove(nextRow, nextCol)) {
                dirIndex = (dirIndex + 1) % 4; // 다음 방향으로
                nextRow = row + dirs[dirIndex][0];
                nextCol = col + dirs[dirIndex][1];
            }

            row = nextRow;
            col = nextCol;
        }
    }

    // 이동 가능한지 확인
    static boolean canMove(int row, int col) {
        // 범위 밖이면 false
        if (row < 0 || row >= N || col < 0 || col >= N) return false;
        // 이미 * 찍힌 곳이면 false
        if (grid[row][col] == '*') return false;
        return true;
    }
}

흐름 요약

main()
 ├─ 입력
 ├─ grid 전체 '.' 초기화
 ├─ drawSnail() 호출
 │    ├─ 시작: (0, N-1) 오른쪽 위 모서리
 │    ├─ 방향: 왼→아래→오→위 반복
 │    └─ 매 칸마다 * 찍고, 막히면 방향 전환
 └─ 출력

핵심은 방향 전환 조건 하나 - 다음 칸이 범위 밖이거나 이미 *이면 방향을 바꾼다.