ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Javascript] 자바스크립트 로또 추첨기
    Javascript 2023. 5. 19. 18:57
    반응형

    6-1. 로또 추첨기 순서도 그리기

    비동기

    • 동기의 반댓말
    • 실제로 코딩한 순서와 다르게 동작하는 코드
    • 위 → 아래, 왼쪽 → 오른쪽으로 실행되는 것이 아니라 작성된 위치와 다른 곳에서 실행되는 코드가 있다면, 비동기를 의심해 볼 수 있다.
    • 대표적인 예로 이벤트 리스, 타이머

     

    순서도 그리기

    1. 시작
    2. 1~45 까지의 숫자를 준비한다
    3. 숫자를 섞는다
    4. 공 7개를 뽑는다. 마지막 공은 보너스 공이 된다
    5. 1초마나 공을 하나씩 화면에 표시한다

    6-2. 공뽑기(피셔 예이츠 셔플)

    피셔 예이츠 셔플

    유한 수열의 무작위 순열을 생성하기 위한 알고리즘

    <script>
            // 1 ~ 45까지의 숫자 뽑기
            const candidate = Array(45).fill().map((v, i) => i + 1);
            // 
            const shuffle = [];
            while (candidate.length > 0) {
                const random = Math.floor(Math.random() * candidate.length); // 무작위로 인덱스 뽑기
                const spliceArray =  candidate.splice(random, 1); // 뽑은 값은 배열에 등록하기
                const value = spliceArray[0]; // 배열에 들어있는 값을 꺼내기
                shuffle.push(value); // shuffle 배열에 넣기
            }
            console.log(shuffle);
      </script>

    🟡 코드 설명

    const spliceArray =  candidate.splice(random, 1); // 뽑은 값은 배열에 등록하기
     splice reutrn 값

    splice로 제외한 값이 리턴값으로 들어있다.

     

    const value = spliceArray[0]; // 배열에 들어있는 값을 꺼내기
    shuffle.push(value); // shuffle 배열에 넣기

    splice의 리턴 값을 꺼내 shuffle 배열에 넣는 코드

     

    🟡 결과

    이 중 앞 6개 + 1개(보너스)를 로또번호로 지정한다

     

    ■ Tip
    while문: 조건이 간단할 때, 정확한 반복 횟수를 모를 때 사용하기 좋다.

    for문: 조건이 복잡할 때, 반복 횟수를 정확히 알고 있을 때, i = i+2와 같은 조건이 사용될 때 유용하다.

     

     

    for문으로 바꾸었을 경우

    const candidate = Array(45).fill().map((v, i) => i + 1);
    const shuffle = [];
    for(let i =candidate.length; i > 0; i--) {
                const random = Math.floor(Math.random() * i); // 무작위로 인덱스 뽑기
                const spliceArray =  candidate.splice(random, 1); // 뽑은 값은 배열에 등록하기
                const value = spliceArray[0]; // 배열에 들어있는 값을 꺼내기
                shuffle.push(value); // shuffle 배열에 넣기
            }
            console.log(shuffle);

     

    6-3. 공 정렬하기(sort)

    <script>
        ...
        const winBalls = shuffle.slice(0, 6).sort((a,b) => a - b);
        const bouns = shuffle[6];
        console.log(winBalls, bouns);
    </script>

    🟡 slice

    • arr.slice(3, 5) : 인덱스 3부터 5까지 자르기
    • slice 사용 시, 원본 배열은 변하지 않는다. (=map메소드의 특성)  splice 원본을 수정한다.

    • arr.slice(-5, -1) : 뒤에서 5번째 인덱스부터 뒤에서 첫번째 인데 전까지 자르기

     

    🟡 sort(정렬)

    • 리턴 값에 따라 어떻게 정렬할 지 결정된다.
    • a - b : 오름차순 정렬
    • b - a : 내림차순 정 

    • sort 사용 시, 배열 원본이 수정된다. 
    • 원본을 다시 사용해야 할 일이 많기 때문에, 원본 배열이 수정되는 것이 불편할 수 있다.

     

    🟡 slice + sort (정렬)

    slice 실행 시, 새로 만들어진 배열은 기존 배열과 다른 복사본이다.

    slice() 사용 시 원본 배열이 변하지 않기 때문에 원본 배열을 이용해 다양한 기능을 구현할 수 있다.

     

    🟡 문자열 sort

     

    arr.slice().sort((a, b) => a[0].charCodeAt() - b[0].charCodeAt())	//오름차순 정렬
    arr.slice().sort((a, b) => b[0].charCodeAt() - a[0].charCodeAt())	//내림차순 정렬

    첫번째 글자의 코드 넘버를 비교해서 오름차순, 내림차순 정렬

    첫번째 글자만 비교하기 때문에 첫번째 글자가 동일한 (ex. ['abc', 'acb'])문자열은 변경되지 않는다.

    (사전순으로 정렬되지 않는다.)

    arr.slice().sort((a, b) => a.localeCompare(b))	//오름차순
    arr.slice().sort((a, b) => b.localeCompare(a))	//내림차순

    localeCompare() : 사전 순 정렬 메소드, 한글도 가능

     

     

    6-4. 일정 시간 후 실행하기(setTimeout)

    setTimeout(() => {
    	// 함수 자리
    }, 밀리초)
    • 1초 = 1000밀리초
    • 밀리쵸 부분에 1000을 적어주면, 1초 후 실행

    실행 화면

     

    // 숫자 원 보여주는 것
    const showBall = () => {
    	const $ball = document.createElement("div"); //div태그 만들기
        $ball.className = "ball"; // class 말고 className으로 해야됨
        $ball.textContent = number; // 
        $target.appendChild($ball);
    };
            setTimeout(() => {
                showBall(winBalls[0], $result);
            },1000);
            setTimeout(() => {
                showBall(winBalls[1], $result);
            },2000);
            setTimeout(() => {
                showBall(winBalls[2], $result);
            },3000);
            setTimeout(() => {
                showBall(winBalls[3], $result);
            },4000);
            setTimeout(() => {
                showBall(winBalls[4], $result);
            },5000);
            setTimeout(() => {
                showBall(winBalls[5], $result);
            },6000);
            setTimeout(() => {
                showBall(bouns, $bonus);
            },8000);

    위 코드를 반복문 사용하지 않고 적은 것

     

    정리된 코드

    <script>
        ...
        // 숫자 원 보여주는 것
            const showBall = () => {
                const $ball = document.createElement("div"); //div태그 만들기
                $ball.className = "ball"; // class 말고 className으로 해야됨
                $ball.textContent = number; // 
                $target.appendChild($ball);
            };
    
    
            // [0, 1, 2, 3, 4, 5] -> [1000, 2000, 3000, 4000, 5000, 6000]
            for(let i = 0; i < 6; i++){
                setTimeout(() => {
                    showBall(winBalls[0], $result);
                }, (i + 1) * 1000);  //(i + 1)초 뒤에 추가
            }
            // 마지막은 보너스 볼 보여준다.
            setTimeout(() => {
                showBall(bouns, $bonus);
            },7000); 
    </script>

     

    Tip
    - 자바스크립트의 타이머는 정확하지 않다.
    - setTimeout의 내부 함수가 하나이고 인수가 없는 경우, 다음과 같이 축약해 작성할 수 있다.
    setTimeout(func,3500);​


     

    최종 코드

    <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>로또 추첨기</title>
        <style>
            .ball {
                display: inline-block;
                border:1px solid black;
                border-radius:20px;
                width: 40px;
                height: 40px;
                line-height: 40px;
                font-size: 20px;
                text-align: center;
                margin-right: 20px;
            }
        </style>
    </head>
    <body>
        <div id="result">추첨 결과는? </div>
        <div id="bonus">보너스: </div>
        <script>
            // 1 ~ 45까지의 숫자 뽑기
            const candidate = Array(45).fill().map((v, i) => i + 1);
            
            const shuffle = [];
            while (candidate.length > 0) {
                const random = Math.floor(Math.random() * candidate.length); // 무작위로 인덱스 뽑기
                const spliceArray =  candidate.splice(random, 1); // 뽑은 값은 배열에 등록하기
                const value = spliceArray[0]; // 배열에 들어있는 값을 꺼내기
                shuffle.push(value); // shuffle 배열에 넣기
            }
            console.log(shuffle);
            // 랜덤 된 값을 정리함 
            const winBalls = shuffle.slice(0, 6).sort((a,b) => a - b);
            const bouns = shuffle[6];
            console.log(winBalls, bouns);
    
            const $result = document.querySelector("#result");
            const $bonus = document.querySelector("#bonus");
    
            // 숫자 원 보여주는 것
            const showBall = () => {
                const $ball = document.createElement("div"); //div태그 만들기
                $ball.className = "ball"; // class 말고 className으로 해야됨
                $ball.textContent = number; // 
                $target.appendChild($ball);
            };
            // [0, 1, 2, 3, 4, 5] -> [1000, 2000, 3000, 4000, 5000, 6000]
            for(let i = 0; i < 6; i++){
                setTimeout(() => {
                    showBall(winBalls[0], $result);
                }, (i + 1) * 1000);  //(i + 1)초 뒤에 추가
            }
            // 마지막은 보너스 볼 보여준다.
            setTimeout(() => {
                showBall(bouns, $bonus);
            },7000); 
        </script>
    </body>
    </html>

     

     

     

     

    영상 출처

    https://tinyurl.com/ytnfzjmx

     

    반응형

    댓글

Designed by Tistory.