[프로그래머스 / JAVA] Level 1 크레인 인형뽑기 게임 (64061)
⏰ 2021-12-14 (화) 14:20:05
크레인 인형뽑기 게임
랭크 | 사용 언어 |
---|---|
Level 1 |
문제 설명
게임개발자인 "죠르디"는 크레인 인형뽑기 기계를 모바일 게임으로 만들려고 합니다. "죠르디"는 게임의 재미를 높이기 위해 화면 구성과 규칙을 다음과 같이 게임 로직에 반영하려고 합니다.
게임 화면은 "1 x 1" 크기의 칸들로 이루어진 "N x N" 크기의 정사각 격자이며 위쪽에는 크레인이 있고 오른쪽에는 바구니가 있습니다. (위 그림은 "5 x 5" 크기의 예시입니다). 각 격자 칸에는 다양한 인형이 들어 있으며 인형이 없는 칸은 빈칸입니다. 모든 인형은 "1 x 1" 크기의 격자 한 칸을 차지하며 격자의 가장 아래 칸부터 차곡차곡 쌓여 있습니다. 게임 사용자는 크레인을 좌우로 움직여서 멈춘 위치에서 가장 위에 있는 인형을 집어 올릴 수 있습니다. 집어 올린 인형은 바구니에 쌓이게 되는 데, 이때 바구니의 가장 아래 칸부터 인형이 순서대로 쌓이게 됩니다. 다음 그림은 [1번, 5번, 3번] 위치에서 순서대로 인형을 집어 올려 바구니에 담은 모습입니다.
만약 같은 모양의 인형 두 개가 바구니에 연속해서 쌓이게 되면 두 인형은 터뜨려지면서 바구니에서 사라지게 됩니다. 위 상태에서 이어서 [5번] 위치에서 인형을 집어 바구니에 쌓으면 같은 모양 인형 두 개가 없어집니다.
크레인 작동 시 인형이 집어지지 않는 경우는 없으나 만약 인형이 없는 곳에서 크레인을 작동시키는 경우에는 아무런 일도 일어나지 않습니다. 또한 바구니는 모든 인형이 들어갈 수 있을 만큼 충분히 크다고 가정합니다. (그림에서는 화면표시 제약으로 5칸만으로 표현하였음)
게임 화면의 격자의 상태가 담긴 2차원 배열 board와 인형을 집기 위해 크레인을 작동시킨 위치가 담긴 배열 moves
가 매개변수로 주어질 때, 크레인을 모두 작동시킨 후 터트려져 사라진 인형의 개수를 return 하도록 solution
함수를 완성해주세요.
제한사항
board
배열은 2차원 배열로 크기는 "5 x 5" 이상 "30 x 30" 이하입니다.board
의 각 칸에는 0 이상 100 이하인 정수가 담겨있습니다.- 0은 빈 칸을 나타냅니다.
- 1 ~ 100의 각 숫자는 각기 다른 인형의 모양을 의미하며 같은 숫자는 같은 모양의 인형을 나타냅니다.
moves
배열의 크기는 1 이상 1,000 이하입니다.moves
배열 각 원소들의 값은 1 이상이며board
배열의 가로 크기 이하인 자연수입니다.
입출력 예
board | moves | result |
---|---|---|
{ { 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 3 }, { 0, 2, 5, 0, 1 }, { 4, 2, 4, 4, 2 }, { 3, 5, 1, 3, 1 } } | { 1, 5, 3, 5, 1, 2, 1, 4 } | 4 |
입출력 예 설명
입출력 예 #1
인형의 처음 상태는 문제에 주어진 예시와 같습니다. 크레인이 [1, 5, 3, 5, 1, 2, 1, 4] 번 위치에서 차례대로 인형을 집어서 바구니에 옮겨 담은 후, 상태는 아래 그림과 같으며 바구니에 담는 과정에서 터트려져 사라진 인형은 4개 입니다.
풀이
- 인형을 뽑는다. 만약 해당 위치에 인형이 없다면 아무것도 뽑지 않는다.
- 뽑은 인형을 바구니에 담는다.
- 방금 뽑은 인형과 마지막으로 뽑았던 인형이 동일하면 삭제한다.
- 삭제한 인형 갯수를 카운팅한다. (삭제 작업 당 +2)
삭제 횟수가 아니라 삭제한 인형의 갯수다. 2개씩 삭제됨에 유의.
크레인을 움직이면서 인형을 하나씩 담는다. 이를 담을 배열이 필요하며, ArrayList
같은 가변 배열이 적절해보인다. 가장 최근에 들어온 데이터로 연산하므로, Stack
의 특성을 적극 활용하고자 한다.
JAVA
1 2 3 4 5 6 7 8 9 10 11 12 13
for (int move : moves) { int j = move - 1; for (int i = 0; i < board.length; i++) { // 인형을 뽑을 경우 if (board[i][j] > 0) { // 동작 } } }
인형을 뽑는 동작은 위와 같다. 열 j
를 기준으로 한 행씩 내려오면서 board[i][j] > 0
인지 확인한다.
해당 인형은 board
에서 제거하고 인형을 스택에 넣는다. 이 때, 스택의 마지막 인형과 뽑은 인형이 같을 경우, 스택의 마지막 인형을 제거하고 삭제한 인형 카운트를 추가한다.
인형이 서로 다르다면, 삭제하지 않고 인형만 스택에 넣는다.
문제를 보다보면 *"인형을 일단 다 뽑고 삭제는 마지막에 한꺼번에 하면 되지 않을까?"*라고 생각하기 쉽지만, 실제로 이렇게 접근하면 더 어렵다.
나중에 한꺼번에 삭제하게 되면, 인형을 삭제하는 순간 다른 인형이 연결될 가능성이 생기므로, 연결된 인형이 없을 때까지 반복적인 연산이 필요하다.
예를 들어, 1 3 2 2 3
의 경우 동일하게 붙은 인형인 2
를 삭제하면 1 3 3
이 된다. 2
가 삭제되며 3
이 붙어버리므로 반복적인 연산이 강제된다.
코드
JAVA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
import java.util.Stack; /** * 크레인 인형뽑기 게임 클래스 * * @author RWB * @since 2021.12.09 Thu 21:40:58 */ class Solution { private final Stack<Integer> bag = new Stack<>(); /** * 해답 반환 메서드 * * @param board: [int[][]] 보드 크기 * @param moves: [int[]] 크레인 작동 위치 * * @return [int] 해답 */ public int solution(int[][] board, int[] moves) { int answer = 0; for (int move : moves) { int j = move - 1; for (int i = 0; i < board.length; i++) { // 인형을 뽑을 경우 if (board[i][j] > 0) { // 뽑은 인형이 있고, 마지막 인형과 방금 뽑은 인형이 동일할 경우 if (!bag.isEmpty() && bag.peek() == board[i][j]) { bag.pop(); answer += 2; } // 아닐 경우 else { bag.push(board[i][j]); } board[i][j] = 0; break; } } } return answer; } }
🏷️ 태그
읽어주셔서 고마워요!
도움이 되셨다면, 공감이나 댓글을 달아주시는 건 어떤가요?
블로그 운영에 큰 힘이 됩니다.