팽이는 1부터 N*N까지의 숫자가 시계방향으로 이루어져 있다.
다음과 같이 정수 N을 입력 받아 N크기의 달팽이를 출력하시오.
[예제]
N이 3일 경우,
N이 4일 경우,
[제약사항]
달팽이의 크기 N은 1 이상 10 이하의 정수이다. (1 ≤ N ≤ 10)
가장 첫 줄에는 테스트 케이스의 개수 T가 주어지고, 그 아래로 각 테스트 케이스가 주어진다.
각 테스트 케이스에는 N이 주어진다.
각 줄은 '#t'로 시작하고, 다음 줄부터 빈칸을 사이에 두고 달팽이 숫자를 출력한다.
(t는 테스트 케이스의 번호를 의미하며 1부터 시작한다.)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.sql.SQLOutput;
import java.util.StringTokenizer;
public class Main {
static StringTokenizer st;
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static int n,T;
static int[][] g;
static boolean[][] visited;
static int[] dx = {0,1,0,-1};
static int[] dy = {1,0,-1,0};
static StringBuilder sb = new StringBuilder();
// 방향벡터 순서 중요
public static void main(String[] args) throws Exception {
T = Integer.parseInt(br.readLine());
for (int t = 1; t <= T; t++) {
n = Integer.parseInt(br.readLine());
g = new int[n][n];
visited = new boolean[n][n];
sb = new StringBuilder();
DFS(0, 0, 1, 0);
sb.append("#").append(t).append("\n");
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
sb.append(g[i][j]).append(" ");
}
sb.append("\n");
}
System.out.println(sb);
}
}
public static void DFS(int x, int y, int num, int dir) { // 현재 위치, 현재 위치에 넣을 수, 방향. 방향은 4가지 방향 존재
// 처음부터 방문 및 해야할 행위 처리 후 넘어감
visited[x][y] = true;
g[x][y] = num;
int nx = x + dx[dir];
int ny = y + dy[dir]; // 다음 번 방향
int nextDir = (dir + 1) % 4;
if(num == n*n)
return; // 종착점 끝.
if (!isInner(nx, ny) || visited[nx][ny]) { // 방향을 바꿔야 하는 경우.
// 1. 좌표 벗어남 2. 현재 좌표 이미 방문함 -> 방향 틀어야해.
nx = x + dx[nextDir];
ny = y + dy[nextDir];
// 다음 좌표는 방향을 바꾼 좌표여야 해.
DFS(nx, ny, num + 1, nextDir);
} else {
DFS(nx, ny, num + 1, dir);
}
}
public static boolean isInner(int x, int y) {
if (x < 0 || x > n - 1 || y < 0 || y > n - 1) {
return false;
}
return true;
}
}
해당 문제는 나는 반복문 4개를 도입해서 풀었다. 하지만 규칙성이 있기에 DFS로 풀 수 있었음.
대신 방향에는 순서가 존재. 동(0) -> 남(1) -> 서(2) -> 북(3) 순으로 순회했어야함.
여기서 mod 연산을 사용하여 자동 방향 전화을 하는 코드 기억. (dir + 1)%4
또한 본인 차례에서 해야하는 행위를 먼저 진행. 그리고 조건 처리.