ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TIL #7 - 로또 프로그램
    프로그래밍/TIL(국비과정) 2020. 4. 2. 19:41

    로또번호 1부터 45를 랜덤하게 6개를 추출해 중복을 가려내고 오름차순으로 정렬하는 프로그램을 만들어본다. 

    LottoNumbers.java

    public class LottoNumbers {
    	private static final int MAX = 45;
    	private static final int SIZE = 6;
    

     상수 2개를 선언해준다. 

    하나는 로또 번호 설정시 사용하는 MAX이고 

    다른 하나는 로또 번호 배열 크기를 위한 SIZE이다. 

     

    다른 블로그를 찾아보니 Math.random이 많이 보였는데 나는 random 객체를 호출한다..

    여기서부터는 main 메소드 안에서 이뤄진다. 

    Random random = new Random();

    그런 후 로또 번호 6개를 담을 배열을 만든다. 

    int[] lottoNumbers = new int[SIZE]; 

    여기서 위에 선언했던 SIZE를 배열의 크기로 넣는다. 

    왜 굳이? 싶지만, Magic Number를 방지하기 위함이라고 한다. 

     

    그런 다음 lottoNumbers 배열의 길이 만큼 랜덤 숫자를 뽑아낸다. 

    	for (int i = 0; i < lottoNumbers.length; i++) {
    			lottoNumbers[i] = random.nextInt(MAX) + 1;
    		}

    여기서 우리는 1부터 45까지의 숫자 중에서의 랜덤 숫자를 원한다. 

    하지만 단독으로 random.nextInt(MAX)를 해버리면 0부터 44까지만 나온다고 한다. 

    그렇기 때문에 +1을 해서 1부터 45가 나오게 만들어준다. 

     

    그런 다음은 for문, forEach 구조를 사용해서 출력한다. 

    우리가 배열 혹은 Collections의 무언가를 쭉 출력할 때 

    몇번째 위치에 있는 무언가를 굳이 지칭해줄 필요는 없다. 

    그냥 쭉 출력하면 되기 때문이다. 

    그럴 때 사용하는것이 아래의 향상된 for문이다. 

    	for (int i : lottoNumbers) {
    			System.out.println(i);
    		}

    여기서의 i의 값은 그냥 임의의 값일 뿐이다. 

    여기서 i = 20; 이라고 선언해도 결과에는 아무런 변화가 없다. 

    바꾸려고 한다면 코드 위의 lottoNumbers를 바꿔줘야한다. 

     

    단, forEach 구조는 2가지 제약이 있다. 

    1. 데이터를 바꾸더라도 원본은 바뀌지 않는다. 

    값만 복사해서 보여주는 용도이기 때문이다. 

    2. 원본이 나온 Collection의 개수가 바뀌면 안된다. 

    이해하기로는,, 고정값이 아니면 출력하기 힘들다는 의미인 것 같다. 

    (후에 내용 추가 하겠습니다)

     

    여기까지하면 1부터 45까지 6개의 랜덤숫자가 나온다. 

    그런데 문제는 중복값이 있을 수 있다는 것이다!

    여기서 중복이라는 의미를 제대로 생각할 필요가 있다. 

    중복이란, 

    1. 인덱스는 다르지만 (즉, 위치는 다르지만)

    2. lottoNumbers[index]의 값이 같을 때이다. 

    다른 위치에 같은 값이 있다면 우리는 그것을 중복이라고 부른다. 

    위치 이야기가 없다면 1번 자리의 3이 곧 1번 자리의 중복이 되는 다시 읽어봐도 말이 안되는 상황이 일어나기 때문이다. 

    컴퓨터는 융통성이 없기 때문에 원하는 바를 제대로 찝어주지 않으면 안되는 것 같다..

     

    		for (int i = 0; i < lottoNumbers.length; i++) {
    			// lottoNumbers[i]는 기준점이 된다.
    			for (int k = 0; k < lottoNumbers.length; k++) {
    				// lottoNumbers[k]는 중복인지 검사할 숫자가 된다.
    				// if문을 달라서 위치가 다르지만 값이 같은 조건을 만들어보자
    				if (lottoNumbers[i] == lottoNumbers[k] && i != k) {
    					System.out.println(i + "와" + k + "가 중복이다.");
    					// 값이 같고, 인덱스가 다르다면 : 중복이다. (위치가 다르고 값이 같은 경우)
    					lottoNumbers[i] = random.nextInt(MAX) + 1; // 새로운 값을 넣어준다.
    					k = -1; // 이 if문이 끝나고 ++되어서 0으로 돌아가 0부터 검사를 시작한다. (따라서 0이면 안됨, 0번째 건너뛰니까)
    				}
    			}
    		}

    역시 배열의 길이만큼 for문을 돌려 하나씩 검사를 해가야한다. 

    문제는 어떤 것과 어떤 것을 검사해서 가려낼 것인가 인데, 

    보면 안에 또 하나의 for문이 있다.

    바깥의 for는 행이고, 안의 for문은 열을 나타낸다고 보면 되는데 

    안의 for문이 lottoNumbers[k]가 직접적으로 중복인지 검사를 하게 될 것이다. 

    바깥의 lottoNumbers[i]는 기준점이다. 

    if문을 보면 바깥의 lottoNumbers[i] 기준점과 안쪽의 lottoNumbers[k]를 비교해 같고 i와 k 즉 위치가 다른 경우를 중복이라고 말하고 있다. 

    이렇게 중복을 찾으면 lottoNumbers[i]에 다시 random을 돌려 새로운 값을 넣어준다. 

    그리고 k를 -1 시켜 if문이 끝난 후에도 0으로 돌아가 다시 검사할 수 있게 한다. 

    +1이 되어 k가 1이 된 상태로 if문을 나가면 0번째 i는 영원히 검사받을 수 없게 되기 때문이다. 

     

    이젠 중복 제거 이후의 숫자들을 출력해본다. 

    System.out.println("==== 중복 제거 후 ==== ");
    		for (int i : lottoNumbers) {
    			System.out.println(i);
    		}
    

     

    이제 중복까지 다 제거한 6개의 랜덤숫자들을 오름차순으로 정렬해본다. 

    배열을 정렬하는 것은 기준 element가 다음 element보다 크다면 자리를 바꿔주면 된다. 

    기준 element는 lottoNumbers[i] 이고 다음 element는 lottoNumbers[i+1] 이 된다. 

    for문은 lottoNumbers.length -1까지 돌린다. 

    아래에서 for문이 돌아가는 것을 보면 이해가 된다. 

    for (int i = 0; i < lottoNumbers.length - 1; i++) {
    			if(lottoNumbers[i] > lottoNumbers[i+1]) {
    				// 앞의 것이 더 크다면 뒤로 보내줘야한다 
    				int temp = lottoNumbers[i]; 
    				// 뒤로 보낼 값을 임시 저장함에 넣고 
    				lottoNumbers[i] = lottoNumbers[i+1];
    				// 앞에 있는 값에 뒤에 있던 값을 넣는다. 
    				lottoNumbers[i+1] = temp;
    				// 이 후 뒤에 있는 값에 저장한 i값이 들어 있는 temp 값을 넣는다. 
    				i = -1;
    		
    			}
    		}

    먼저 앞서 말했듯이 기준점의 i와 기준점 뒤의 i+1 값을 비교해서 i값이 더 크다면 

    i 값을 temp라는 임시 저장함에 넣어둔다. 

    i는 i+1의 자리로 가야하기 때문에 

    lottoNumbers[i] = lottoNumbers[i+1] 을 통해 i+1로 보내준다. 

    그러면 기존에 있던 i+1은 temp에 넣는다. 

    temp에 들어간 i+1은 i 값을 들어가게 된다. 

    그런 후 다시 0부터 차례대로 검사를 해야하기 때문에 아까 중복값을 검사했을 때와 마찬가지로 

    for문으로 인해 +1이 된 i값을 -1해주어 다시 0 인덱스부터 검사할 수 있게 만들어준다. 

     

    아래는 전체적인 코드이다. 

    
    import java.util.Random;
    
    import util.MyArray;
    
    public class LottoNumbers {
    	private static final int MAX = 45; 
    
    	private static final int SIZE = 6;
    
    	public static void main(String[] args) {
    		Random random = new Random();
    
    		int[] lottoNumbers = new int[SIZE]; // 랜덤 숫자 담을 배열
    
    		for (int i = 0; i < lottoNumbers.length; i++) {
    			lottoNumbers[i] = random.nextInt(MAX) + 1; // 그냥 MAX 하면 0부터 44까지 나온다.그래서 +1을 해서 1부터 44까지 나오게
    
    
    		for (int i : lottoNumbers) {
    			// 만약 여기서 i = 20; 이라고 선언해도 바뀌지 않는다.
    			// 그대로 lottoNumbers가 바뀌지 않는한 이 안에서 뭘해도 i값은 바뀌지 않는다.
    
    			System.out.println(i);
    		}
    
    
    		for (int i = 0; i < lottoNumbers.length; i++) {
    			// lottoNumbers[i]는 기준점이 된다.
    			for (int k = 0; k < lottoNumbers.length; k++) {
    				// lottoNumbers[k]는 중복인지 검사할 숫자가 된다.
    				// if문을 달라서 위치가 다르지만 값이 같은 조건을 만들어보자
    				if (lottoNumbers[i] == lottoNumbers[k] && i != k) {
    					System.out.println(i + "와" + k + "가 중복이다.");
    					// 값이 같고, 인덱스가 다르다면 : 중복이다. (위치가 다르고 값이 같은 경우)
    					lottoNumbers[i] = random.nextInt(MAX) + 1; // 새로운 값을 넣어준다.
    					k = -1; // 이 if문이 끝나고 ++되어서 0으로 돌아가 0부터 검사를 시작한다. (따라서 0이면 안됨, 0번째 건너뛰니까)
    				}
    			}
    		}
    		System.out.println("==== 중복 제거 후 ==== ");
    		for (int i : lottoNumbers) {
    			System.out.println(i);
    		}
    
    
    		for (int i = 0; i < lottoNumbers.length - 1; i++) {
    			if(lottoNumbers[i] > lottoNumbers[i+1]) {
    				// 앞의 것이 더 크다면 뒤로 보내줘야한다 
    				int temp = lottoNumbers[i]; 
    				// 뒤로 보낼 값을 임시 저장함에 넣고 
    				lottoNumbers[i] = lottoNumbers[i+1];
    				// 앞에 있는 값에 뒤에 있던 값을 넣는다. 
    				lottoNumbers[i+1] = temp;
    				// 이 후 뒤에 있는 값에 저장한 i값이 들어 있는 temp 값을 넣는다. 
    				i = -1;
    			
    			}
    		}
    		System.out.println("==== 정렬 끝남 ====");
    		for(int i : lottoNumbers) {
    			System.out.println(i);
    			
    			
    			
    		}
    	}
    
    }
    

     

    '프로그래밍 > TIL(국비과정)' 카테고리의 다른 글

    TIL #9 - 필드, 메소드  (0) 2020.04.07
    TIL #8 - 게시판 프로그램  (0) 2020.04.06
    TIL #7 - 각종 출력, 입력, 조회 기능  (0) 2020.04.02
    TIL #6 - 배열 활용 (2)  (0) 2020.04.01
    TIL #6 - 배열 활용 (1)  (0) 2020.04.01

    댓글

Designed by Tistory.