본문 바로가기

Web Development/Front-end

[Zerocho-07] 로또게임 (배열 주요 메소드 & JS에서 HTML제어)

안녕하세요! 지난 시간에는 포스팅이 많이 길어져 조금 힘들었지만 !

결국 틱택토를 완성시켰습니다 !

이번에는 로또 게임을 만들어 보도록해요 !

 

이 게임을 통해 우리는,

배열의 Array, fill, map, sort 등 새로운 메소드들을 만나게 될 것이고,

더 이상 HTML을 Javascript에 작성하지 않는 방법을 알게 될 것 입니다.

 

로또게임이 어떤 게임인지 좀 살펴볼까요?

 

로또게임

로또는 1~45 까지의 숫자중에서, 무작위 숫자 6가지를 뽑아 비교하는 복권게임(?)입니다.

그리고, 보너스볼이라는 개념도 있어서 추가적으로 1개의 숫자를 하나 더 뽑는 게임입니다.

 

 

1. 순서도

 

로또게임 순서도

 

위처럼, 배열을 이용해서 45개의 숫자를 담고, 배열을 섞은 뒤, 무작위로 섞은 배열에서 총 7개의 숫자를 뽑아내는 방식으로 전개됩니다.

 

 

2. 코드분석

HTML파일부터 작성해보도록 하겠습니다. (이젠 번거롭게 JS로 HTML을 안써도 되요 ㅠㅠ!!)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>로또 추첨기</title>
</head>
<body>
    <h3>당첨숫자!</h3>
    <div id='result_blank'></div>
    <button class='result_button'>당첨숫자보기</button>
    <h3>보너스볼!</h3>
    <div class='bonus_blank'></div>
    <button class='result_bonus'>보너스볼보기</button>
    <script src="lotto.js"></script>
</body>
</html>

이런식으로말이죠.

h3태그로 당첨숫자와, 보너스볼 란을 만들어줬구요.

기본볼을 뽑아 결과를 출력할 부분인 div태그를 생성해,  result_blank라는 아이디로 설정해줬습니다.

button을 만들어 버튼을 눌러야 볼을 출력하도록 eventListener적용을 위한 버튼을 만들어줬구요.

마지막에는 lotto.js파일을 임포트해오도록 작성했습니다.

 

이제 JS파일로 넘어가서, 여기에 맞게 코드를 짜줘야하는데 우선, 1~45값을 가진 배열을 작성해줘야합니다.

var balls = Array(45).fill().map(function(item, idx){
    return idx+1;
})
console.log(balls);

이런식으로 말이죠. 처음 떠오른방법은 var balls = [1,2,3,4,5,6,7,8,9,10 ......] 이런식으로 작성하는 것이었는데 이를위해 사용하는 여러 좋은 함수들이 있더라구요.

위에서 사용한 함수는, Array() & fill() & map() 함수입니다.

 

 

Array(몇개의배열을만들까?) => 배열을 생성하는 함수로, 괄호안에 만들 배열의 갯수를 넣어주면, 그 만큼의 empty배열이 생성됩니다.

*여기서 empty배열은 반복문에 적용이 되지않습니다. ㅠㅠ 그래서..

.fill() => fill 함수를 이용하면, empty값으로 된 배열의 값을 모두 'undefined'(아직 값을 설정하지 않은 상태)로 바꿔줍니다.

.map(함수(element, index){}) => map함수는, 다음과 같은 역할을 합니다.

//map함수

var balls = Array(45).fill()


var mapped = balls.map(function(ele, idx){
    return idx;
})

console.log(mapped);

//=>> 배열내에 [1 ..... 44] 이런식으로 1~44까지의 값이 출력됨.
//=>> 만약 return ele를 한다면 45개의 undefined가 배열내에 출력됩니다.
//=>> 즉, 배열 내 element값이나, idx값으로 배열을 치환해주는 역할을 합니다.

 

위 코드처럼 우리는 return값에 index값 + 1을 해줌으로써 1~45까지의 숫자를 배열에 가지게 됩니다.

배열 내 숫자는 1~ 45까지 순차적으로 되어있으니, 이걸 섞어줍시다.

var balls = Array(45).fill().map(function(item, idx){
    return idx+1;
});

var shuffled = [];
while(balls.length > 0){
    var moved = balls.splice(Math.floor(Math.random() * balls.length), 1)[0];
    shuffled.push(moved);
}

1. balls에서 45개의 숫자를 가진 배열을 생성했고,

2. shuffled라는 새로운 배열을 변수에 할당했으며,

