public class Lotto {
    public static void main(String[] args) {
        int[] lotto = new int[6];
        for (int i = 0; i < lotto.length; i++) {
            int ranNum = -1;
            boolean isDuplicate;
            do {
                isDuplicate = false;
                ranNum = (int) (Math.random() * 45 + 1);
                for (int j = 0; j < i; j++) {
                    if (ranNum == lotto[j]) {
                        isDuplicate = true;
                        break;
                    }
                }
            } while (isDuplicate);
            lotto[i] = ranNum;
        }
        for (int n : lotto) {
            System.out.print(n + "\t");
        }
    }
}


자바 기초공부 하면서 작성해본 로또 번호 생성 메서드입니다. 이제 갓 배우기 시작한 초보이니 고수님들 코드 보시고 지적할 부분 있다면 지적해주세요.



제가 위 구문에서 배열에 번호를 넣은 이유는 나중에 사용자 입력 번호를 받아서 배열과 비교해 당첨 여부를 확인해주기 위함이었는데, starbros님께서 댓글로 적어주신 코드가 중복 검사에서 더 효율적으로 보이길래 starbros님의 방법을 활용하면서 당첨 번호를 배열에 따로 넣도록 코드를 새로 작성해봤습니다. 중복 여부 검사는 int형 배열이 0으로 초기화 된다는 점을 활용하니 확실히 편하네요.

public class Lotto {
    public static void main(String[] args) {
        int count = 0;
        int[] numbers = new int[45];
        int[] lotto = new int[6];
        while (count < lotto.length) {
            int ranNum = (int) (Math.random() * 45);
            if (numbers[ranNum] == 0) {
                numbers[ranNum] = 1;
                lotto[count] = ranNum + 1;
                count++;
            }
        }
        for (int n : lotto) {
            System.out.print(n + "\t");
        }
    }
}
신고

