• 중간 복습(Review)

    2021. 5. 6.

    by. 와트

    객체를 나가기 전에 기존 내용들을 복습하는 문제를 풀었다.

    하나하나 풀어갈 때는 고개를 끄덕거리며 따라갔는데 막상 문제를 풀려고 하면 왜 이렇게 처음부터 턱 막히는지 모르겠다... 복습에만 이틀이 소요되다니

    그래도 이것저것 구글링해가며 직접 문제를 풀어서 조금 뿌듯하다. 물론 선생님 답안은 달랐지만... 그게 더 깔끔했지만...

     

    ※문제. 빙고 게임

    사용자로부터 빙고판의 크기를 입력 받아 지정된 수의 가로*세로 빙고판에 1부터 가로*세로 값까지의 수를 랜덤하게 발생시켜 빙고판을 만드시오. (다만, 중복되는 수는 없어야 하며, 숫자를 선택하면 해당 칸이 0으로 바뀌고 모든 칸의 값이 0이 되면 프로그램을 종료하시오.)

    1) Scanner를 통해 값을 입력받아 해당 값만큼의 2차원 배열을 생성하고

    2) 해당 배열의 인덱스에 랜덤 값을 넣은 후

    3) Scanner로 한 번 더 값을 받아 해당 값을 가진 행렬의 값을 0으로 변환하고

    4) 모든 인덱스의 값이 0이 되면 종료 선언하기.

    더보기
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
        public void method1() {
            
            Scanner sc = new Scanner(System.in);
            System.out.print("빙고판 크기 지정: ");
            int num = sc.nextInt();
            int[][] arr = new int[num][num];
            
            List<Integer> data = IntStream.rangeClosed(1, num * num).boxed().collect(Collectors.toList());
            Collections.shuffle(data);
            Iterator<Integer> iter = data.iterator();
            for (int i = 0; i < arr.length; i++) {
                for (int j = 0; j < arr[i].length; j++) {
                    arr[i][j] = iter.next();
                }
            }
            System.out.println("======= 빙고 게임 시작 =======");
            
            while(true) {
     
            for(int i = 0; i< arr.length; i++) {
                for(int j = 0; j < arr[i].length; j++) {
                    System.out.print(arr[i][j] + "\t");
     
                }
            System.out.println();
            }
            System.out.print("번호 입력: ");
            int num2 = sc.nextInt();
            for(int k = 0; k < arr.length; k++) {
                for(int l = 0; l < arr[k].length; l++) {
                    if(arr[k][l] == num2) {
                        arr[k][l] = 0;
                    }
                }    
            }
            int sum = 0;
            for(int i = 0; i < arr.length; i++) {
                for(int j = 0; j <arr[i].length; j++) {
                    sum += arr[i][j];
                }
            }
            if(sum == 0) {
                System.out.println("게임을 종료합니다");
                break;
            }
            }        
        }
    cs

    배운 내용대로라면 분명 Math.random()을 써야 하는데 이 메소드는 0~1 사이의 랜덤한 수를 불러오는 것으로 알고 있어서 아예 사용 선상에서 제외했다.(그러지 말았어야 했는데)

    도저히 내가 배운 내용으로는 답이 안나와서 구글링을 하는데, '2차원 배열 랜덤'이라고 아무리 쳐도 내가 원하는 답이 안나왔다.

    나중에 '2 dimensional array random'이라고 치니 내가 원하는 답이 딱 나왔다.

    이래서 다들 스택오버플로우를 찬양하는구나 싶었음

    stackoverflow.com/questions/36610226/how-to-fill-a-2d-array-with-random-non-duplicate-numbers-in-java

     

    How to fill a 2D array with random non duplicate numbers in Java

    I'm having a hard time figuring out how to fill my 2D array with random numbers without duplicates. I currently have it filed with random numbers within the correct range, but I just cant think of a

    stackoverflow.com

    암튼 해당 링크를 통해 셔플 함수에 대해 알게 되어 이 메소드를 사용했다.

    범위를 지정해서 범위 내의 정수를 셔플하고, 이 수를 각각 배열 인덱스에 넣어주는 것.

    셔플만 한 거라서 중복이 나올 일이 없다.

    모든 값이 0인 것은 배열의 인덱스를 모두 더했을 때 0이 나오느냐로 if문을 사용해서 만들었다.

    시간은 오래 걸렸지만 구글링과 배워온 것들로 직접 문제를 풀어봤다는 사실이 굉장히 뿌듯했다:)

    답안은 아래에.

    더보기
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
        public void answer1() {
            Scanner sc = new Scanner(System.in);
            System.out.print("빙고판 크기 지정: ");
            int len = sc.nextInt();
            
            //일차원 배열로 중복 값 제거한 후 이차원 배열 대입
            int[] temArr = new int[len*len];
            
            //랜덤 값 대입 후 중복 비교
            for(int i = 0; i < temArr.length; i++) {
                temArr[i] = (int)(Math.random()*(len*len)) + 1;
                //중복 값 발생하면 i--
                //i+1로 진행하지 않고 i에 랜덤 값 대입 후 중복 비교
                for(int j = 0; j < i; j++) {
                    if(temArr[i] == temArr[j]) {
                        i--;
                        break;
                    }
                }
            }
            
            //중복 값 제거가 잘 되어 있는지 출력해 확인
            System.out.println(Arrays.toString(temArr));
            
            //일차원 배열을 이차원 배열로 옮기기
            int[][] arr = new int[len][len];
            int index = 0;
            for(int i = 0; i <len; i++) {
                for(int j = 0; j <len; j++) {
                    arr[i][j] = temArr[index++];
                }
            }
            
            System.out.println("======= 빙고 게임 시작 =======");
            
            //빙고판 출력
            for(int i = 0; i < arr.length; i++) {
                for(int j =0; j < arr[i].length; j++) {
                    System.out.print(arr[i][j] + "\t");
                }
                System.out.println();
            }
            
            //모든 자리가 0이 될 때까지 무한 반복
            while(true) {
                System.out.print("숫자 선택: ");
                int num = sc.nextInt();
                
                //선택한 숫자를 0으로 바꾼 뒤 출력
                for(int i = 0; i < arr.length; i++) {
                    for(int j = 0; j < arr[i].length; j++) {
                        if(arr[i][j] == num) {
                            arr[i][j] = 0;
                        }
                        System.out.print(arr[i][j] + "\t");
                    }
                    System.out.println();
                }
                
                //게임 종료 조건 확인
                boolean flag = false;
                for(int i = 0; i < arr.length; i++) {
                    for(int j = 0; j < arr[i].length; j++) {
                        if(arr[i][j] != 0)
                            flag = true;
                    }
                    }
                    
                    //모든 칸이 0이면 게임 종료
                    if(flag == false)
                        break;
                }
            System.out.println("빙 고 완 성 !!!");
            System.out.println("======= 빙고 게임 종료 =======");
            }
    cs

    boolean을 사용할 생각을 못했는데 사용하니 정말 코드가 깔끔해지더라...

    일차원 배열을 생성해 먼저 값을 만들고 이차원 배열에 값을 넣으니 직관적으로 보기가 더 편했다.

    Math.random()을 어떻게 쓸 수 있을까 고민했는데 그냥 (int)로 형변환 해주면 되는 거였음을...

    나도 계속 공부하면 더 쉽고 편한 코드를 짤 수 있겠지...?

     

    그리고 여기서 이어진 심화 문제.

    ※문제. 빙고 게임 업그레이드

    빙고 게임 + 3줄이 빙고가 되면(가로, 세로, 대각선 모두 포함) 프로그램을 종료하시오.

    더보기
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
        public void method2() {
            Scanner sc = new Scanner(System.in);
            System.out.print("빙고판 크기 지정: ");
            int len = sc.nextInt();
            
            int[] temArr = new int [len*len];
            for(int i = 0; i < temArr.length; i++) {
                temArr[i] = (int)(Math.random()*(len*len))+1;
            
            for(int j = 0; j < i; j++) {
                if(temArr[i] == temArr[j]) {
                    i--;
                    break;
                }
            }
            }
            
            int [][] arr = new int [len][len];
            int index = 0;
            for(int i = 0; i < arr.length; i++) {
                for(int j = 0; j < arr[i].length; j++) {
                    arr [i][j] = temArr[index++];
                }
            }
            System.out.println("======= 빙고 게임 시작 =======");
            
            for(int i = 0; i <arr.length; i++) {
                for(int j = 0; j <arr[i].length; j++) {
                    System.out.print(arr[i][j] + "\t");
                }
                System.out.println();
            }
            
            while(true) {
                System.out.print("숫자 선택: ");
                int num = sc.nextInt();
                int bingo = 0;
                
                for(int i = 0; i < arr.length; i++) {
                    for(int j = 0; j <arr[i].length; j++) {
                        if(arr[i][j] == num) {
                            arr[i][j] = 0;
                        }
                    System.out.print(arr[i][j] + "\t");
                    }
                    System.out.println();
                }
                
                for(int i = 0; i < arr.length; i++) {
                    int[] newArr = new int[len];
                    for(int j = 0; j < arr.length; j++) {
                    for(int k = 0; k < arr[i].length; k++){
                    newArr[j] = arr[i][k];
                }
                    if(newArr[j] !=0 ) 
                        break;
                }
            }
                for(int i = 0; i < arr.length; i++) {
                    int[] newArr = new int[len];
                    for(int j = 0; j < arr[i].length; j++) {
                    for(int k = 0; k < arr.length; k++){
                    newArr[j] = arr[k][i];
                }
                    if(newArr[j] !=0 ) 
                        break;
                    }
            }
                for(int i = 0; i < arr.length; i++) {
                    int[] newArr = new int[len];
                    for(int j = 0; j < arr.length; j++) {
                    newArr[i] = arr[j][j];
                }
                    if(newArr[i] !=0 )
                        break;
                    }
                
                for(int i = 0; i < arr.length; i++) {
                    int[] newArr = new int[len];
                    for(int j = 0; j < arr.length; j++) {
                        for(int k = arr.length -1; k >= 0; k--){
                    newArr[i] = arr[j][k];
                        }
                    if(newArr[i] !=0 ) 
                        break;
                    }
        }
     
                if(bingo >= 3) {
                    System.out.println("빙 고 완 성 !!!");
                    System.out.println("게임을 종료합니다");
                    break;
                }
            }
        }
    cs

    int bingo = 0;을 만들어서 bingo>=3일 때 break하는 무한 루프를 만들어 보려고 했는데 내가 원하는 대로 돌아가지 않았다

    한 줄이 모두 0이어야 빙고가 되는 거니까 1차원 배열을 임의로 만들어서 2차원 배열의 값을 대입하고, 이 배열의 값이 0이면 빙고카운트가 1씩 증가하는 거로 코드를 짜봤는데 break 없이 계속 게임이 진행되는 사태가 발생...

    그리고 코드 엄청 더럽고 길다...이게 빙고가 되는 경우가

    1) 대각선 왼쪽 위에서 오른쪽 아래

    2) 대각선 오른쪽 위에서 왼쪽 아래

    3) 가로 한줄

    4) 세로 한줄

    총 네 종류라서... 이때마다 계속 일차원 배열을 만들고(배열 안 인덱스 값이 달라지니까) 그걸 이차원 배열과 비교하려니 엄청 복잡해지는 것...

    손코딩도 해보고 계속 건드려봤지만 결국 다 풀지 못했다.

    답안은 아래

    더보기
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
        public void answer2() {
            Scanner sc = new Scanner(System.in);
            System.out.print("빙고판 크기 지정: ");
            int len = sc.nextInt();
     
            int[] temArr = new int[len * len];
            for (int i = 0; i < temArr.length; i++) {
                temArr[i] = (int) (Math.random() * (len * len)) + 1;
                for (int j = 0; j < i; j++) {
                    if (temArr[i] == temArr[j]) {
                        i--;
                        break;
                    }
                }
            }
            int[][] arr = new int[len][len];
            int index = 0;
            for (int i = 0; i < len; i++) {
                for (int j = 0; j < len; j++) {
                    arr[i][j] = temArr[index++];
                }
            }
     
            System.out.println("======= 빙고 게임 시작 =======");
            for (int i = 0; i < arr.length; i++) {
                for (int j = 0; j < arr[i].length; j++) {
                    System.out.print(arr[i][j] + "\t");
                }
                System.out.println();
            }
            while (true) {
                System.out.print("숫자 선택: ");
                int num = sc.nextInt();
     
                for (int i = 0; i < arr.length; i++) {
                    for (int j = 0; j < arr[i].length; j++) {
                        if (arr[i][j] == num) {
                            arr[i][j] = 0;
                        }
                        System.out.print(arr[i][j] + "\t");
                    }
                    System.out.println();
                }
     
                // 3빙고이면 게임 종료
                int bingoCnt = 0;
                int crossCnt1 = 0;
                int crossCnt2 = 0;
     
                for (int i = 0; i < arr.length; i++) {
                    int colCnt = 0;
                    int rowCnt = 0;
                    for (int j = 0; j < arr[i].length; j++) {
                        // 가로
                        if (arr[i][j] == 0) {
                            rowCnt++;
                        }
                        // 세로
                        if (arr[j][i] == 0) {
                            colCnt++;
                        }
                        // 왼쪽에서 오른쪽 아래로 대각선
                        if (i == j && arr[i][j] == 0) {
                            crossCnt1++;
                        }
                        // 오른쪽에서 왼쪽 아래로 대각선
                        if ((i + j) == len - 1 && arr[i][j] == 0) {
                            crossCnt2++;
                        }
                    }
                    // 가로 한 줄이 모두 0이면 빙고
                    if (rowCnt == len) {
                        bingoCnt++;
                    }
                    // 세로 한 줄이 모두 0이면 빙고
                    if (colCnt == len) {
                        bingoCnt++;
                    }
                }
                // 왼쪽에서 오른쪽 아래로 대각선이 모두 0이면 빙고
                if (crossCnt1 == len) {
                    bingoCnt++;
                }
                if (crossCnt2 == len) {
                    bingoCnt++;
                }
                if (bingoCnt == 3) {
                    break;
                }
            }
            System.out.println("빙 고 완 성 !!!");
            System.out.println("======= 빙고 게임 종료 =======");
     
        }
    cs

    변수가 지나치게 많은 것도 좋지 않다고 들어서 계속 간결한 코드를 쓰려고 노력하는데

    답안을 보니 또 너무 변수 생성을 아끼는 것도 도움이 안 되는 것 같다.

    Cnt 변수를 각각 생성해서 네 가지 경우에 따라 카운트를 달리하니 훨씬 간단하고 깔끔한 코드가 나온다.

    지속적으로 복습하고 공부하면서 즉각적으로 써내려가진 못하더라도 이 때 이 메소드를 쓰면 된다, 이 변수를 만들면 된다 떠오르게 되면 좋겠다.

    '혼자 있는 방 > Java' 카테고리의 다른 글

    객체 배열  (1) 2021.05.30
    객체 간 협력  (0) 2021.05.30
    DemensionArray(2차원 배열)  (1) 2021.05.04
    Array(배열)  (0) 2021.05.04
    Repetitive(반복문) 2  (0) 2021.05.02

    댓글

Designed by Nana