[백준 / 골드4] 3190 뱀 (Java)

Ilhwanee·2022년 12월 3일
0

코딩테스트

목록 보기
132/155
post-custom-banner

문제 보기



사용한 것

  • 뱀을 나타내기 위한 클래스 Snake
    • 뱀의 머리의 좌표 : pos
    • 뱀의 방향 : dir
    • 뱀의 길이 : len
    • 성장(사과 먹고 길이 증가) : growUp()
    • 방향 전환 : rotate()
    • 이동 : move()


풀이 방법

뱀의 머리 좌표를 계속해서 저장하고 뱀이 자신과 부딪혔는지 확인하기 위해 사용한다. (뱀의 머리를 제외한 좌표는 이전 특정 시간 뱀의 머리의 좌표)

  • while 문에서
    • time을 증가시키고 snake.move() 호출
    • isGameOver()가 true면 while 문 종료
      • 벽에 부딪혔는지 확인
      • snake.getLen()만큼 이전 좌표들(positions) 확인해서 부딪혔는지 확인
    • 현재 좌표가 사과면 snake.growUp() 호출
    • command의 현재 time에 방향 전환 커맨드 있으면 snake.rotate()
    • 현재 위치 positions에 저장


코드

public class Main {

    private static int n;
    private static int k;
    private static int l;
    private static boolean[][] apple;
    private static Map<Integer, Character> command;

    public static void main(String[] args) throws IOException {
        input();
        System.out.println(findEndTime());
    }

    private static void input() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] line;
        n = Integer.parseInt(br.readLine());
        k = Integer.parseInt(br.readLine());
        apple = new boolean[n + 1][n + 1];
        command = new HashMap<>();
        for (int i = 0; i < k; i++) {
            line = br.readLine().split(" ");
            int x = Integer.parseInt(line[0]);
            int y = Integer.parseInt(line[1]);
            apple[x][y] = true;
        }
        l = Integer.parseInt(br.readLine());
        for (int i = 0; i < l; i++) {
            line = br.readLine().split(" ");
            int x = Integer.parseInt(line[0]);
            char c = line[1].charAt(0);
            command.put(x, c);
        }
        br.close();
    }

    private static int findEndTime() {
        // 초기화
        int time = 0;
        Snake snake = new Snake();
        List<Position> positions = new ArrayList<>(); // 자신과 부딪히는 경우 위해 경로 저장
        positions.add(new Position(1, 1)); // 시작 위치

        // 탐색
        while (true) {
            time++;
            snake.move();

            // 게임 종료 상황이면 break
            if (isGameOver(snake, time, positions)) {
                break;
            }

            Position p = snake.getPos();
            int x = p.getX();
            int y = p.getY();

            // 사과 먹으면 길이 증가
            if (apple[x][y]) {
                snake.growUp();
                apple[x][y] = false;
            }

            // 커맨드 있으면 방향 전환
            if (command.containsKey(time)) {
                snake.rotate(command.get(time));
            }

            // 현재 위치 경로에 저장
            positions.add(new Position(x, y));
        }

        return time;
    }

    private static boolean isGameOver(Snake snake, int time, List<Position> positions) {
        Position pos = snake.getPos();
        int x = pos.getX();
        int y = pos.getY();

        // 벽에 부딪히면 게임오버
        if (x < 1 || x > n || y < 1 || y > n) {
            return true;
        }

        // 자신과 부딪히면 게임오버
        for (int i = time - 1; i >= time - snake.getLen(); i--) {
            Position prePos = positions.get(i);
            if (x == prePos.getX() && y == prePos.getY()) {
                return true;
            }
        }

        return false;
    }
}

class Snake {

    private Position pos;
    private int dir; // 0 : U, 1 : R, 2 : D, 3 : L
    private int len;

    public Snake() {
        pos = new Position(1, 1);
        dir = 1;
        len = 1;
    }

    public Position getPos() {
        return pos;
    }

    public int getLen() {
        return len;
    }

    public void growUp() {
        len++;
    }

    public void rotate(char c) {
        switch (dir) {
            case 0:
                dir = c == 'L' ? 3 : 1;
                break;
            case 1:
                dir = c == 'L' ? 0 : 2;
                break;
            case 2:
                dir = c == 'L' ? 1 : 3;
                break;
            default:
                dir = c == 'L' ? 2 : 0;
                break;
        }
    }

    public void move() {
        int x = pos.getX();
        int y = pos.getY();
        switch (dir) {
            case 0:
                pos.setX(x - 1);
                break;
            case 1:
                pos.setY(y + 1);
                break;
            case 2:
                pos.setX(x + 1);
                break;
            default:
                pos.setY(y - 1);
                break;
        }
    }
}

class Position {

    private int x;
    private int y;

    public Position(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }
}


profile
블로그 이전 -> https://pppp0722.github.io
post-custom-banner

0개의 댓글