Tag : , ,

  1. 2011.02.12 22:41

    비밀댓글입니다

    • BlogIcon snpbox
      2011.02.12 22:44 신고
      수정 및 삭제

      요즘은 회사다닌다고 바빠서 주말에만 블로그 하고 있습니다. 그래서 질문에는 전혀 답변하지 않고 있구요.

      말씀하신대로 자식을 부모에 병합한 다음 클린 자식으로 교체하면 됩니다. 하지만 저는 자식을 병합하는 방법보다 부모로 부팅해서 데몬을 설치한 다음 부모 상태에서 자식 파일을 교체하고, 자식으로 재부팅하는 방법을 선호합니다.

  2. BlogIcon hongyang
    2011.02.12 22:54 신고

    오... 이제 자바 글도 올리시넹. 흑흑 그리고 6번 이미지 시험은 실패했습니다.


  3. 2011.02.12 23:24

    비밀댓글입니다

  4. 추추추
    2011.02.13 00:27 신고

    윈7 익스8버젼에서
    소스보기를 메모장으로 볼수있게 하는 방법 없나요?
    도구-옵션에서 HTML편집기를 메모장으로 바꾸면 된다고하던데..
    그 방법이 안되네요.
    다른 방법 없나요? ㅡㅜ

    • NaVI
      2011.02.13 01:11 신고
      수정 및 삭제

      레지스트리 편집기로 아래 경로에 있는 편집기 프로그램 경로를 변경하면 됩니다.
      HKEY_CURRENT_USER/Software/Microsoft/Internet Explorer/View Source Editor/Editor Name
      특수문자가 제대로 표현이 안되는 군요...
      슬래시가 아니고 엔터키 위에 있는 역슬래쉬 입니다. 감안해서 보세요.

  5. 추추추
    2011.02.13 01:29 신고

    해봤는데, 안되네요.
    레지 경로도 마지막에 약간 다르네요.(윈7 익스8버젼 차인가?)
    HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Default HTML Editor 가보면,
    익스플로러 도구에서 메모장으로 바꿔놔서 그런지 레지스트리도 메모장으로 되어있는데,
    정작 소스보기하면 메모장으로 연결이 안되네요.

  6. BlogIcon 고길동,
    2011.02.13 02:19 신고

    학기때 과제로 로또 번호 생성 해본적이 있었는데, 역시 코드 볼때마다 느끼는점은

    한가지 결과를 내기위해서 다양한 방법이 있다는것을 볼 수 있는 것 같습니다.

    잘 봤습니다 ㅎ

    • BlogIcon snpbox
      2011.02.13 02:47 신고
      수정 및 삭제

      네 정말 그렇죠. 저는 처음에 이거랑 좀 다르게 했는데 다른 분이 boolean을 이용하길래 저도 약간 수정해본 코드였습니다. 코드에는 그 사람의 스타일이 확연히 뭍어나오는 것 같아요. ^^

  7. BlogIcon starbros
    2011.02.13 03:19 신고

    비약적으로 고수 프로그래머가 되어가시는듯하군요 ^^
    조금 쓴 소리를 하자면요. for문안에 do문안에 또다시 For문이 있는 구조는
    반복문이 3중으로 중첩되어서 앞으로 프로그래밍을 하시는데 좋은 습관이 될 수 없구요.
    작성할때마다 생각도 많이 해야하고 예기치않은 오류에 부딪힐 가능성이 많아집니다.

    제생각에 반복문은 꼭 필요한 경우에만 쓰는게 좋구요. 가능하다면 최소한으로 줄여야 겠지요.^^

    로또의 경우 1부터 45까지의 숫자중에서 중복되지 않게 순서에 상관없이 뽑은 공을 바로바로 출력해주면
    되겠지요??
    키포인트만 말씀드리겠습니다.
    int[] lotto = new int[46]; //저는 로또번호를 46개로 하겠습니다. [0]부터... [45]까지

    lotto[0]=1; // 뽑은 공의 횟수를 카운트합니다.
    do {
    ranNum = (int) (Math.random() * 45; //랜덤수는 0부터 44까지만 나오도록 하겠습니다.
    if( lotto[45-ranNum]!=1) { //뽑은 공이 중복아니면
    System.out.printn(45-ranNum); //번호를 보여줍니다.
    lotto[45-ranNum]=1; lotto[0]++; //뽑은 공을 표시하고 횟수를 증가시킵니다.
    }
    } while(lotto[0]<6); //6개의 공을 뽑았다면 관둬야지요^^

    여기까지 입니다. lotto[0]은 단순히 뽑은공의 횟수만 카운터 하는데 사용했지만,
    나중에 프로그래밍할때 [0]번째 주소는 무시하고 [45]와 실제 45라는 공의 숫자와 일치해서 생각하면
    편하기 때문에 개인적인 습관일뿐입니다. 결국은 반복문 한번만으로 구현가능하지요.^^

    • BlogIcon snpbox
      2011.02.13 02:43 신고
      수정 및 삭제

      음... 반복문의 중첩은 안 좋다는 말씀이시군요. 저는 그게 생각하기 편한데 ^^;; 일단 적어주신 코드를 보면서 생각해보겠습니다. 조언해주셔서 감사드려요. ^^

  8. BlogIcon No.190
    2011.02.13 13:01 신고

    두번째 코드는 연속적인 좁은 범위의 값을 랜덤으로 뽑는것에서 효율적인데요. 사이값이 엄청나게 커지게 되면 메모리 낭비로 이어지게 됩니다.
    나중에 시간이 되시면 랜덤값을 그동안 로또 당첨 번호의 평균치를 통해서 구해보시면 재미있으실겁니다.
    오류역전파 알고리즘을 살짝 보시면 금방 만드실수 있으실겁니다.(문제는 나온놈만 나올수도 있지만요;ㅎ)

  9. BlogIcon bookworm
    2011.02.13 14:57 신고

    글을 보고 흥미를 느껴 펄로 한 번 만들어 봤습니다. 펄 초보라 더 이상 버밍은 안 되더군요. ^^;;

    perl -e 'use List::Util "shuffle"; print join " ", sort {$a <=> $b} (shuffle 1..45)[0..5];'

  10. BlogIcon 박문식
    2011.02.13 16:10 신고

    제 블로그이름이 많이 들어갔군요ㅋㅋㅋ

  11. BlogIcon Nvdie
    2011.02.13 20:09 신고

    자바를 배웠지만 진짜 간단한 프로그래밍이라도 못하겠음 ㅠ.ㅜㅎ

  12. BlogIcon starbros
    2011.02.14 23:17 신고

    스눕신님이 프로그래밍도 완전접수하시는 날이 머지않았다 생각되는군요^^


  13. 2011.02.15 13:32 신고

    대부분의 프로그래밍 언어에서 random 함수는 실제로 무작위가 아닙니다.
    일정한 패턴을 가지는 숫자를 뽑아내주죠
    좀더 랜덤한 상황을 이용하려면 타임시드를 이용하는 방법이 있습니다.

  14. BlogIcon starbros
    2011.02.15 22:47 신고

    환님 java에서는 random은 클래스에 해당되며, 그안에 다양한 메소드가 존재합니다.
    Math.random()은 절대로 일정한 패턴을 가질 수 없습니다. 일정한 패턴을 지니게하려면 seed값을 임의로
    고정시켜야하는데 ()안에 seed를 고정으로 지정하여 일정한 패턴을 유지하도록 제한 할 수 있습니다.
    하지만, 기본적으로는 자동시드가 적용되게끔 되어있지요.
    그리고, 자동으로서 시드값을 변경하는 수단으로 시분초 즉 타임값을 이용하기때문에 타임시드라고 하는것이구요. 엄밀히 말하자면 Math.random()은 자동 타임시드를 이용한 불규칙한 난수를 발생하게 되는 것입니다.
    처음숫자와 이후에 나오는 어떠한 숫자도 절대 동일한 시드를 가지지 않기에 해당 시드값으로 발생된
    난수또한 일정한 패턴을 유지할 수 없는 것이죠.
    java 클래스는 다 공개되어 있으니 시간나시면 random클래스부터 분석해보시기 바랍니다. q:^)


  15. 2011.02.16 15:36 신고

    starbros님 // 지금 다시 확인해보니 Java에서는 System.currentTimeMillis()를 기본 시드로 잡아주는군요 -0-ㅋ
    잘못된 정보를 남긴것 죄송합니다. ㅡㅜ

    • BlogIcon starbros
      2011.02.16 16:26 신고
      수정 및 삭제

      죄송할것까지야..
      타임시드개념까지 이해하고 계신분을 만나뵙기는 드문데
      영광입니다. q:^)

  16. BlogIcon TendoZinZzA
    2011.02.19 17:26 신고

    어머.. 로또번호 생성이라니.. ㄷㄷㄷㄷ

  17. spectator
    2011.03.03 14:07 신고

    종종 들렀다가는 과객입니다. 제딴에 프로그래머라고 이런 거를 보면 지나치질 못하네요.
    최적화된 코드가 아닐지는 모르겠지만 제딴에 아이디어가 생각나서 적어봅니다.
    간단히 설명을 하자면 45개 int배열에 1~45 숫자를 초기화시켜 넣어두고, 숫자를 하나 뽑으면 해당 숫자를 다음 선택 대상에서 빼기 위해 배열의 마지막 숫자를 선택된 숫자 자리로 옮긴 다음, 랜덤대상 갯수를 하나씩 줄여가는 식입니다.
    마치 실제 로또에서 첨에 45개의 공으로 시작해서 공이 하나 빠질 때마다 남은 공 갯수가 줄어드는 것과 같은 식인거죠.

    int max_num = 45;
    int lotto_count = 6;
    int[] lotto = new int[lotto_count]; // 결과가 들어갈 로또숫자배열
    int[] numbers = new int[max_num]; // 랜덤대상 숫자배열
    for(int i=0; i < max_num; i++)
    numbers[i] = i+1; // 1~45를 배열에 채움

    for(int i=0; i < lotto_count; i++) {
    int lotto_index = (int)(Math.random() * max_num);
    lotto[i] = numbers[lotto_index];
    max_num --; // 랜덤대상 갯수를 줄여준다. 배열의 마지막 인덱스가 어차피 max_num-1 이므로 미리 처리
    if( lotto_index != max_num ) // 배열의 맨끝 숫자라면 어차피 다음 랜덤대상에서 자동으로 빠짐
    numbers[lotto_index] = numbers[max_num]; // 배열의 맨뒤 숫자를 중간에 선택된 숫자로 이동
    }

    for(int i=0; i < lotto_count; i++)
    System.out.print(lotto[i] + " ");

  18. 루이보스
    2012.10.27 14:29 신고

    import java.util.Iterator;
    import java.util.TreeSet;

    public class LottoTreeSet
    {
    TreeSet<integer> tree = new TreeSet<integer>(); //Integer 오브젝트를 담는 트리셋 선언

    public void lottoNumber()
    {
    //TreeSet의 사이즈가 6개가 될때까지 반복된다.
    while( tree.size() != 6 )
    {
    //TreeSet에 임의의 숫자를 넣게되는데, TreeSet의 특성상 중복된 숫자는 들어가지 않는다.
    tree.add((int)(Math.random()*45) + 1);
    }

    //TreeSet 자체로는 출력하기 어려우므로, Iterator를 사용해 출력한다.
    //출력을 위한 Integer 오브젝트를 담는 Iterator를 선언
    Iterator<integer> i = tree.iterator();

    while (i.hasNext()) //다음 오브젝트가 존재할 경우에만,
    {
    System.out.println(i.next() + "\t"); //로또 번호 출력
    }
    }

    public static void main(String[] args)
    {
    LottoTreeSet lotteTreeSet = new LottoTreeSet();
    lotteTreeSet.lottoNumber(); //로또 번호 생성 메소드
    }
    }

  19. 횽덕
    2015.10.10 17:52 신고

    저기 ... 로또 물어볼게있어서요.
    (int)(Math.Random() * 45) + 1 이걸로해서 .
    ● 5개 정답이면 => 1등, 상금 1000
    ● 4개 맞추면 => 2등, 상금 500
    ● 3개 맞추면 => 3등, 상금 300
    ● 2개 이하 맞추면 => 다음번에 다시 도전! 뭐 이런식으로 나타내고싶은데 어케해야하나요?.