14499 주사위 굴리기 - (https://www.acmicpc.net/problem/14499)
문제 설명부터 이해하는 데 힘들었다.
지도가 있는데 지도 위에 주사위가 굴러간다.
육면체 주사위가 명령대로 이동하면서 지도 칸에 숫자의 유무에 따라 주사위 면의 숫자가 바뀌거나 지도 칸의 숫자가 바뀐다.
명령은 1~4까지 동서북남 순으로 명령에 맞게 주사위 방향을 굴릴 수 있다.
명령을 실행할 때마다 주사위가 천장을 바라보는 면의 숫자를 출력한다.(지도 밖으로 나갈 경우 명령 무시)
육면체 주사위를 동서남북 방향으로 각각 굴릴 때 6개의 면이 어떻게 이동하는지에 대해서 확인을 해봐야하는 빡구현 문제다.
이렇게 주사위 전개도를 생각해보자.(문제에서 이렇게 예시를 주어 접근하기 편했다.)
동쪽으로 구르게 되면 윗면이 동쪽면으로, 동쪽면이 밑면으로 가고, 밑면이 서쪽면으로, 서쪽면이 윗면으로 가는 구조가 된다.
서쪽으로 구르게 되면 동쪽과 반대방향이 된다. 윗면이 서쪽으로, 밑면이 동쪽으로 ...
주사위 전개도에서 밑면 위치를 종방향으로 뒀으므로 북쪽 남쪽은 직관적이다.
윗면은 북쪽으로, 북쪽은 밑면으로, 밑면은 남쪽으로, 남쪽은 윗면으로 한 칸씩 이동하며 된다.
남쪽방향은 북쪽방향의 반대로 하면 된다. 아래 방향으로 이동하게끔.
그럼 어떻게 이 4방향을 구현해야할까? 위에 사진에서 주사위 각 면을 0번부터 5번까지 기입한 이유가 바로 구현의 힌트다. int[] dice = new int[6]
으로 두어 각 인덱스를 주사위 면으로 생각하면 우리가 만들어놓은 방향별 이동 순서를 인덱스 조작으로 쉽게 구현할 수 있게 된다! (물론 빡구현은 불가피했다.)
package samsungSW.baekjoon;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
//230725 22:21 ~ 23:16
public class BOJ14499 {
static int N, M, x, y, K;
static int[][] board;
static int[] dice = new int[6];
static int[] dx = {-1, 0, 1, 0};
static int[] dy = {0, 1, 0, -1};
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] s = br.readLine().split(" ");
N = Integer.parseInt(s[0]);
M = Integer.parseInt(s[1]);
x = Integer.parseInt(s[2]);
y = Integer.parseInt(s[3]);
K = Integer.parseInt(s[4]);
board = new int[N][M];
int row = 0;
for (int t = 0; t < N; t++) {
String[] ss = br.readLine().split(" ");
for (int j = 0; j < M; j++) {
board[row][j] = Integer.parseInt(ss[j]);
}
row++;
}
// for(int i = 0; i < board.length; i++) {
// System.out.println(Arrays.toString(board[i]));
// }
String [] _s = br.readLine().split(" ");
for (int i = 0; i < _s.length; i++) {
int cmd = Integer.parseInt(_s[i]);
if (cmd == 1) {
// 위치 이동
int nx = dx[1] + x;
int ny = dy[1] + y;
if(0 <= nx && nx < N && 0 <= ny && ny < M) {
x = nx;
y = ny;
// 동
int tmp = dice[1];
dice[1] = dice[3];
dice[3] = dice[0];
dice[0] = dice[5];
dice[5] = tmp;
// 지도가 0이 아님
if(board[x][y] != 0) {
dice[5] = board[x][y];
board[x][y] = 0;
}
// 지도가 0임
else {
board[x][y] = dice[5];
}
System.out.println(dice[3]);
}
} else if (cmd == 2) {
// 위치 이동
int nx = dx[3] + x;
int ny = dy[3] + y;
if(0 <= nx && nx < N && 0 <= ny && ny < M) {
x = nx;
y = ny;
// 서
int tmp = dice[0];
dice[0] = dice[3];
dice[3] = dice[1];
dice[1] = dice[5];
dice[5] = tmp;
// 지도가 0이 아님
if(board[x][y] != 0) {
dice[5] = board[x][y];
board[x][y] = 0;
}
// 지도가 0임
else {
board[x][y] = dice[5];
}
System.out.println(dice[3]);
}
} else if (cmd == 3) {
// 위치 이동
int nx = dx[0] + x;
int ny = dy[0] + y;
if(0 <= nx && nx < N && 0 <= ny && ny < M) {
x = nx;
y = ny;
// 북
int tmp = dice[2];
dice[2] = dice[3];
dice[3] = dice[4];
dice[4] = dice[5];
dice[5] = tmp;
// 지도가 0이 아님
if(board[x][y] != 0) {
dice[5] = board[x][y];
board[x][y] = 0;
}
// 지도가 0임
else {
board[x][y] = dice[5];
}
System.out.println(dice[3]);
}
} else if (cmd == 4) {
// 위치 이동
int nx = dx[2] + x;
int ny = dy[2] + y;
if(0 <= nx && nx < N && 0 <= ny && ny < M) {
x = nx;
y = ny;
// 남
int tmp = dice[5];
dice[5] = dice[4];
dice[4] = dice[3];
dice[3] = dice[2];
dice[2] = tmp;
// 지도가 0이 아님
if(board[x][y] != 0) {
dice[5] = board[x][y];
board[x][y] = 0;
}
// 지도가 0임
else {
board[x][y] = dice[5];
}
System.out.println(dice[3]);
}
}
// System.out.println("cmd: " + cmd);
// System.out.println("dice" + Arrays.toString(dice));
}
}
}
각 명령에 맞게 위에서 생각한 이동순서를 그대로 코드로 나타냈다. int[] dx, int[] dy
를 활용하여 동서남북 네 방향의 x, y 이동 좌표를 설정했다. 지금 보니 중복되는 코드는 따로 함수로 빼내어 구현을 하면 더 깔끔한 코드가 될 것 같다.
구현 문제는 종이에다가 설계를 해보면서 끄적이는 습관을 길들이는게 중요한 것 같다. 키보드에 먼저 손이 올라가면 중간에 로직이 꼬일 경우 정답을 향한 이정표를 못 찾게 될 수 있기 때문이다.
좋은 정보 감사합니다