본문 바로가기

Algorithm/Algorithm Test

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

카테고리

로직 짜기

나만의 카테고리

테트리스

문제 링크

https://programmers.co.kr/learn/courses/30/lessons/17679

 

코딩테스트 연습 - [1차] 프렌즈4블록

프렌즈4블록 블라인드 공채를 통과한 신입 사원 라이언은 신규 게임 개발 업무를 맡게 되었다. 이번에 출시할 게임 제목은 "프렌즈4블록". 같은 모양의 카카오프렌즈 블록이 2×2 형태로 4개가 붙

programmers.co.kr

요점

  • 블락을 내려보내는 테트리스 문제는 for문을 역으로 순회해야한다.

참고 지식

  • String.toCharArray()

풀이 (Java)

import java.util.*;

class Solution {
    private char[][] glbBoard;
    
    public int solution(int m, int n, String[] board) {
        glbBoard = new char[m][n];
        
        for (int i = 0; i < m; i++) {
            glbBoard[i] = board[i].toCharArray(); 
        }
        
        int answer = 0;
        while(true) {
            int count = deleteQuad(m, n);
            if (count == 0) break;
            
            dropBlock(m, n);
            answer += count;
        }

        return answer;
    }
    
    private int deleteQuad(int m, int n) {
        List<List<Integer>> deleteTargetList = new ArrayList<>();
        
        for (int i = 0; i < m - 1; i++) {
            for (int j = 0; j < n - 1; j++) {
                if (isDeletable(i, j)) {
                    deleteTargetList.add(Arrays.asList(i, j));
                }
            }
        }
        
        int count = 0;
        for (List<Integer> temp : deleteTargetList) {
            count += deleteQuadBlock(temp.get(0), temp.get(1));
        }
        
        return count;
    }
    
    private int deleteQuadBlock(int row, int col) {
        int count = 0;
        
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                if (glbBoard[row + i][col + j] != '-') {
                    glbBoard[row + i][col + j] = '-';
                    count++;
                }
            }
        }
        
        return count;
    }
    
    private void dropBlock(int m, int n) {
		for(int i = 0 ; i < n ; i++) {
			for(int j = m - 1 ; j >= 0 ; j--) {
				if(glbBoard[j][i] == '-') {
					for(int k = j - 1 ; k >= 0 ; k--) {
						if(glbBoard[k][i] != '-') {
							glbBoard[j][i] = glbBoard[k][i];
							glbBoard[k][i] = '-';
							break;
						}
					}
				}
			}
		}
	}
    
    private boolean isDeletable(int row, int col) {
        return (glbBoard[row][col] == glbBoard[row][col + 1])
            && (glbBoard[row][col] == glbBoard[row + 1][col])
            && (glbBoard[row][col] == glbBoard[row + 1][col + 1]);
    }
}

 

일단은 각 행이 String으로 구성되어 있으면 Java에서는 하나씩 접근하기가 힘듭니다. 그래서 char 객체 하나씩 분리하여 배열을 변환합니다. 이후의 로직은 아래와 같습니다.

  • 지워야 할 블록 찾아서 리스트에 저장
  • 위의 리스트의 블록 제거
  • 블록 내리기
  • 지울 블록이 없을 때까지 반복

여기서 블록 내리기가 가장 어려웠습니다. 처음에는 배열의 윗부분([0][0])부터 밑에 블록이 비어있으면 내리면 되겠다 싶었는데 테스트를 통과하지 못했습니다. 배열의 윗 부분부터 검사한다면 중간에 빈 부분이 생기게 됩니다. 

 

그래서 동일한 방법을 배열의 밑 부분부터 처리해야 정상적으로 처리할 수 있게 됩니다.


알고리즘 초보가 정리한 글입니다

더 좋은 방법이나 코드에 대한 코멘트 언제나 환영합니다!

 

 

 

반응형