[프로그래머스 / JAVA] [1차] 프렌즈4블록 (정답 코드 / not good)
막히거나 틀린 부분이 있더라도, 그냥 그대로 내가 스스로 작성한 부분들을 기록하고 있다.
미래의 복기용으로 나를 위해 적어둔 기록이다.
(이 사람은 어떻게 실패하거나 성공했는지 살펴보는 용도로도 적합할 것 같다.)
너무 오랫동안 푼 문제라서 기록으로 남겨본다.
처음에는 이 게임판을 그냥 char[][] 형식으로 설정했는데, 만들다 보니까 각 열을 (수직) 하나의 ArrayList로 두고 맨 아래를 index 0으로 설정하고 만들면 remove()를 통해서 그냥 빈칸이 메꿔질 수 있겠다는 생각이 들었다.
ArrayList 중간의 요소를 삭제하면 뒤에서부터 앞으로 당겨지는데, 마찬가지로 블록들도 위에서 아래로 쌓이기 때문이다.
근데 일단 구현 중간에 이 아이디어가 떠올라서, 일단은 배열을 빡구현하는 방식으로 풀어보았다.
다음 글에서 ArrayList를 활용한 풀이를 올려볼 생각이다.
이렇게 푸니, 만들어야 할 메서드도 너무 많고 시간도 너무 오래걸렸다.
그리고 중간에 오류도 너무 많아져서, 디버깅에 시간이 너무 오래 걸렸다.
자잘한 버그들을 피하려면 최대한 제공하는 자료구조나 라이브러리의 이점을 활용하자.
import java.util.*;
class Solution {
private static char[][] Board;
private static boolean[][] EraseMap; // 선택되어 지워져야할 블록 체크
private static int M, N;
private static int Cnt = 0;
public int solution(int m, int n, String[] board) {
M = m;
N = n;
Board = new char[M][N];
// Board 채우기
for(int i = 0; i < M; i++) {
char[] row = board[i].toCharArray();
for (int j = 0; j < N; j++) {
Board[i][j] = row[j];
}
}
// 2x2 안찾아질때까지 반복
while(true) {
EraseMap = new boolean[M][N];
boolean found = false;
for (int i = 0; i < M-1; i++) {
for (int j = 0; j < N-1; j++) {
if(isSameTwoTwo(i, j)) { // 2x2 발견
deleteTwoTwo(i, j);
found = true;
}
}
}
if(found == false) // 2x2발견 못하면 종료
break;
else { // 2x2 발견 다 하면 이제 ' ' 로 표시된 부분 위에서 아래로 빈칸 다 매꿔주기
fillBlanks();
found = false; // 내린 다음 또 발견을 위해 false으로 초기화
}
}
// System.out.println(Arrays.deepToString(Board));
return Cnt;
}
private static boolean isSameTwoTwo(int r, int c) {
char leftTop = Board[r][c];
if (leftTop == ' ')
return false;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
if (!isInside(r, c) || Board[r + i][c + j] != leftTop) {
return false;
}
}
}
return true;
}
private static void deleteTwoTwo(int r, int c) { // Erase 맵에 지워야할 블록 체크
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
if(EraseMap[r + i][c + j] == false) {
EraseMap[r + i][c + j] = true;
Cnt++;
}
}
}
}
private static void fillBlanks() {
// 먼저 EraseMap 참고해서 빈칸으로 다 바꿔주기
// System.out.println("before");
// printBoard(Board);
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
if(EraseMap[i][j] == true) {
Board[i][j] = ' ';
EraseMap[i][j] = false;
}
}
}
// System.out.println("middle");
// printBoard(Board);
// 왼쪽 열부터 오른쪽으로 훑기
for (int c = 0; c < N; c++) {
// 아래 행부터 위로 훑기 (빈칸 찾기)
int lowestBlankRow = -1; // 빈칸중 맨 아래
for (int r = M - 1; r >= 0; r--) {
if (lowestBlankRow == -1 && Board[r][c] == ' ') { // 제일 아래 빈칸 찾았으면
lowestBlankRow = r;
} else if (lowestBlankRow != -1 && Board[r][c] != ' ') { // 아래 빈칸이 있는데 채워져있는 블록을 찾음
char block = Board[r][c];
Board[lowestBlankRow][c] = block; // 아래의 빈칸 위에서 내려서 채우기
Board[r][c] = ' '; // 아래로 내렸으니 빈칸으로 만들기
r = lowestBlankRow;
lowestBlankRow = -1; // 다시 탐색을 위해 초기화
}
}
}
// System.out.println("after");
// printBoard(Board);
}
private static boolean isInside(int r, int c) {
return (0 <= r && r < M && 0 <= c && c < N);
}
private static void printBoard(char[][] board) {
for(char[] row : board) {
System.out.println(Arrays.toString(row));
}
}
}
하루에 한 문제 이상 꾸준히 풀자.
실수는 많이 할수록, 더 많이 배울 수 있다.
https://school.programmers.co.kr/learn/courses/30/lessons/17679
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr