[프로그래머스] Level2 프렌즈4블록 (Java)

MINSANG YU·2022년 9월 23일
0

프로그래머스

목록 보기
11/15
post-thumbnail

문제 링크

핵심

없애야 할 블록을 어떻게 판별할지, 블록을 어떤 방법으로 내릴 지를 빠르게 파악하는 것이 중요했다. 추가적으로 문제에서 주어진 String[] 배열을 그대로 사용할 경우, board의 각 칸을 확인할 때 charAt 메서드를 사용해야 하는데, 코드 가독성이 떨어지고 번거로워서 char 배열로 변환하여 사용했다.

코드

import java.util.*;

class Solution {
    
    static char[][] blocks;
    
    static boolean[][] check(int m, int n) {
        boolean[][] result = new boolean[m][n];
        
        for(int i=0; i<m-1; i++) {
            for(int j=0; j<n-1; j++) {
                if(blocks[i][j]=='x') continue;
                if(blocks[i][j]==blocks[i][j+1] && blocks[i][j]==blocks[i+1][j] 
                   && blocks[i][j]==blocks[i+1][j+1]) {
                    result[i][j] = true;
                    result[i][j+1] = true;
                    result[i+1][j] = true;
                    result[i+1][j+1] = true;
                }   
            }
        }
        return result;
    }
    
    static void drop(int m, int n, boolean[][] result) {
        for(int i=0; i<m; i++) {
            for(int j=0; j<n; j++) {
                if(result[i][j]) blocks[i][j]='x';
            }
        }
        
        for(int i=m-1; i>=0; i--) {
            for(int j=0; j<n; j++) {
                if(blocks[i][j]=='x') {
                    int r = i;
                    while(r>0) {
                        r--;
                        if(blocks[r][j]!='x') break;
                    }
                    blocks[i][j] = blocks[r][j];
                    blocks[r][j] = 'x';
                }
            }
        }
    }
    
    
    public int solution(int m, int n, String[] board) {
        int answer = 0;
        
        blocks = new char[m][n];
        
        for(int i=0; i<m; i++) {
            for(int j=0; j<n; j++) {
                blocks[i][j] = board[i].charAt(j);
            }
        }
   
        while(true) {            
            boolean[][] result = check(m,n);
            int cnt = 0;
            for(int i=0; i<m; i++) {
                for(int j=0; j<n; j++) {
                    if(result[i][j]) cnt++;
                }
            }
            if(cnt==0) break;
            answer+=cnt;
            drop(m,n,result);            
        }
        
        return answer;
    }
}

없애야 할 블록을 판별하는 방법

  • 현재 인덱스가 (r,c)일 때 (r,c+1), (r+1,c),(r+1,c+1)과의 값을 비교해 모두 같으면 없애야 할 블록으로 선정하는 방법을 선택했다.

블록을 없앤 뒤 빈 칸을 내리는 방법

  • 먼저 블록의 이름은 'A~Z'만 사용하므로 없애야 할 칸을 'x' 로 정했다. 그 뒤 편의를 위해 제일 아래 행부터 배열을 탐색하고, 만약 현재 칸 (r,c)의 값이 'x' 라면 (r-1,c),(r-2,c) ... (0,c) 까지 반복해 연속된 x 값들을 찾아내고, x가 아닌 값을 찾았다면 그 값과 (r,c)의 위치를 바꿔주면 요구사항대로 블록을 내릴 수 있다.
profile
쉿! 공부중

0개의 댓글