본문 바로가기

TIL

[TIL-85~86] 위코드 사전스터디 2주차 : 로또 번호 만들기

로또 번호 만들기

<조건>

 

  • 랜덤숫자 만들어, 배열에 추가하기
    • for문을 이용해 6번 반복
      let numbers = [];
      function addNumber() {
        const num = Math.ceil(Math.random() * 45);
        if (num > 0) {
          numbers.push(num);
        }
        // else {}, 0이 나올 경우 다시 숫자를 만들어야 하는데 어떻게 해야 할지 모르겠음
      }
      for (let i = 0; i < 6; i++) {
        addNumber();
      }
      console.log(numbers);
      • 문제 : 랜덤숫자가 0이 나올 경우 배열에 추가하지 않도록 함. 그래서 고정적으로 6번을 반복하게 할 경우, 랜덤숫자로 0이 나온 경우의 수만큼 숫자가 부족하게 됨.
      • [1/30] 해결 : 아래 "랜덤숫자의 생성과 범위" 참고.
    • while문을 이용해 배열에 숫자가 6번 추가될 때까지 반복
      let numbers = [];
      function addNumber() {
        const num = Math.ceil(Math.random() * 45);
        if (num > 0) {
          numbers.push(num);
        }
      }
      let i = numbers.length;
      while (i < 6) {
        addNumber();
        i = numbers.length;
      }
      // while문을 이용해서 배열의 길이가 6이 될 때까지(숫자가 6개 찰 때까지) 숫자를 추가해줌.
      console.log(numbers);
    • for문 응용해서 위 while문 구현
      let numbers = [];
      function addNumber() {
        const num = Math.ceil(Math.random() * 45);
        if (num > 0) {
          numbers.push(num);
        }
      }
      for (let i = numbers.length; i < 6; i = numbers.length) {
        addNumber();
      }
      console.log(numbers);​
      • while문 보다 짧고 간결함.

 

  • 중복 걸러내기
    let numbers = [];
    
    function makeNumber() {
      const randomNum = Math.ceil(Math.random() * 45);
      if (randomNum > 0) {
        return randomNum;
      }
    }
    // 1~45의 숫자를 만드는 함수. 0이 만들어질 경우 값을 리턴하지 않는다.
    
    function addNumber() {
      for (let i = numbers.length; i < 6; i = numbers.length) {
        let num = makeNumber();
        for (let i = 0; i < numbers.length; i++) {
          if (num === numbers[i]) {
            console.log("중복 발생 " + num);
            num = makeNumber();
            console.log("새로운 숫자 생성" + num);
            i = 0;
            // 중복 확인할 숫자가 새로 생성되었으므로 배열의 첫번째 요소부터 확인하기 위해 i를 0으로 바꿈.
          }
        }
        numbers.push(num);
      }
    }
    
    addNumber();
    
    console.log(numbers);​
    • 랜덤숫자를 생성하는 makeNumber 함수와, 랜덤숫자를 기존 배열의 요소들과 비교하여 중복되지 않을 때 배열에 추가하는 addNumber 함수로 나눔.
    • makeNumber : 0~45 사이의 숫자를 랜덤으로 생성 후 0이 아닐 때만 값을 리턴함.
    • addNumber : makeNumber() 함수로 랜덤숫자 생성. for문 안의 for문에서 랜덤숫자가 배열의 모든 요소와 비교하여 값이 같은 경우(중복 발생) 새로운 랜덤숫자를 생성함.
    • 확인 결과
      • 두번째 숫자가 첫번째 숫자인 7로 중복되어 44로 대체됨. 그리고 6번째 숫자가 다시 세번째 숫자인 16으로 중복되어 42로 대체됨.

 

  • 랜덤숫자의 생성과 범위
    • Math.random() : 난수 생성 함수. 0~1 사이의 실수를 랜덤으로 생성함. 보통 응용하여 원하는 범위만큼 곱해서 사용.
      • 예) Math.random() * 10 : 0~10 사이의 난수가 생성됨.
    • Math.ceil(), Math.floor(), Math.round() : 받은 숫자를 올림/내림/반올림 함.
    • Math.floor(Math.random() * 45)
      • 0~45 사이의 난수가 생성되면 내림하므로 0~0.9999는 0, 1~1.99999는 1이 되는 방식으로 44~44.9999는 44가 되고, 45일 때(Math.random()의 결과가 1일 때)만 45가 나옴.
      • 문제 : 제시된 조건에서 1~45가 랜덤번호의 범위. 0이 나오면 안 됨.
      • 해결 1) Math.floor(Math.random() * 44) + 1 : 0~44 사이의 정수가 생성된 뒤 1이 더해져, 결과적으로 1~45 사이의 정수가 나옴. 하지만 45가 나올 경우는 오직 Math.random()의 결과가 1일 때만이기 때문에 사실상 로또번호로 45가 나오기 힘듦.
        • [1/30] 잘못 알고 있어서 괜히 고생함. 좀 찾아볼 걸;; 알고 보니 Math.random()의 값은 0.0000부터 0.99999까지로, 1이 포함되지 않음. 따라서 그냥 Math.floor(Math.random() * 45) + 1 하면 됨.
      • 해결 2) 0이 나온 경우를 체크하여 로또번호(배열)에 저장하지 않음. 이 경우, 6번으로 정해두고 for문을 돌리면 로또 추첨 결과가 5개 숫자로 끝나는 오류가 날 수 있음. for문의 i(카운터변수)가 반복할 실행문 종료 후 배열의 길이(저장된 로또번호의 수)가 되도록 함. 즉, 증감식에 i++이 아니라 i=numbers.length를 씀.