3. while조건문을통해, 배열만큼 반복하는(45회) 반복문을 작성했습니다.

4. 그리고, moved(이동되었다는의미)에서는 balls(45개의 순차적배열)의 값을 랜덤한 숫자부터 1개씩 뽑는 splice함수를 사용해줬습니다.

*여기서 뒤에 [0]을 쓴 이유는, 뽑은 값이 [9], [31] 이런식으로 배열로 리턴되기에, 각 배열의 0번째값 즉 본인 자신의 값을 불러오도록 [0]을 붙여줬습니다.

5. 그리고, 위에서 생성한 shuffled라는 빈 변수에, push()함수를 활용해 shuffled라는 변수에 1~45중 무작위의 순서대로 뽑은 45개의 숫자를 넣어줬습니다. 즉, balls에서 1~45까지의 숫자를 순차적으로 [1,2,3,4,5,6....45] 이런식으로 대입했다면, shuffled 변수에는 balls값을 무작위로 섞어서 넣어줬습니다.

 

그럼 이제, 기본볼과, bonus볼을 shuffled(섞인 배열)에서 기본볼은 맨앞에서 6개, 그리고 bonus볼은 맨 뒤에서 하나 가져오는 식으로 변수를 만들어보겠습니다.

var balls = Array(45).fill().map(function(item, idx){
    return idx+1;
});

var shuffled = [];
while(balls.length > 0){
    var moved = balls.splice(Math.floor(Math.random() * balls.length), 1)[0];
    shuffled.push(moved);
}
var picked_number = shuffled
                    .slice(0, 6) //마지막 수는 포함되지 않음.
                    .sort(function(p,c){
                        return p-c
                    });
var bonus = shuffled[shuffled.length-1];

1. picked_number(기본볼) 6개를 shuffled 배열에서, slice함수를 이용해서 가져왔습니다.

그리고 그 숫자가 무작위기에, 4, 17, 15, 29, 3 이런식으로 오름차순, 혹은 내림차순이 되지않습니다. 그것을 sort함수를 이용해서 소팅(정렬)해줬습니다.

**sort함수 부가설명

sort함수에 function을 주고 매개변수로 p(previes, 이전숫자), c(current, 현재숫자) 를 준다음 return값으로 p-c를 해줬습니다.

이게, 이전숫자(p) - 현재숫자(c)를 해서, -가되면, 현상태를 유지하고, +가되면 서로 자리를 바꿔주는 역할을 합니다.

그럼 반대로, c - p라고 리턴값을 주게되면, 역순정렬이 됩니다.

 

2. 그리고 bonus 변수에는 shuffled 배열에서, 맨 마지막 숫자 하나만을 가져올 수 있게 [shuffled.length-1]을 해줬습니다.

(배열은 0부터 숫자를 세고, length는 1부터 숫자를 세기 때문에 -1을 붙여줬습니다.)

 

이제 이벤트리스너와, 작동을 위한 함수를 작성해주도록하겠습니다.

var balls = Array(45).fill().map(function(item, idx){
    return idx+1;
});

var shuffled = [];
while(balls.length > 0){
    var moved = balls.splice(Math.floor(Math.random() * balls.length), 1)[0];
    shuffled.push(moved);
}
var picked_number = shuffled
                    .slice(0, 6) //마지막 수는 포함되지 않음.
                    .sort(function(p,c){
                        return p-c
                    });
var bonus = shuffled[shuffled.length-1];


var result_button = document.querySelector('.result_button');
result_button.addEventListener('click', function(){
    function ball_color(num) {
        var result_blank = document.querySelector('#result_blank');
        var ball = document.createElement('div');
        ball.textContent = picked_number[num];
        result_blank.appendChild(ball);
    }
});

1. var result_button 이라고 변수를 선언하고, 이것이 HTML의 result_button(기본공을뽑는버튼)을 선택하도록 querySelector를 사용해 지정해줬습니다.

** document.querySelcector(선택할 HTML)

위와 같은 형식으로 작성해주면 되는데요. 선택할 HTML부분에 CSS작성하는것과 같이 '.className' 혹은 '#id' 이런식으로 넣어주면, HTML에서 해당 ID값이나, class값을 가진 부분을 선택할 수 있습니다.

2. 그리고 result_button(기본공을 뽑는 버튼)에 클릭 이벤트를 다루는 이벤트 리스너를 추가해줬습니다.

