코드굽는 타자기
Baekjoon[19235] - 모노미노도미노 본문
링크
문제설명
- 테트리스 시뮬레이션
문제풀이
- 테트리스와는 조금 다른게 덩어리 기준으로 내려갈 수 있다. 덩어리끼리 접착제 붙여놓지 않았다고 생각하면 편함.
- 덩어리 체크를 해야함.
문제코드
import java.util.Scanner;
public class Main19235_모노미노도미노 {
public static int[][] map = new int[10][10];
public static int score = 0;
public static int[][] dir = {
{0,1},//우
{-1,0}//하
};
// 조각만 이동
public static void moveRight(int t, int x, int y, int num) {
int[] a;
int[] b;
switch (t) {
case 1:
a = new int[] {x,y};
for (int r = 0; r < 9; r++) {
if(a[1]+1 < 10 && map[a[0]][a[1]+1]==0) {
a[1]++;
}
}
map[a[0]][a[1]]=num;
break;
case 2:
a = new int[] {x,y};
b = new int[] {x,y+1};
for (int r = 0; r < 9; r++) {
if(a[1]+1 < 10 && b[1]+1 < 10 && map[a[0]][a[1]+1]==0 && map[b[0]][b[1]+1]==0) {
a[1]++;
b[1]++;
}
}
map[a[0]][a[1]]=num;
map[b[0]][b[1]]=num;
break;
case 3:
a = new int[] {x+1,y};
b = new int[] {x,y};
for (int r = 0; r < 9; r++) {
if(a[1]+1 < 10 && b[1]+1 < 10 && map[a[0]][a[1]+1]==0 && map[b[0]][b[1]+1]==0) {
a[1]++;
b[1]++;
}
}
map[a[0]][a[1]]=num;
map[b[0]][b[1]]=num;
break;
}
for (int r = 0; r < 9; r++) {
}
}
public static void moveDown(int t, int x, int y, int num) {
int[] a;
int[] b;
switch (t) {
case 1:
a = new int[] {x,y};
for (int r = 0; r < 9; r++) {
if(a[0]+1 < 10 && map[a[0]+1][a[1]]==0) {
a[0]++;
}
}
map[a[0]][a[1]]=num;
break;
case 2:
a = new int[] {x,y};
b = new int[] {x,y+1};
for (int r = 0; r < 9; r++) {
if(a[0]+1 < 10 && b[0]+1 < 10 && map[a[0]+1][a[1]]==0 && map[b[0]+1][b[1]]==0) {
a[0]++;
b[0]++;
}
}
map[a[0]][a[1]]=num;
map[b[0]][b[1]]=num;
break;
case 3:
a = new int[] {x+1,y};
b = new int[] {x,y};
for (int r = 0; r < 9; r++) {
if(a[0]+1 < 10 && b[0]+1 < 10 && map[a[0]+1][a[1]]==0 && map[b[0]+1][b[1]]==0) {
a[0]++;
b[0]++;
}
}
map[a[0]][a[1]]=num;
map[b[0]][b[1]]=num;
break;
}
}
// 제거(점수x) 후 모든 조각 일괄 이동
public static void moveRightSync(int cnt) {
for (int r = 0; r < cnt; r++) {
for (int i = 1; i < 10; i++) {
for (int j = 0; j < 4; j++) {
map[j][9-i+1] = map[j][9-i];
map[j][9-i] = 0;
}
}
}
}
public static void moveDownSync(int cnt) {
for (int r = 0; r < cnt; r++) {
for (int i = 1; i < 10; i++) {
for (int j = 0; j < 4; j++) {
map[9-i+1][j] = map[9-i][j];
map[9-i][j] = 0;
}
}
}
}
// 제거(점수o) 후 모든 덩어리별로 이동
public static void moveRightAll() {
for (int r = 0; r < 9; r++) {
for (int i = 1; i < 10; i++) {
for (int j = 0; j < 4; j++) {
// 블럭이 있으며
if(map[j][9-i]>0) {
// 덩어리인 경우
if(j<3 && map[j][9-i] == map[j+1][9-i]) {
// 오른칸이 비었고
if(map[j][9-i+1] == 0) {
// 함께 right갈 수 있을 때만 내려가기
if(map[j][9-i+1] == 0 && map[j+1][9-i+1] == 0) {
map[j][9-i+1] = map[j][9-i];
map[j][9-i] = 0;
}
else {
j++;
}
}
else {
j++;
}
}
// 덩어리가 아닌 경우 or 덩어리 체크 한 밑에칸 오른쪽갈수있을 때
else if(map[j][9-i+1] == 0){
map[j][9-i+1] = map[j][9-i];
map[j][9-i] = 0;
}
}
}
}
}
}
public static void moveDownAll() {
for (int r = 0; r < 9; r++) {
for (int i = 1; i < 10; i++) {
for (int j = 0; j < 4; j++) {
// 블럭이 있으며
if(map[9-i][j]>0) {
// 덩어리인 경우
if(j<3 && map[9-i][j] == map[9-i][j+1]) {
// 아래칸이 비었고
if(map[9-i+1][j] == 0) {
// 함께 down갈 수 있을 때만 내려가기
if(map[9-i+1][j] == 0 && map[9-i+1][j+1] == 0) {
map[9-i+1][j] = map[9-i][j];
map[9-i][j] = 0;
}
else {
j++;
}
}
else {
j++;
}
}
// 덩어리가 아닌 경우 or 덩어리 체크 한 밑에칸
else if(map[9-i+1][j] == 0){
map[9-i+1][j] = map[9-i][j];
map[9-i][j] = 0;
}
}
}
}
}
}
// 점수체크
public static boolean checkRight() {
boolean erased = false;
for (int i = 0; i < 4; i++) {
int cnt = 0;
for (int j = 0; j < 4; j++) {
if(map[j][6+i]>0) {
cnt ++;
}
}
if(cnt==4) {
score++;
erased = true;
for (int j = 0; j < 4; j++) {
map[j][6+i]=0;
}
}
}
return erased;
}
public static boolean checkDown() {
boolean erased = false;
for (int i = 0; i < 4; i++) {
int cnt = 0;
for (int j = 0; j < 4; j++) {
if(map[6+i][j]>0) {
cnt ++;
}
}
if(cnt==4) {
score++;
erased = true;
for (int j = 0; j < 4; j++) {
map[6+i][j]=0;
}
}
}
return erased;
}
// 애매한 영역 체크
public static int cntRight() {
int cnt = 0;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 4; j++) {
if(map[j][4+i]>0) {
cnt++;
break;
}
}
}
return cnt;
}
public static int cntDown() {
int cnt = 0;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 4; j++) {
if(map[4+i][j]>0) {
cnt++;
break;
}
}
}
return cnt;
}
public static void main(String[] args) {
for (int i = 4; i < 10; i++) {
for (int j = 4; j < 10; j++) {
map[i][j] = -1;
}
}
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int t=0;
int x=0;
int y=0;
score = 0;
int count = 0;
for (int i = 1; i <= N; i++) {
t= sc.nextInt();
x= sc.nextInt();
y= sc.nextInt();
// 설치 후 가로이동
moveRight(t,x,y,i);
// 설치 후 세로이동
moveDown(t,x,y,i);
// 가로이동 점수 체크 후 모두이동
while(checkRight()) {
moveRightAll();
}
// 세로이동 점수 체크
while(checkDown()) {
moveDownAll();
}
// 애매한 영역체크
moveRightSync(cntRight());
moveDownSync(cntDown());
}
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if(map[i][j]>0) {
count++;
}
}
}
System.out.println(score);
System.out.println(count);
// 초기화
score = 0;
}
}
아쉬운 점
- index 오류
- 가로로 이동하는것과 세로로 이동하는 것 arr[i][j] 를 arr[j][i]로 바꾸면 되긴하는데 은근 복잡했음.
- 문제 이해 잘못함
- 1x2 , 2x1 같은경우는 라인 제거해도 그대로 떨어져야함 1x1로 떨어지는게 아니라
- 덩어리 체크 구현
- if - else 흐름 꼼꼼히 체크 못했었음.
- 이 문제같은 경우 덩어리를 체크할 테스트케이스가 없어서 테케를 찾는데 많이 힘들었다.
- 실제로 이렇게 나오면 디버깅하기 어려웠을 듯
잘한 점
-
덩어리 고려하는 것을 제외하면 시키는대로 구현은 제대로 했었음.
-
덩어리 체크
- 덩어리 체크를 위해 블록을 {1|0}이 아닌 {n|0}으로 구분하였음.
- 덩어리 체크를 할 때는 0,1,2,3 에서 0,1,2 칸만 오른쪽 칸을 고려하였음. 테트리스였다면 훨씬 복잡했을 것.
-
시간은 map의 크기도 작았기 때문에 크게 고려하진 않았음
- {N:10000}*[{move:4*10*2*10} + {lineclear: 4*10*2*10} + {delete : 4*10*2*10}]
- 대강 10^7~ 10^8 쯤 나오는 것 같다.
-
간만의 포스팅. 8월 1일에 포스팅 올리고 싶었지만 아무튼 8월 1일에 시작하긴함. 8월의 나는 다르다.
'알고리즘 > Simulation' 카테고리의 다른 글
Baekjoon[17140] - 이차원 배열과 연산 (0) | 2020.08.31 |
---|---|
Baekjoon[15685] - 드래곤 커브 (1) | 2020.08.30 |
Baekjoon[5373] - 큐빙 (3) | 2020.03.02 |
Baekjoon[16235] - 나무 재테크 (0) | 2020.03.02 |
Baekjoon[17406] - 배열 돌리기 4 (0) | 2020.02.26 |
Comments