[ 백준 ] 14499 주사위 굴리기

codesver·2023년 7월 7일
0

Baekjoon

목록 보기
50/72
post-thumbnail

📌 Problem

N x M 크기의 지도가 있으며 정육면체의 주사위 하나가 특정 좌표 X x Y에서 시작한다. 주사위 눈은 모두 0으로 시작하며 동서남북으로 이동할 수 있다. 이동을 할 때마다 주사위가 위치한 곳의 지도 번호에 따라 다른 동작을 한다. 지도 번호가 0이면 주사위의 바닥에 있는 번호를 지도에 복사한다. 만약 0이 아니면 지도에 있는 숫자를 주사위 바닥에 복사하고 해당 위치의 지도는 0으로 초기화 한다. K번의 이동이 주어졌을 때 (동서남북 = 1243) 각 이동 별 주사위 윗면의 숫자를 출력하면 된다. 이 때 지도 밖으로 나가는 이동이 주어지면 해당 이동은 무시하고 출력도 하지 않는다.

📌 Solution

단순 구현 문제이기 때문에 각 이동(동서남북)별로 주사위의 눈들을 바꾼다. 또한 이동 후 지도와 맞닿은 부분의 지도 번호 상태에 따라 주사위 바닥면 눈과 지도 번호를 업데이트한다.

📌 Code

public void solve() throws IOException {
    StringTokenizer tokenizer = new StringTokenizer(reader.readLine());
    int N = Integer.parseInt(tokenizer.nextToken()); // Row Size
    int M = Integer.parseInt(tokenizer.nextToken()); // Column Size
    int x = Integer.parseInt(tokenizer.nextToken()); // Dice init row location
    int y = Integer.parseInt(tokenizer.nextToken()); // Dice init column location
    int K = Integer.parseInt(tokenizer.nextToken()); // Rolling times

    DiceMap diceMap = new DiceMap(N, M, x, y); // Dice and Map

    // Set numbers of the map
    for (int row = 0; row < N; row++) {
        tokenizer = new StringTokenizer(reader.readLine());
        for (int col = 0; col < M; col++)
            diceMap.setMapNumber(row, col, Integer.parseInt(tokenizer.nextToken()));
    }

    // Roll the dice
    tokenizer = new StringTokenizer(reader.readLine());
    while (K-- > 0) {
        Direction direction = switch (Integer.parseInt(tokenizer.nextToken())) {
            case 1 -> Direction.EAST;   // Roll to east direction
            case 2 -> Direction.WEST;   // Roll to west direction
            case 3 -> Direction.NORTH;  // Roll to north direction
            case 4 -> Direction.SOUTH;  // Roll to south direction
            default -> throw new IllegalArgumentException("Not available direction");
        };

        // Print top number of each rolling
        // If out of map then ignore
        try {
            result.append(diceMap.rollDice(direction)).append("\n");
        } catch (ArrayIndexOutOfBoundsException ignored) {
        }
    }
}
class DiceMap {

    private final Dice dice;    // Dice on the map
    private final int[][] map;  // Map's number information

    public DiceMap(int rowSize, int colSize, int diceRowLoc, int diceColLoc) {
        map = new int[rowSize][colSize];
        dice = new Dice(diceRowLoc, diceColLoc);
    }

    /**
     * Set number of map (one by one)
     * @param row Row
     * @param col Column
     * @param num Number
     */
    public void setMapNumber(int row, int col, int num) {
        map[row][col] = num;
    }

    /**
     * Roll the dice
     * @param direction Rolling direction
     * @return Top number of the dice
     */
    public int rollDice(Direction direction) {
        return dice.roll(direction, map);
    }
}

class Dice {

    private int row, col;           // Dice location
    private final Eye top, bottom;  // Top and bottom eye of the dice

    // Rolling sequence of each direction
    private final Map<Direction, List<Eye>> rolls = new HashMap<>();

    public Dice(int row, int col) {
        this.row = row;
        this.col = col;
        top = new Eye();
        bottom = new Eye();
        Eye front = new Eye(), back = new Eye(), right = new Eye(), left = new Eye();
        rolls.put(Direction.NORTH, List.of(back, top, front, bottom));
        rolls.put(Direction.EAST, List.of(right, top, left, bottom));
        rolls.put(Direction.SOUTH, List.of(front, top, back, bottom));
        rolls.put(Direction.WEST, List.of(left, top, right, bottom));
    }

    /**
     * Roll the dice
     * @param direction Rolling direction
     * @param map Map information
     * @return Top number of dice after rolling
     */
    public int roll(Direction direction, int[][] map) {
        int num = map[row + direction.getRow()][col + direction.getCol()];
        row += direction.getRow();
        col += direction.getCol();
        rollEyes(rolls.get(direction));

        // If map number is 0 then copies bottom number
        // Else change dice bottom number and set map number to 0
        if (num == 0) map[row][col] = bottom.getNum();
        else {
            bottom.setNum(map[row][col]);
            map[row][col] = 0;
        }
        return top.getNum();
    }

    /**
     * Change each eye's number
     * @param eyes Eye number changing sequence
     */
    private void rollEyes(List<Eye> eyes) {
        int temp = eyes.get(0).getNum();
        eyes.get(0).setNum(eyes.get(1).getNum());
        eyes.get(1).setNum(eyes.get(2).getNum());
        eyes.get(2).setNum(eyes.get(3).getNum());
        eyes.get(3).setNum(temp);
    }
}

class Eye {

    private int num;

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }
}

enum Direction {
    NORTH(-1, 0), EAST(0, 1), SOUTH(1, 0), WEST(0, -1);

    private final int row, col;

    Direction(int row, int col) {
        this.row = row;
        this.col = col;
    }

    public int getRow() {
        return row;
    }

    public int getCol() {
        return col;
    }
}
profile
Hello, Devs!

0개의 댓글