코드굽는 타자기

Baekjoon[19235] - 모노미노도미노 본문

알고리즘/Simulation

Baekjoon[19235] - 모노미노도미노

bright-jun 2020. 8. 2. 00:44

링크

 

 

19235번: 모노미노도미노

모노미노도미노는 아래와 같이 생긴 보드에서 진행되는 게임이다. 보드는 빨간색 보드, 파란색 보드, 초록색 보드가 그림과 같이 붙어있는 형태이다. 게임에서 사용하는 좌표 (x, y)에서 x는 행,

www.acmicpc.net

문제설명

  • 테트리스 시뮬레이션

문제풀이

  • 테트리스와는 조금 다른게 덩어리 기준으로 내려갈 수 있다. 덩어리끼리 접착제 붙여놓지 않았다고 생각하면 편함.
  • 덩어리 체크를 해야함.

문제코드

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