[프로그래머스] 블록 게임

박형진·2022년 6월 25일
0

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


1. 코드

def solution(board):
    """
     블록 모양 
         - 3x2 블록                             - 2x3 블록 
         top_left, top_mid, top_right           top_left, top_right
         btm_left, btm_mid, btm_right           mid_left, mid_right
                                                btm_left, btm_right                           
    """
    
    """검은 블록이 board[x][y]로 떨어질 수 있는지 확인"""
    def check_falling(x, y):
        for x_pos in range(0, x + 1):
            if board[x_pos][y] != 0:
                return False
        return True

    def check_two_three(x, y):
        top_left, top_right = board[x][y], board[x][y + 1]
        mid_left, mid_right = board[x + 1][y], board[x + 1][y + 1]
        btm_left, btm_right = board[x + 2][y], board[x + 2][y + 1]
        if (top_left == 0 and mid_left == 0) and (top_right == mid_right == btm_left == btm_right != 0):
            # todo: mid_left 까지 블록이 떨어질 수 있는지 검사
            if check_falling(x + 1, y):
                board[x][y + 1] = board[x + 1][y + 1] = board[x + 2][y] = board[x + 2][y + 1] = 0
                return True
        elif (top_right == 0 and mid_right == 0) and (top_left == mid_left == btm_left == btm_right != 0):
            # todo: mid_right 까지 블록이 떨어질 수 있는지 검사
            if check_falling(x + 1, y + 1):
                board[x][y] = board[x + 1][y] = board[x + 2][y] = board[x + 2][y + 1] = 0
                return True
        return False

    def check_three_two(x, y):
        top_left, top_mid, top_right = board[x][y], board[x][y + 1], board[x][y + 2]
        btm_left, btm_mid, btm_right = board[x + 1][y], board[x + 1][y + 1], board[x + 1][y + 2]
        if (top_left == 0 and top_right == 0) and (top_mid == btm_left == btm_mid == btm_right != 0):
            # todo: top_left 와 top_right 까지 블록이 떨어질 수 있는지 검사
            if check_falling(x, y) and check_falling(x, y + 2):
                board[x][y + 1] = board[x + 1][y] = board[x + 1][y + 1] = board[x + 1][y + 2] = 0
                return True
        elif (top_left == 0 and top_mid == 0) and (top_right == btm_left == btm_mid == btm_right != 0):
            # todo: top_left 와 top_mid 까지 블록이 떨어질 수 있는지 검사
            if check_falling(x, y) and check_falling(x, y + 1):
                board[x][y + 2] = board[x + 1][y] = board[x + 1][y + 1] = board[x + 1][y + 2] = 0
                return True
        elif (top_mid == 0 and top_right == 0) and (top_left == btm_left == btm_mid == btm_right != 0):
            # todo: top_mid 와 top_right 까지 블록이 떨어질 수 있는지 검사
            if check_falling(x, y + 1) and check_falling(x, y + 2):
                board[x][y] = board[x + 1][y] = board[x + 1][y + 1] = board[x + 1][y + 2] = 0
                return True
        return False

    answer = 0
    while True:
        remove = False
        """2x3 블록 단위 탐색"""
        for i in range(len(board) - 2):
            for j in range(len(board[0]) - 1):
                if check_two_three(i, j):
                    remove = True
                    answer += 1
        """3x2 블록 단위 탐색"""
        for i in range(len(board) - 1):
            for j in range(len(board[0]) - 2):
                if check_three_two(i, j):
                    remove = True
                    answer += 1
        if not remove:
            break
    return answer

2. 후기

이 문제는 블록의 숫자를 구분할 필요가 없고, 블록이 제거되는 경우가 한정적이기 때문에 전체 board를 2x3, 3x2 단위로 탐색하면서 블록이 제거될 수 있는지 확인했다.

블록이 제거될 수 있는 조건은 위의 조건 단 하나만 존재한다.

즉, 기존 블록들이 처음부터 겹쳐져서 2x3 또는 3x2 칸을 모두 채우고 있더라도 검은 블록이 없기 때문에 위의 조건을 충족하지 못한다.

또한 2x3 또는 3x2 탐색 단위 안에 블록이 겹쳐져 있고 검은 블록이 떨어져 두 블럭이 모두 제거 조건을 충족하여 두 개의 블록 둘 다 제거되야 하는지 고민할 수 있다. 하지만 조건을 읽어보면 그 블록 이라는 표현을 사용하는데, 오직 하나의 블록만이 제거됨을 의미한다.

결과적으로 이 문제는 탐색 단위내에 하나의 블록만 존재하고, 검은 블록을 통해 그 블록이 제거될 수 있는지 없는지만 판별하면 된다.

profile
안녕하세요!

0개의 댓글