본문 바로가기

알고리즘/문제 풀이

💜 백준 3109 뱀 JAVA

1. 문제 분석

[3190 뱀 문제 링크](https://www.acmicpc.net/problem/3190)

지렁이 게임의 원리대로 움직이는 문제 빈 공간은 0, 사과는 1, 뱀이 존재하는 자리는 2로 표시한다.

  1. 뱀이 2차원 배열 내를 움직임 -> 움직이니까, 지나간 장소는 2가 아니라 다시 0으로 와야함.
  2. 사과를 먹으면 뱀의 몸집이 1 커짐
  3. 뱀이 벽에 부딪히면 게임오버
  4. 뱀이 자신의 몸에 부딪히면 게임오버
  5. 뱀은 방향 전환이 가능 -> 몇 초에 반시계, 시계 방향 중 어디로 움직일지는 주어진다.
  6. 게임이 몇 초간 걸리는지 구하기 (뱀은 한 번 움직일 떄, 2차원 배열에서 한 칸 움직이고, 이떄 시간이 1 든다.)

2. 푸는 원리

저기 나오는 1~5를 함수로 작성해서, 함수가 돌아가도록 하면 된다.

처음에는 Stream으로 풀려고 했는데, 백준에서는 List의 getFirst()라든가 removeLast() 라든가부터 Stream 전반을 사용하지 못해서 Legacy하게 바꾸는 것이 일이었다.

3. 코드 분석

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

/*
* 3190번 뱀
* */


public class Main {

    // 0. 정보   N      = 배열의 길이,   apples = 사과의 개수,
    //          map    = 2차원 배열,    idx,idy = 나아갈 방향
    //          snakes = 뱀이 차지하고 있는 공간
    //          nowD   = 뱀의 현재 방향
    //          snakesMovement = [index]가 초, 값이 방향
    // -------- 빈칸: 0, 사과: 1, 뱀: 2
    static int N, apples;
    static int [][] map;
    static int [] idx = {-1,0,1,0};
    static int [] idy = {0,1,0,-1};
    static int nowD = 1;

    static boolean isFinished = false;


    static ArrayList<int []> snakes = new ArrayList<>();

    static char [] snakesMovement = new char [10001];

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));


        // 1. 값 입력 --------------------------------------------------------------------
        N       = Integer.parseInt(br.readLine());
        apples  = Integer.parseInt(br.readLine());

        map     = new int [N][N];

        for (int i = 0; i < N; i++) {
            Arrays.fill(map[i], 0);
        }

        // 1-2. 사과 입력
        for (int i = 0; i < apples; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            map[Integer.parseInt(st.nextToken())-1][Integer.parseInt(st.nextToken())-1] = 1;
        }

        int moveCnt = Integer.parseInt(br.readLine());

        // 1-3. 뱀의 방향전환 입력
        for (int i = 0; i < moveCnt; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            snakesMovement[Integer.parseInt(st.nextToken())] = st.nextToken().charAt(0);
        }

        // 1-4. 뱀의 초기값 입력
        snakes.add(new int[]{0, 0});
        // -------------------------------------------------------------------------------
        // 실행----------------------------------------------------------------------------

        for (int i = 0; i < snakesMovement.length; i++) {




            if(snakesMovement[i] == '0') {
                moving();



                if(isFinished){
                    System.out.println(i+1);
                    return;
                }
                continue;
            }

            snakeTurnAbout(snakesMovement[i]);
            moving();

            if(isFinished){
                System.out.println(i+1);
                return;
            }


        }


    }

    // 2. 방향 전환------------------------------------------------------------------------
    public static void snakeTurnAbout (char direction) {

        switch (direction) {
            case 'D': {

                nowD = nowD == 3? 0 : nowD+1;
                break;
            }

            case 'L': {

                nowD = nowD == 0? 3 : nowD-1;
                break;
            }
        }
    }

    // 3. 자신의 몸과 부딪혔는지 확인
    public static boolean isCrashedWithBody () {

        // 앞 머리가 자신의 몸과 부딪히는지 확인
        int x = snakes.get(0)[0];
        int y = snakes.get(0)[1];


        for (int i = 1; i < snakes.size(); i++) {
            if(snakes.get(i)[0] == x && snakes.get(i)[1] == y){
                return true;
            }
        }

        return false;
        //  백준 Stream 사용이 안됨.
//          return  snakes.stream().skip(1).anyMatch(snakes -> snakes[0] == x && snakes[1] == y);
    }

    // 4. 벽과 부딪혔는지 확인
    public static boolean isCrashedWithWall () {

        // 앞 머리가 자신의 몸과 부딪히는지 확인
        int x = snakes.get(0)[0];
        int y = snakes.get(0)[1];

        return x < 0 || y < 0 || x >= N || y >= N;
    }

    // 5. 움직이기
    public static void moving () {

        int nx = snakes.get(0)[0] + idx[nowD];
        int ny = snakes.get(0)[1] + idy[nowD];

        if(nx>=0 && ny>=0 && nx < N && ny < N && map[nx][ny] == 1 ){
            ateApple(nx,ny);
            return;
        }


        snakes.add(0,new int[]{nx,ny});

        if(isCrashedWithWall() || isCrashedWithBody()){
            isFinished = true;
            return;
        }

        snakes.remove(snakes.size()-1);
    }

    // 6. 사과 먹기
    public static void ateApple(int x, int y) {

        map[x][y] = 0;
        snakes.add(0,new int[]{x,y});
    }
}

'알고리즘 > 문제 풀이' 카테고리의 다른 글

💜 백준 1874번 스택 수열  (0) 2024.04.20
💜 백준 7490. 0 만들기 JAVA  (0) 2024.04.17
💜 백준 2085 사탕게임 JAVA  (0) 2024.04.11
💜 백준 1038 감소하는 수  (0) 2024.04.09
💔 백준 14500 테트로미노  (0) 2024.04.09