상세 컨텐츠

본문 제목

GUI 로또번호발생기 이번주 예상 번호는...?

자바스크립트

by e7e 2023. 7. 5. 17:58

본문

랜덤 로또번호 6개 만들깅은 요즘 프로그램을 배우는 사람들은

거의 피할 수 없이 지나가야 하는 재미난 통과의례이당.

 

 랜덤은 더미데이터 맹글기에 도움이 되어 전체적인 프로그램을 재밌게 보이도록 도와주공,

각기 다른 6개 번호를 골라야 하는 중복제거 로직은 지금은 체크 메소드가 다 준비되어 있어

시시하지만, 사실 초급자에겐 꼭 한번 생각해보면 좋은 알고리즘 과제이당.

 

단순히 화면에 번호만 찍히는 건 넘 재미없으닝, CSS와 타이머를 쪼메 섞어서,

로또복권 사고싶겡 쪼메나마 재밌게 만들어 보장.

 

일부러 기럭지가 기러지더라도 가독성 선택을 위해 CSS를 길게 펼쳐놓았으니

소스 이해는 크게 어렵지 않을거지만, 전역변수를 

window[`lotoNum${i}`] 식으로 사용한 부분과, 타이머 사용부분에 주목해서 보도록 하장.

특히 타이머는 많이 섞어서 사용할 수록 머리속이 입체화 되어 로직훈련에 아주좋당.

 

아래 소스는 랜덤 로또 번호가 단순히 쪼메 뻣뻣하게 하늘에서 떨어지는 소스당.

simpleLottto.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>로또번호 발생기!</title>
    <style>
        * {
            margin: 0;
            border: 0;
            padding: 0
        }

        #wrapper {
            margin: 10px auto;
            position: relative;
            border: 1px solid blue;
            width: 500px;
            height: 500px;
        }

        #btn1 {
            position: absolute;
            color: blue;
            font-size: 2em;
            width: 400px;
            height: 50px;
            left: 40px;
            bottom: 20px;
        }

        .num {
            position: absolute;
            top: 100px;
            font-size: 2.5em;
            line-height: 60px;
            text-align: center;
            border: 1px solid black;
            border-radius: 50%;
            width: 60px;
            height: 60px;
            color: gold;
            background-color: black
        }

        /* 그냥 스크립트로 할깡? 고민하다 가독성을 위한 초기화 선택 */
        .num1 {
            left: 35px;
        }

        .num2 {
            left: 105px;
        }

        .num3 {
            left: 175px;
        }

        .num4 {
            left: 245px;
        }

        .num5 {
            left: 315px;
        }

        .num6 {
            left: 385px;
        }
        
        #backImg {
            opacity: 0.3;
        }
    </style>
