백준/구현
백엔드 20061 c++ "모노미노도미노 2" -PlusUltraCode-
PlusUltraCode
2025. 7. 21. 08:49
https://www.acmicpc.net/problem/20061
[필사 사고]
단순 구현 문제라고 생각했지만 의외로 조건들이 많아서 힘들었다.
블록들을 내리는 방식과
갱신되고
특정 조건에서 다시 update해주는게 처음 마주한 입장에서 다소 힘들었다.
[코드 해설]
1. dropGreen(int t, int x, int y)
초록색 보드에 블록을 떨어뜨리는 함수입니다.
블록의 종류(t)에 따라 다음과 같이 다르게 동작합니다:
- t == 1: 1x1 크기의 블록입니다. 해당 열에서 가장 아래까지 빈 칸을 찾아 내려보내고, 해당 위치에 블록을 놓습니다.
- t == 2: 1x2 가로 블록입니다. y열과 y+1열을 동시에 고려하면서 아래로 떨어뜨립니다. 두 칸 모두 비어있는 가장 아래 행을 찾아 그 행에 블록을 놓습니다.
- t == 3: 2x1 세로 블록입니다. y열을 기준으로 두 행을 차지하므로, 아래로 두 칸을 차지할 수 있는 위치를 찾아 해당 두 칸에 블록을 놓습니다.
2. dropBlue(int t, int x, int y)
파란색 보드에 블록을 떨어뜨리는 함수입니다.
방향이 오른쪽이라는 점만 제외하면 dropGreen과 로직이 유사합니다.
- t == 1: 1x1 블록입니다. x행의 가장 오른쪽까지 가면서 비어있는 위치를 찾고 해당 열에 놓습니다.
- t == 2: 1x2 가로 블록입니다. 파란 보드에서는 같은 행의 연속된 두 칸이므로, 오른쪽으로 두 칸 모두 비어있는 곳을 찾아 블록을 놓습니다.
- t == 3: 2x1 세로 블록입니다. 파란 보드에서는 x, x+1 두 행의 같은 열에 놓이므로, 오른쪽 열들 중 두 행이 모두 비어있는 열을 찾아 해당 열에 놓습니다.
3. cleanGreen()
초록 보드에서 점수를 얻는 처리 함수입니다.
가장 아래쪽 행부터 위로 2번 행까지 확인합니다.
- 한 행이 모두 1로 가득 차 있다면 해당 행을 제거하고, 그 위의 모든 행을 한 칸씩 아래로 당깁니다.
- 가장 위 행(0행)은 0으로 초기화합니다.
- 한 줄이 지워지면 점수(score)를 1점 추가합니다.
- 지운 이후에도 같은 행을 다시 확인해야 하므로, i++로 인덱스를 복원합니다.
4. cleanBlue()
파란 보드에서 점수를 얻는 처리 함수입니다.
방향이 오른쪽이라는 점만 다르고, cleanGreen과 거의 동일한 로직입니다.
- 5번 열부터 2번 열까지 확인하며, 해당 열이 모두 1로 가득 차 있으면 지우고 점수를 1점 얻습니다.
- 지운 열의 왼쪽 열들을 오른쪽으로 한 칸씩 밀고, 가장 왼쪽 열은 0으로 초기화합니다.
- j++로 지운 열을 다시 검사합니다.
5. shiftGreen()
초록 보드의 연한 구역(0, 1행)에 블록이 존재하는 경우를 처리하는 함수입니다.
- 0행 또는 1행에 블록이 존재하면, 존재하는 행의 수만큼 아래로 전체를 밀어야 합니다.
- cnt는 연한 구역(0행, 1행)에 블록이 있는 행의 수입니다.
- cnt만큼 전체를 아래로 한 칸씩 밀고, 가장 위 행(0행)은 0으로 초기화합니다.
이 로직은 **게임 규칙의 "연한 색 블록 처리"**를 구현한 것입니다.
6. shiftBlue()
파란 보드의 연한 구역(0, 1열)에 블록이 존재하는 경우를 처리하는 함수입니다.
- 0열 또는 1열에 블록이 존재하면, 존재하는 열의 수만큼 전체를 오른쪽으로 밀어야 합니다.
- cnt는 연한 구역(0열, 1열)에 블록이 있는 열의 수입니다.
- cnt만큼 전체를 오른쪽으로 한 칸씩 밀고, 가장 왼쪽 열(0열)은 0으로 초기화합니다.
마찬가지로 **게임 규칙의 "연한 색 블록 처리"**를 구현한 것입니다.
[소스 코드]
#include <iostream>
#include <vector>
using namespace std;
int N, score = 0;
int green[6][4], blue[4][6];
void dropGreen(int t, int x, int y) {
int r = 0;
if (t == 1) {
while (r + 1 < 6 && green[r + 1][y] == 0) r++;
green[r][y] = 1;
}
else if (t == 2) {
while (r + 1 < 6 && green[r + 1][y] == 0 && green[r + 1][y + 1] == 0)r++;
green[r][y] = green[r][y + 1] = 1;
}
else {
while (r + 2 < 6 && green[r + 2][y] == 0)r++;
green[r][y] = green[r + 1][y] = 1;
}
}
void dropBlue(int t, int x, int y) {
int c = 0;
if (t == 1) {
while (c + 1 < 6 && blue[x][c + 1] == 0) c++;
blue[x][c] = 1;
}
else if (t == 2) { // 가로 블록
while (c + 2 < 6 && blue[x][c + 2] == 0) c++;
blue[x][c] = blue[x][c + 1] = 1;
}
else { // 세로 블록
while (c + 1 < 6 && blue[x][c + 1] == 0 && blue[x + 1][c + 1] == 0) c++;
blue[x][c] = blue[x + 1][c] = 1;
}
}
void cleanGreen() {
for (int i = 5; i >= 2; i--) {
bool full = true;
for (int j = 0; j < 4; j++) {
if (green[i][j] == 0)full = false;
}
if (full) {
score++;
for (int r = i; r >= 1; r--) {
for (int c = 0; c < 4; c++) {
green[r][c] = green[r - 1][c];
}
}
for (int c = 0; c < 4; c++)green[0][c] = 0;
i++;
}
}
}
void cleanBlue() {
for (int j = 5; j >= 2; j--) {
bool full = true;
for (int i = 0; i < 4; i++)
if (blue[i][j] == 0) full = false;
if (full) {
score++;
for (int c = j; c >= 1; c--)
for (int r = 0; r < 4; r++)
blue[r][c] = blue[r][c - 1];
for (int r = 0; r < 4; r++) blue[r][0] = 0;
j++;
}
}
}
void shiftGreen() {
int cnt = 0;
for (int i = 0; i <= 1; i++) {
for (int j = 0; j < 4; j++) {
if (green[i][j]) {
cnt++;
break;
}
}
}
while (cnt--) {
for (int i = 5; i >= 1; i--) {
for (int j = 0; j < 4; j++) {
green[i][j] = green[i - 1][j];
}
}
for (int j = 0; j < 4; j++)green[0][j] = 0;
}
}
void shiftBlue() {
int cnt = 0;
for (int j = 0; j <= 1; j++) {
for (int i = 0; i < 4; i++) {
if (blue[i][j]) {
cnt++;
break;
}
}
}
while (cnt--) {
for (int j = 5; j >= 1; j--)
for (int i = 0; i < 4; i++)
blue[i][j] = blue[i][j - 1];
for (int i = 0; i < 4; i++) blue[i][0] = 0;
}
}