본문 바로가기

알고리즘 (2020 : 08 : 10 ~ )/구현, 시뮬

[백준 / BOJ] 4577 소코반

문제

출처 : https://www.acmicpc.net/problem/4577

 

4577번: 소코반

소코반은 1982년에 일본에서 만들어진 게임으로, 일본어로 창고지기라는 뜻이다. 이 게임은 캐릭터를 이용해 창고 안에 있는 박스를 모두 목표점으로 옮기는 게임이다. 목표점의 수와 박스의 수

www.acmicpc.net

"소코반"이라는 게임을 플레이하는 시뮬레이터를 만들어야한다.

행과 열 R,C가 주어지고, 소코반의 상태가 주어진다.

 

. 빈공간

# 벽

+ 비어있는 목표점

b 박스

B 목표점 위에 있는 박스

w 캐릭터 

W 목표점 위에 있는 캐릭터

 

이후, 캐릭터의 이동방향이 주어진다. UDLR(각각 up, down, left, right)

이때, 소코반게임이 끝나거나 캐릭터 이동이 끝났을때의 보드 상태를 출력하는 문제다.


풀이

문제가 시키는대로 하면 되는 구현 문제다.

로직

1. 소코반게임에서 캐릭터를 이동시킬수있는지 확인한다.

    private boolean moveChecker(char[][] arr, int y, int x, char dir){
        int _y = y + dy[(int)dir - (int)'A'];
        int _x = x + dx[(int)dir - (int)'A'];
        if(!outOfIndex(_y, _x) && arr[_y][_x] != 'b' && arr[_y][_x] != 'B' && arr[_y][_x] != '#') return true;
        if(!outOfIndex(_y, _x) && arr[_y][_x] == 'b' || arr[_y][_x] == 'B'){ // 다음 위치가 박스인경우
            int __y = _y + dy[(int)dir - (int)'A'];
            int __x = _x + dx[(int)dir - (int)'A'];
            if(outOfIndex(__y, __x) || arr[__y][__x] == 'b' || arr[__y][__x] == 'B' || arr[__y][__x] == '#') return false; // 이동위치가 박스거나 벽이라면 false
            return true;
        }
        return false;
    }
    private boolean outOfIndex(int y, int x){
        return (y < 0 || x < 0 || y >= N || x >= M);
    }

이때, dy, dx 배열에서 값을 가져오는 방식을 보자. 이동방향이 char형식으로 주어졌을때 써먹을수있는 나름 꿀팁이다...

 

2. 이동시킬수 있다면 이동시킨다. 이때, 다음위치가 목표점에 해당하는지 유심히 확인해야한다.

예를들어, 캐릭터가 왼쪽으로 이동해야할때, 왼쪽박스가 'B'인 경우이다. 캐릭터는 왼쪽으로 박스를 밀면서 이동하고, 이때, 캐릭터는 'W'가 된다.

    private char[][] move(char[][] arr, int y, int x, char dir){
        int _y = y + dy[(int)dir - (int)'A'];
        int _x = x + dx[(int)dir - (int)'A'];
        if(arr[_y][_x] == '.' || arr[_y][_x] == '+'){
            if(targetCheck(arr, y, x)) arr[y][x] = '+';
            else arr[y][x] = '.';
            if(targetCheck(arr, _y, _x)) arr[_y][_x] = 'W';
            else arr[_y][_x] = 'w';
        }
        if(arr[_y][_x] == 'b' || arr[_y][_x] == 'B'){
            if(targetCheck(arr, y, x)) arr[y][x] = '+';
            else arr[y][x] = '.';
            if(targetCheck(arr, _y, _x)) arr[_y][_x] = 'W';
            else arr[_y][_x] = 'w';
            int __y = _y + dy[(int)dir - (int)'A'];
            int __x = _x + dx[(int)dir - (int)'A'];
            if(targetCheck(arr, __y, __x)) arr[__y][__x] = 'B';
            else arr[__y][__x] = 'b';
        }
        return arr;
    }
    private boolean targetCheck(char[][] arr, int y, int x){
        return (arr[y][x] >= (int)'A' && arr[y][x] <= (int)'Z') || arr[y][x] == '+';
    }

3. 매 이동마다, 게임이 종료됐는지 확인한다. 

문제에 명시되어 있는 것 처럼 게임이 종료되면 더 이상 캐릭터를 이동하면 안된다.

    private boolean isFinish(char[][] arr){
        for(int i = 0; i < N; i++)
            for(int j = 0; j < M; j++) 
                if(arr[i][j] == 'b') return false;
        return true;
    }

전체소스코드

https://github.com/devxb/JJUNalgo/blob/master/BOJ%20source%20code/4577%20%EC%86%8C%EC%BD%94%EB%B0%98/Main.java

 

GitHub - devxb/JJUNalgo: 백준 알고리즘 소스코드🙃

백준 알고리즘 소스코드🙃. Contribute to devxb/JJUNalgo development by creating an account on GitHub.

github.com