3. ball_color라는 함수를 만들어줬는데요. 이 함수는 볼을 생성하고, 출력하고, 디자인(CSS)하는 것까지 모두 합니다. (CSS요소가 엄청~ 많아서 ball_color라고 이름을 지었어요 ㅎㅎ..;;

4. result_blank 변수를 선언해, 이를 위에서 배운 querySelector를 이용해서, 볼을 출력할 HTML 중 <div id='result_blank'></div> 요부분을 선택하게 해줬습니다.

5. 그리고 ball변수에 div태그를 생성해줬고, 이 ball 변수를 4번에서 만든 result_blank(<div id='result_blank'></div>) 이 부분에 자식 div태그로 삽입하도록 작성했습니다.

6. 그리고, ball 변수에 textContent(내용)으로 picked_number(배열 내 6개의 기본볼)을 작성하게 해줬고, 이 배열내에는 예를들어,[1,5,26,36,40,55] 이런식으로 여섯개의 요소가 존재할 것이기에, 읽는 값은 function의 매개변수로 두어 유동적으로 만들었습니다.

 

그리고 이 볼들을 이제 출력해야 하잖아요? 순차적으로 시간 갭을 두고 출력하기 위해 setTimeout함수를 사용합니다.

var balls = Array(45).fill().map(function(item, idx){
    return idx+1;
});

var shuffled = [];
while(balls.length > 0){
    var moved = balls.splice(Math.floor(Math.random() * balls.length), 1)[0];
    shuffled.push(moved);
}
var picked_number = shuffled
                    .slice(0, 6) //마지막 수는 포함되지 않음.
                    .sort(function(p,c){
                        return p-c
                    });
var bonus = shuffled[shuffled.length-1];


var result_button = document.querySelector('.result_button');
result_button.addEventListener('click', function(){
    function ball_color(num) {
        var result_blank = document.querySelector('#result_blank');
        var ball = document.createElement('div');
        ball.textContent = picked_number[num];
        result_blank.appendChild(ball);
    }
    setTimeout(function(){
        ball_color(0);
    }, 1000);
    setTimeout(function(){
        ball_color(1);
    }, 2000);
    setTimeout(function(){
        ball_color(2);
    }, 3000);
    setTimeout(function(){
        ball_color(3);
    }, 4000);
    setTimeout(function(){
        ball_color(4);
    }, 5000);
    setTimeout(function(){
        ball_color(5);
    }, 6000);
});

setTimeout함수를 사용해서, ball_color함수를 호출시킵니다. 그리고 ball_color함수의 매개변수인 num값을, 0, 1,2,3,4,5 이렇게 순차적으로 삽입해줌으로써 picked_number(기본볼 배열, 6개의 엘리먼트)들을 하나씩 뽑아 공에 담을 수 있게 됩니다. 그리고 설정시간을 첫번째공은 1000, 둘째는 2000, 셋쨰는 3000, 넷째는 4000 ...... 이런식으로 해주면서 공이 하나씩 출력될 수 있게 해줬습니다.

 

**setTimeout =>> 설정한 시간 이후에 함수를 실행시키는 메소드입니다.

setTimeout(실행함수, 설정시간) << 이렇게 구성되어있습니다. 설정시간의 1000은 1초 단위로 계산됩니다.

 

 

그럼 이제, 볼의 css요소를 조금 추가해보도록하겠습니다.

var balls = Array(45).fill().map(function(item, idx){
    return idx+1;
});

var shuffled = [];
while(balls.length > 0){
    var moved = balls.splice(Math.floor(Math.random() * balls.length), 1)[0];
    shuffled.push(moved);
}
var picked_number = shuffled
                    .slice(0, 6) //마지막 수는 포함되지 않음.
                    .sort(function(p,c){
                        return p-c
                    });
var bonus = shuffled[shuffled.length-1];


var result_button = document.querySelector('.result_button');
result_button.addEventListener('click', function(){
    function ball_color(num) {
        var result_blank = document.querySelector('#result_blank');
        var ball = document.createElement('div');
        ball.textContent = picked_number[num];
        ball.style.display = 'inline-block';
        ball.style.border = '1px solid black';
        ball.style.borderRadius = '20px';
        ball.style.width = '30px';
        ball.style.height = '30px';
        ball.style.textAlign = 'center';
        ball.style.marginRight = '15px';
        ball.style.marginTop = '5px';
        ball.style.marginBottom = '5px';
        ball.style.fontSize = '15px'
        ball.style.lineHeight = '30px';
        var background_color;
        if (picked_number[num] <= 10){
            background_color = 'red';
        }else if(picked_number[num] <= 20){
            background_color = 'orange';
        }else if(picked_number[num] <= 30){
            background_color = 'yellow';
        }else if(picked_number[num] <= 40){
            background_color = 'blue';
        }else{
            background_color = 'green';
        }
        ball.style.background = background_color;
        result_blank.appendChild(ball);
    }
    setTimeout(function(){
        ball_color(0);
    }, 1000);
    setTimeout(function(){
        ball_color(1);
    }, 2000);
    setTimeout(function(){
        ball_color(2);
    }, 3000);
    setTimeout(function(){
        ball_color(3);
    }, 4000);
    setTimeout(function(){
        ball_color(4);
    }, 5000);
    setTimeout(function(){
        ball_color(5);
    }, 6000);
});

1. css내용은 볼 모양의 ㅇ << 이런 둥그런 모양을 만든다는 것이고,

**CSS에서는 margin-bottom 이런식으로 쓰는데 반해, JS에서는 CSS를 marginBottom 이렇게, '-'구분자를 삭제하고, 대문자로 대신하는 방식의 표기법을 사용합니다.

2. var background_color부분부터 보시면, 볼의 배경색을 지정하는 부분입니다. 조건문으로 picked_number[num]<< 뽑은 기본공의 값이 10보다 작거나 같으면 빨간색, 11~20까지는 오렌지색, 21~30까지는 노란색, 31~40까지는 파란색, 그리고 41~45까지는 녹색으로 한다는 코드입니다.

 

 

그럼 이제 기본공을 출력하는 부분은 끝났으니, 보너스볼을 출력하는 부분을 작성해보겠습니다. (기본공과 같은 로직을 사용합니다.)

var bonus_button = document.querySelector('.result_bonus');
bonus_button.addEventListener('click', function(){
    setTimeout(function(){
        var bonus_blank = document.querySelector('.bonus_blank');
        var bonus_ball = document.createElement('div');
        bonus_ball.textContent = bonus;
        bonus_ball.style.display = 'inline-block';
        bonus_ball.style.border = '1px solid black';
        bonus_ball.style.borderRadius = '20px';
        bonus_ball.style.width = '30px';
        bonus_ball.style.height = '30px';
        bonus_ball.style.textAlign = 'center';
        bonus_ball.style.marginTop = '5px';
        bonus_ball.style.marginBottom = '5px';
        bonus_ball.style.lineHeight = '30px';
        var background_color = '#bfff00';
        bonus_ball.style.background = background_color;
        bonus_blank.appendChild(bonus_ball);
    }, 1000);
})

1. bonus_button 변수를 생성해, querySelector로, HTML에 result_bonus클래스를 가져옵니다.

2. bonus_button에 EventListner를 추가해서, 클릭이벤트를 생성했습니다.

3. setTimeout을 이용해, 버튼을 클릭하고 1초뒤에 공을 보여주도록 했습니다.

4. bonus_blank변수를 만들어 querySelector로 , HTML의 bonus_blank(보너스볼을 출력하는공간)을 가져왔습니다.

5. bonus_ball변수에 div태그를 생성해주고, 이를 bonus_blank의 자식태그로 추가시켜줬습니다.

6. 사이의 CSS태그는 위와 마찬가지로, ㅇ << 이런 동그란 공모양을 만들어주고, 공 번호가 가운데 위치할 수 있도록 해줬습니다. background Color부분은, 금색깔을 구글링해서 찾다가 대충 집어넣은 색이니 원하시는 색으로 하셔도 좋습니다.

 

 

요번엔 앞에 내용이 많이 겹치므로 좀 수월하게 할 수 있었죠? ㅎㅎ

그럼 마무리 코드 살펴보겠습니다.

 

lotto.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>로또 추첨기</title>
</head>
<body>
    <h3>당첨숫자!</h3>
    <div id='result_blank'></div>
    <button class='result_button'>당첨숫자보기</button>
    <h3>보너스볼!</h3>
    <div class='bonus_blank'></div>
    <button class='result_bonus'>보너스볼보기</button>
    <script src="lotto.js"></script>
</body>
</html>

 

lotto.js

var balls = Array(45).fill().map(function(item, idx){
    return idx+1;
});

var shuffled = [];
while(balls.length > 0){
    var moved = balls.splice(Math.floor(Math.random() * balls.length), 1)[0];
    shuffled.push(moved);
}
var picked_number = shuffled
                    .slice(0, 6) //마지막 수는 포함되지 않음.
                    .sort(function(p,c){
                        return p-c
                    });
var bonus = shuffled[shuffled.length-1];


var result_button = document.querySelector('.result_button');
result_button.addEventListener('click', function(){
    function ball_color(num) {
        var result_blank = document.querySelector('#result_blank');
        var ball = document.createElement('div');
        ball.textContent = picked_number[num];
        ball.style.display = 'inline-block';
        ball.style.border = '1px solid black';
        ball.style.borderRadius = '20px';
        ball.style.width = '30px';
        ball.style.height = '30px';
        ball.style.textAlign = 'center';
        ball.style.marginRight = '15px';
        ball.style.marginTop = '5px';
        ball.style.marginBottom = '5px';
        ball.style.fontSize = '15px'
        ball.style.lineHeight = '30px';
        var background_color;
        if (picked_number[num] <= 10){
            background_color = 'red';
        }else if(picked_number[num] <= 20){
            background_color = 'orange';
        }else if(picked_number[num] <= 30){
            background_color = 'yellow';
        }else if(picked_number[num] <= 40){
            background_color = 'blue';
        }else{
            background_color = 'green';
        }
        ball.style.background = background_color;
        result_blank.appendChild(ball);
    }
    setTimeout(function(){
        ball_color(0);
    }, 1000);
    setTimeout(function(){
        ball_color(1);
    }, 2000);
    setTimeout(function(){
        ball_color(2);
    }, 3000);
    setTimeout(function(){
        ball_color(3);
    }, 4000);
    setTimeout(function(){
        ball_color(4);
    }, 5000);
    setTimeout(function(){
        ball_color(5);
    }, 6000);
})

var bonus_button = document.querySelector('.result_bonus');
bonus_button.addEventListener('click', function(){
    setTimeout(function(){
        var bonus_blank = document.querySelector('.bonus_blank');
        var bonus_ball = document.createElement('div');
        bonus_ball.textContent = bonus;
        bonus_ball.style.display = 'inline-block';
        bonus_ball.style.border = '1px solid black';
        bonus_ball.style.borderRadius = '20px';
        bonus_ball.style.width = '30px';
        bonus_ball.style.height = '30px';
        bonus_ball.style.textAlign = 'center';
        bonus_ball.style.marginTop = '5px';
        bonus_ball.style.marginBottom = '5px';
        bonus_ball.style.lineHeight = '30px';
        var background_color = '#bfff00';
        bonus_ball.style.background = background_color;
        bonus_blank.appendChild(bonus_ball);
    }, 1000);
})

 

3. 문법정리

이번시간에 나왔던 문법은 대다수 앞에서 겹치는 내용이 많았고, 조금 다른점은 HTML에서 HTML을 작성할 수 있게 되었고, 우리는 js를 통해 그런 HTML을 제어하는 document.querySelector를 알아보았습니다.

 

그리고 배열의 주요 메소드들, Array, fill, map, sort 등을 사용해보았습니다.

//Array() =>> 배열을 원하는 element 갯수만큼 생성해준다.
//단 요소들은 empty로, 반복문의 적용이 불가하다.

var ary = Array(100);





//fill() =>> empty로 채워진 배열들을 undefined라는 값으로 넣어줄 수 있는 역할을 한다.

ary.fill();






//map() =>> 배열내 값을 원하는 index 혹은 element 값으로 바꿀 수 있게 해준다. 즉, 치환해준다.
//map을 사용할때는 반드시 할당할 변수를 선언해줘야한다.

var mapped_array = ary.map(element, index){
                      return element;
                      return index;
                  })
                  
                  
        
        
        

 //sort() =>> 배열내 숫자를 정렬해주는 역할을 한다.
 var array = [1,4,3,10,5,9]
 
 
 array.sort(function(p,c){
 	return p-c;
 });
//위 sort의 결과는 => [1,3,4,5,9,10]



 array.sort(function(p,c){
 	return c-p;
 });
 //위 sort의 결과는 => [10,9,5,4,3,1]

**sort함수 부가설명

sort함수에 function을 주고 매개변수로 p(previes, 이전숫자), c(current, 현재숫자) 를 준다음 return값으로 p-c를 해줬습니다.

이게, 이전숫자(p) - 현재숫자(c)를 해서, -가되면, 현상태를 유지하고, +가되면 서로 자리를 바꿔주는 역할을 합니다.

그럼 반대로, c - p라고 리턴값을 주게되면, 역순정렬이 됩니다.

 

 

다음시간에는 '가위바위보'게임을 만들어 보도록 하겠습니다.