</head>
<body>
    <div id="wrapper">
        <div id="backImg">
            <img src="https://cdn.news.eugenes.co.kr/news/photo/201704/2830_5671_4357.jpg">
        </div>
        <div id="num1" class="num num1">?</div>
        <div id="num2" class="num num2">?</div>
        <div id="num3" class="num num3">?</div>
        <div id="num4" class="num num4">?</div>
        <div id="num5" class="num num5">?</div>
        <div id="num6" class="num num6">?</div>
        <input id=btn1 type=button value="로또번호발생" onclick="lotto()">
    </div>
    <script>
        // 로또번호는 6개
        const lottoCnt = 6;
        // 랜덤 함수 1~N까지 발생
        function myRandom(N) {
            return Math.ceil(Math.random() * N);  
        }

        // 16진수 랜덤 색깔 코드 맹글깅
        const hexaChar = '0123456789ABCDEF';
        const ranColor = ()=>{
            let sColor ="#";
            for(let i=1; i<=lottoCnt; i++){
                sColor += hexaChar[Math.floor(Math.random()*hexaChar.length)];
            }
            return sColor;
        }

        // 6개 넘버 출력할 DIV 태그(요소)들
        // window객체에 JSON 배열식 접근법을 이용 전역변수 선언

        for(let i=1; i<=lottoCnt; i++){
            window[`lotoNum${i}`] = document.querySelector(`#num${i}`);
        }

        // 로또함수(아 1등 한번 되고팡!)
        function lotto() {            
            // 번호 담는 div top값 초기황
            for (let i = 1; i <=lottoCnt ; i++) {
                let divStr = `lotoNum${i}`;
                if(window[divStr].style.top) window[divStr].style.top = null;  
            }

            //로또 번호(6개) 담을 배열
            let lottoNums = [];
            while (true) {
                if (lottoNums.length == lottoCnt) break;
                let tempNum = myRandom(45);
                if (!lottoNums.includes(tempNum)) {
                    lottoNums.push(tempNum);
                }
            }
            // 정렬(괘니 뒤집깅)
            lottoNums = lottoNums.sort(function(a,b){return b-a;});
            // 번호값 div에 넣고 시간차 두어 부르깅
            for (let i = 0; i < lottoNums.length; i++) {
                let numStr = `#num${i+1}`;
                let divStr = `lotoNum${i+1}`;
                let numDiv = document.querySelector(numStr);
                numDiv.innerHTML = lottoNums[i];  //문자열 트릭!
                numDiv.style.backgroundColor = ranColor();
                numDiv.style.color = ranColor();
                move(window[divStr],1000*i);
            }
        }

        // 번호 떨어지는 움직임 구현
        const underLimit = 200;  // 200px에 멈추겡
        function move(divItem,timeNum) {
            if(!divItem.style.top) divItem.style.top = "-100px"; // 화면 밖
            if(parseInt(divItem.style.top) >= underLimit) return;
            divItem.style.top = parseInt(divItem.style.top) + 5 + "px"; // 5px씩 이동
            setTimeout(move,timeNum,divItem);
        }
    </script>
</body>
</html>

재미로 로또번호발생 버튼을 마구 여러번 눌러보장, 어떤 결과가 보이는강?

 

위 소스의 결과를 보았다면, 음.. 역시 뻣뻣하군 느낌같은 느낌이 왔을거당.

움직임을 조금 부드럽게 하기 위해서 작업한 뽀인토는(실험적 튜닝값이당)

149 라인에 move(window[divStr],5*i); 을 넣었공,

166 라인에 setTimeout(move.bind(null,divItem,timeNum),timeNum); 을 넣었당.

(bind에 특히 주목, call, apply도 생각이 나야 한당)

그리고, fProxy라는 함수를 넣어서, lotto 함수 동작 중일때는 버튼을 눌러도 

lotto 함수를 부르지 않게 맹글었당. proxy 뜻을 사전에서 찾아보장.(중요하당, 자주 듣게될거당)

나머지는 위 소스와 완전 동일하지만, 카.복하는 분들을 위해 소스전체를 붙인당.

 

smoothLotto.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>로또번호 발생기!</title>
    <style>
        * {
            margin: 0;
            border: 0;
            padding: 0
        }

        #wrapper {
            margin: 10px auto;
            position: relative;
            border: 1px solid blue;
            width: 500px;
            height: 500px;
        }

        #btn1 {
            position: absolute;
            color: blue;
            font-size: 2em;
            width: 400px;
            height: 50px;
            left: 40px;
            bottom: 20px;
        }

        .num {
            position: absolute;
            top: 100px;
            font-size: 2.5em;
            line-height: 60px;
            text-align: center;
            border: 1px solid black;
            border-radius: 50%;
            width: 60px;
            height: 60px;
            color: gold;
            background-color: black
        }

        /* 그냥 스크립트로 할깡? 고민하다 가독성을 위한 초기화 선택 */
        .num1 {
            left: 35px;
        }

        .num2 {
            left: 105px;
        }

        .num3 {
            left: 175px;
        }

        .num4 {
            left: 245px;
        }

        .num5 {
            left: 315px;
        }

        .num6 {
            left: 385px;
        }
        #backImg {
            opacity: 0.3;
        }
    </style>
