백준 14499번 구현 문제를 Java로 풀어보았다. 초반에 주사위의 6개 면을 어떻게 표현해야할지, 주사위가 구를 때 각 면의 위치가 바뀌는 것을 어떻게 표현해야할지 고민을 하느라 시간을 좀 날렸다.
주사위 객체를 주어진 특성에 맞게 선언해주면 쉽게 해결이 가능하다.
문제가 역시 길기에 링크만 첨부한다.
https://www.acmicpc.net/problem/14499
주사위의 6개 면을 서로 다른 이름을 주어 네이밍을 하고 주사위가 구르는 행위를 하나의 메소드로서 선언해줬다.
윗면을 top
, 바닥면을 bottom
, 왼쪽을 left
, 오른쪽을 right
, 뒷쪽면을 rear
, 정면을 front
라 이름 지었다.
static class Dice {
int top, bottom, rear, front, left, right;
Dice(){ // 주사위 초기 상태
top = 0; bottom = 0; rear = 0; front = 0; left = 0; right = 0;
}
void move1(){ // 1번 굴리기, rear&front 은 그대로
int beforeTop = top; int beforeBottom = bottom; int beforeLeft = left; int beforeRight = right;
top = beforeLeft; left = beforeBottom; bottom = beforeRight; right = beforeTop;
}
void move2(){ // 2번 굴리기, rear&front 은 그대로
int beforeTop = top; int beforeBottom = bottom; int beforeLeft = left; int beforeRight = right;
top = beforeRight; right = beforeBottom; bottom = beforeLeft; left = beforeTop;
}
void move3(){ // 3번 굴리기, left&right 는 그대로
int beforeTop = top; int beforeBottom = bottom; int beforeRear = rear; int beforeFront = front;
top = beforeFront; front = beforeBottom; bottom = beforeRear; rear = beforeTop;
}
void move4(){ // 4번 굴리기, left&right 는 그대로
int beforeTop = top; int beforeBottom = bottom; int beforeRear = rear; int beforeFront = front;
top = beforeRear; front = beforeTop; bottom = beforeFront; rear = beforeBottom;
}
}
문제에 주어진 1,2,3,4 번 움직임에 따라 어느 면이 어느 위치로 이동하는지를 move1,2,3,4
메소드로 구현했다.
move
만약 map
의 범위를 벗어나는 move
를 하게 될 때는 무시해야 한다. 따라서 무작정 move
를 해줄 게 아니라 범위를 먼저 확인한 후에 움직임을 가져야 한다.
이를 위해 범위를 확인한 후에 1. 주사위를 굴리고, 2. 윗면을 출력한다.
int whereToMove = orders[i];
int tmpX = x + moveDirection[whereToMove-1][0];
int tmpY = y + moveDirection[whereToMove-1][1];
if(isInRange(tmpX, tmpY)){
x = tmpX; y = tmpY;
switch(whereToMove){
case 1:
dice.move1();
break;
case 2:
dice.move2();
break;
case 3:
dice.move3();
break;
case 4:
dice.move4();
break;
default:
break;
}
if(map[x][y]==0){ // 지도가 0이면
map[x][y] = dice.bottom;
}
else{ // 지도가 0이 아니면
dice.bottom = map[x][y];
map[x][y] = 0;
}
bfw.write(String.valueOf(dice.top) + "\n");
}
이렇게 범위를 확인해주게 되면 움직일 수 없을 경우에는 move
명령을 무시하고 그냥 지나치게 된다.
아래는 내가 제출한 코드다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.util.StringTokenizer;
public class boj14499 {
static int n,m,x,y,k;
static int[][] map;
static int[] orders;
static int[][] moveDirection = { {0,1}, {0,-1}, {-1,0}, {1,0} };
public static void main(String args[]) throws IOException {
BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer stk = new StringTokenizer(bfr.readLine());
n = Integer.parseInt(stk.nextToken()); m = Integer.parseInt(stk.nextToken());
x = Integer.parseInt(stk.nextToken()); y = Integer.parseInt(stk.nextToken());
k = Integer.parseInt(stk.nextToken());
map = new int[n][m];
for(int i=0; i<n; i++){ // 지도 입력
stk = new StringTokenizer(bfr.readLine());
for(int j=0; j<m; j++)
map[i][j] = Integer.parseInt(stk.nextToken());
}
orders = new int[k];
stk = new StringTokenizer(bfr.readLine());
for(int i=0; i<k; i++) // 명령 입력
orders[i] = Integer.parseInt(stk.nextToken());
Dice dice = new Dice();
for(int i=0; i<k; i++){
int whereToMove = orders[i];
int tmpX = x + moveDirection[whereToMove-1][0];
int tmpY = y + moveDirection[whereToMove-1][1];
if(isInRange(tmpX, tmpY)){
x = tmpX; y = tmpY;
switch(whereToMove){
case 1:
dice.move1();
break;
case 2:
dice.move2();
break;
case 3:
dice.move3();
break;
case 4:
dice.move4();
break;
default:
break;
}
if(map[x][y]==0){ // 지도가 0이면
map[x][y] = dice.bottom;
}
else{ // 지도가 0이 아니면
dice.bottom = map[x][y];
map[x][y] = 0;
}
bfw.write(String.valueOf(dice.top) + "\n");
}
}
bfw.close();
}
static class Dice {
int top, bottom, rear, front, left, right;
Dice(){
top = 0; bottom = 0; rear = 0; front = 0; left = 0; right = 0;
}
void move1(){ // 1번 굴리기, rear&front 은 그대로
int beforeTop = top; int beforeBottom = bottom; int beforeLeft = left; int beforeRight = right;
top = beforeLeft; left = beforeBottom; bottom = beforeRight; right = beforeTop;
}
void move2(){ // 2번 굴리기, rear&front 은 그대로
int beforeTop = top; int beforeBottom = bottom; int beforeLeft = left; int beforeRight = right;
top = beforeRight; right = beforeBottom; bottom = beforeLeft; left = beforeTop;
}
void move3(){ // 3번 굴리기, left&right 는 그대로
int beforeTop = top; int beforeBottom = bottom; int beforeRear = rear; int beforeFront = front;
top = beforeFront; front = beforeBottom; bottom = beforeRear; rear = beforeTop;
}
void move4(){ // 4번 굴리기, left&right 는 그대로
int beforeTop = top; int beforeBottom = bottom; int beforeRear = rear; int beforeFront = front;
top = beforeRear; front = beforeTop; bottom = beforeFront; rear = beforeBottom;
}
}
static Boolean isInRange(int x, int y){
if(0<=x && x<n && 0<=y && y<m) return true;
else return false;
}
}
처음에 ArrayIndexOutOfBounds
를 만난 이유는 map
의 범위에 맞는 움직임인지 확인해주지 않아 범위를 벗어나게 되어 발생했다. 문제가 길다보니 놓칠 때가 많다.