문제
https://school.programmers.co.kr/learn/courses/30/lessons/17679
프로그래머스
SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
m x n 크기의 게임판이 있다.
같은 그림의 2x2 블록은 지워진다.
블록이 지워진 후에는 위에 있는 블록이 아래로 떨어져 빈 공간을 채우게 된다.
첫 배치가 주어졌을 때, 지워지는 블록이 모두 몇 개인지 계산하려고 한다.


- 2 ≤ `n`, `m` ≤ 30
풀이
더 이상 지워지는 블록이 없을 때까지 아래의 계산을 반복한다.
- 게임판을 순회하면서 같은 그림의 2x2 블록을 찾아서 지워질 모든 블록의 좌표를 계산한다. (`check2x2(map)`)
- 지워질 모든 블록을 0으로 변환하며 지워지는 블록을 계산한다. (`replace(map, postitions)`)
- 중력이 작용하는 것처럼, 블록을 아래로 떨어뜨린다. (`applyGravity(map)`)
2x2 크기에서 겹치는 좌표가 있을 수 있으므로 중복된 좌표를 제거해야 했다. 블록의 좌표를 `[x, y]` 형태의 배열에 담았었는데, 배열에 담았기에 그대로 Set에 넣어 제거하는 것은 불가능했다. 문자열로 변환한 뒤(`JSON.stringify`), 이것을 다시 파싱하여(`JSON.parse`) 중복을 제거했다.
중력을 작용시켜 떨어뜨리는 로직은 2중 반복문으로 작성할 수 있었다. 열을 기준으로 중력을 작용시켜 떨어뜨렸다. 블록이 있다면 `lowestEmptyRow`까지 떨어뜨리게 된다. 0이 아니라면 `lowestEmptyRow`를 감소시켜 한 칸씩 떨어져야 하는 위치를 위로 올리기 때문에, 블록이 떨어져야 하는 가장 아래 칸의 위치를 보장할 수 있다.
코드
function solution(m, n, board) {
const map = board.map(line => line.split(""));
let removedBlocks = 0;
while (true) {
// 맵을 순회하면서 2x2를 체크한다.
const toBeRemoved = check2x2(map, m, n);
if (toBeRemoved.length === 0) break;
// 체크된 칸들을 0으로 변환한다.
const blocks = replace(map, toBeRemoved);
removedBlocks += blocks;
// 블록을 아래로 떨어뜨린다.
applyGravity(map);
}
return removedBlocks;
}
function check2x2(map) {
const arr = [];
for (let i = 0; i < map.length - 1; i++) {
for (let j = 0; j < map[0].length - 1; j++) {
if (map[i][j] === 0) continue;
if (map[i][j] === map[i][j + 1]
&& map[i][j + 1] === map[i + 1][j]
&& map[i + 1][j] === map[i + 1][j + 1]) {
arr.push([i, j]); arr.push([i, j + 1]);
arr.push([i + 1, j]); arr.push([i + 1, j + 1]);
}
}
}
return Array.from(new Set((arr.map(e => JSON.stringify(e))))).map(str => JSON.parse(str));
}
function replace(map, positions) {
let blocks = 0;
for (const [x, y] of positions) {
map[x][y] = 0;
blocks++;
}
return blocks;
}
function applyGravity(map) {
const rows = map.length;
const cols = map[0].length;
for (let j = 0; j < cols; j++) {
let lowestEmptyRow = rows - 1;
for (let i = lowestEmptyRow; i >= 0; i--) {
if (map[i][j] !== 0) {
if (i !== lowestEmptyRow) {
map[lowestEmptyRow][j] = map[i][j];
map[i][j] = 0;
}
lowestEmptyRow--;
}
}
}
}'Problem Solving > 프로그래머스' 카테고리의 다른 글
| [프로그래머스/JavaScript] 조이스틱 (0) | 2025.08.21 |
|---|---|
| [프로그래머스/JavaScript] 소수 찾기 (1) | 2025.07.18 |
| [프로그래머스/JavaScript] 파일명 정렬 (0) | 2025.07.01 |
| [프로그래머스/JavaScript] 주차 요금 계산 (0) | 2025.07.01 |
| [프로그래머스/Java] 다트 게임 (2) | 2025.05.30 |