</head>
<body>
    <div id="wrapper">
        <div id="backImg">
            <img src="https://cdn.news.eugenes.co.kr/news/photo/201704/2830_5671_4357.jpg">
        </div>
        <div id="num1" class="num num1">?</div>
        <div id="num2" class="num num2">?</div>
        <div id="num3" class="num num3">?</div>
        <div id="num4" class="num num4">?</div>
        <div id="num5" class="num num5">?</div>
        <div id="num6" class="num num6">?</div>
        <input id=btn1 type=button value="로또번호발생" onclick="fProxy()">
    </div>
    <script>
        //로또 번호는 6갱
        const lottoCnt = 6;
        // 랜덤 함수 1~N까지 발생
        function myRandom(N) {
            return Math.ceil(Math.random() * N);  
        }

        // 16진수 랜덤 색깔 코드 맹글깅
        const hexaChar = '0123456789ABCDEF';
        const ranColor = ()=>{
            let sColor ="#";
            for(let i=1; i<=lottoCnt; i++){
                sColor += hexaChar[Math.floor(Math.random()*hexaChar.length)];
            }
            return sColor;
        }

        // 6개 넘버 출력할 DIV 태그(요소)들
        // window객체에 JSON 배열식 접근법을 이용 전역변수 선언

        for(let i=1; i<=lottoCnt; i++){
            window[`lotoNum${i}`] = document.querySelector(`#num${i}`);
        }

        // 상태(flag) 변수
        let isStart = false; // 로또 함수 안 작동중
        function fProxy(){
            if(!isStart){
                lotto();
                isStart = true;
            }
        }

        // 로또함수(아 1등 한번 되고팡!)
        function lotto() {            
            // 번호 담는 div top값 초기황
            for (let i = 1; i <=lottoCnt ; i++) {
                let divStr = `lotoNum${i}`;
                if(window[divStr].style.top) window[divStr].style.top = null;  
            }

            //로또 번호(6개) 담을 배열
            let lottoNums = [];
            while (true) {
                if (lottoNums.length == lottoCnt) break;
                let tempNum = myRandom(45);
                if (!lottoNums.includes(tempNum)) {
                    lottoNums.push(tempNum);
                }
            }
            // 정렬(괘니 뒤집깅)
            lottoNums = lottoNums.sort(function(a,b){return b-a;});
            // 번호값 div에 넣고 시간차 두어 부르깅
            for (let i = 0; i < lottoNums.length; i++) {
                let numStr = `#num${i+1}`;
                let divStr = `lotoNum${i+1}`;
                let numDiv = document.querySelector(numStr);
                numDiv.innerHTML = lottoNums[i];  //문자열 트릭!
                numDiv.style.backgroundColor = ranColor();
                numDiv.style.color = ranColor();
                //움직임 부드럽게 튜닝!
                move(window[divStr],5*i);
            }
        }

        // 번호 떨어지는 움직임 구현
        const underLimit = 200;  // 200px에 멈추겡
        function move(divItem,timeNum) {
            if(!divItem.style.top) divItem.style.top = "-100px"; // 화면 밖
            if(parseInt(divItem.style.top) >= underLimit) {
                // 6번째꺼이 끝나면 진짜 끝난 거임
                if(divItem.getAttribute("id")=="num6"){
                    isStart = false;  // 다시 버튼 누를수 있겡!
                }
                return;
            }
            divItem.style.top = parseInt(divItem.style.top) + 5 + "px"; // 5px씩 이동
            // bind를 이용해서 개별 divItem timeNum값 조절
            setTimeout(move.bind(null,divItem,timeNum),timeNum);
        }

        // setInterval(lotto,3000);  테스트용 자동반복
    </script>
</body>

</html>

항상 결과만 확인하는 사람은 나쁜사람이당. 코드를 추가/수정/실험을 통해 실력을 키우장

 

사실 그동안 로또복권 사는데 들인 돈이 적지않당.

최고는 4등 5만원 다시 복권10장으로 바꾸면 이상하게 모두 꽝이난당.

그래도 운이란 놈은 돌고 도는 것이니, 계속 사본당

로또번호 조작설에도 귀 기울여본당. 나만 이렇게 안되는 걸깡?

생각해보면 가끔 5등은 여러번 되었당. 필요없당!! 회계상 결국 적자당.

오늘 이 프로그램이 알려 준 번호로 또 사볼 생각이당. 인생 한방 기쁨도 필요하당.

역시 난 하찮은 인간인가 보당.~~ 하찮은 행복을 기대해 본당.

만약 1등이 된다면 그 뒤에도 로또 널 사랑할 수 있을깡? 

 

 

https://www.youtube.com/watch?v=AbkLAcFvj58 

 

관련글 더보기