본문 바로가기
개발/Javascript

[js] 자바스크립트로 숫자야구 게임 구현하기

by 코딩하는 갓디노 2020. 12. 18.

 

자바스크립트를 이용하여,
숫자야구를 구현하는 예제입니다.

 

예제는 인프런의 제로초, "조현영"님의 강의를 들으면서 공부한 내용입니다.

 

구현 순서

순서 특이사항
컴퓨터가 랜덤 4자리 숫자 문제 제출 예시) 4385, 조건)겹치지 않는 4개
사용자가 답을 입력  
입력한 답의 결과 발표

결과 발표: 홈런/스트라이크/볼
홈런) 숫자가 모두 일치할 경우
스트라이크) 자리수가 맞을 경우
볼) 자리수는 맞이 않으나, 숫자가 맞을 경우

답이 맞을때까지 10회 제한을 둠

 

순수 자바스크립트(리팩토링 전)

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>숫자야구 리팩토링 전</title>
</head>

<body>
    <script>
        //화면구성    
        let title = document.createElement("h1");
        title.textContent = "숫자야구";
        document.body.append(title);
        let form = document.createElement("form");
        document.body.append(form);
        let input = document.createElement("input");
        input.maxLength = 4;
        form.append(input);
        let btn = document.createElement("button");
        btn.textContent = "입력"
        form.append(btn);
        let result = document.createElement("div");
        document.body.append(result);
        
        //숫자뽑기
        let candidate = [1, 2, 3, 4, 5, 6, 7, 8, 9];
        let chosenNum = [];
        
        //숫자 4개 뽑기
        for (let i = 0; i < 4; i++) {
            //1-9까지 랜덤한 숫자 빼주기 splice() 0-8번째 index
            let fourNum = [];
            //[9],[5],[2],[7] array가 4개 나오기 때문에 [0]으로 앞자리만 뽑음
            //splice()가 index를 하나씩 빼주기 때문에 뽑을 숫자가 하나씩 줄음
            //안했을 경우, 랜덤 숫자가 undefined가 나옴 -> 9-i로 index 수 반영
            fourNum = candidate.splice(Math.floor(Math.random() * (9 - i)), 1)[0];
            chosenNum.push(fourNum);
        }
        console.log(chosenNum); //콘솔로 랜덤 숫자 확인

        let tryNum = 0; //시도 10번 제한
        form.addEventListener('submit', function(e) {
            e.preventDefault();
            let answer = input.value; //string
            //string.split('') -> array
            //array.join('') -> string
            if (answer == chosenNum.join('')) { //답이 맞으면 to string
                result.textContent = "홈런! 축하합니다.";
                input.value = "";
                input.focus();
                //다음 문제 내기
                candidate = [1, 2, 3, 4, 5, 6, 7, 8, 9];
                chosenNum = [];

                for (let i = 0; i < 4; i++) {
                    let fourNum = [];
                    fourNum = candidate.splice(Math.floor(Math.random() * (9 - i)), 1)[0];
                    chosenNum.push(fourNum);
                }
                tryNum = 0; //시도 10회로 복귀
                console.log('다음문제' + chosenNum);
            } else { //답이 틀리면 ball, strike 안내
                //answer을 배열로 만들어서 indexOf(값)으로 확인
                let answerArray = answer.split(''); //to array
                let ball = 0;
                let strike = 0;
                tryNum += 1;

                if (tryNum > 10) { //10회 이상 실패시
                    result.textContent = '횟수 초과로 실패하였습니다. 답은 ' + chosenNum.join(', ') + '입니다.';
                    input.value = '';
                    input.focus();
                    //다음 문제 내기
                    candidate = [1, 2, 3, 4, 5, 6, 7, 8, 9];
                    chosenNum = [];

                    for (let i = 0; i < 4; i++) {
                        let fourNum = [];
                        fourNum = candidate.splice(Math.floor(Math.random() * (9 - i)), 1)[0];
                        chosenNum.push(fourNum);
                    }
                    tryNum = 0; //시도 10회로 복귀
                    console.log('다음문제' + chosenNum);
                } else { //시도 10회 이하 실패시
                    for (let i = 0; i < 4; i += 1) {
                        //answerArray는 string이므로 Number() 처리
                        if (Number(answerArray[i]) === chosenNum[i]) { //같은 자리이면 strike
                            strike += 1;
                            //같은 자리는 아니지만, 배열안에 숫자가 있으면 ball
                            //indexOf(값) 값이 있는 index 리턴, 값이 없으면 -1
                        } else if (chosenNum.indexOf(Number(answerArray[i])) > -1) {
                            ball += 1;
                        }
                    }
                    result.textContent = `${strike}스트라이크, ${ball}볼입니다.`;
                    input.value = "";
                    input.focus();
                }
            }
        });
    </script>

</body>

</html>

 

순수 자바스크립트(리팩토링 후)

리팩토링 부분

다음 문제 내는 코드가 3번 반복되므로 이를 함수로 만들어 준다.

	function selectNumFn() {
            candidate = [1, 2, 3, 4, 5, 6, 7, 8, 9];
            chosenNum = [];
            for (let i = 0; i < 4; i++) {
                let fourNum = [];
                fourNum = candidate.splice(Math.floor(Math.random() * (9 - i)), 1)[0];
                chosenNum.push(fourNum);
            }
        }

 

리팩토링 후 스크립트 코드

<script>
        //화면구성    
        let title = document.createElement("h1");
        title.textContent = "숫자야구";
        document.body.append(title);

        let form = document.createElement("form");
        document.body.append(form);

        let input = document.createElement("input");
        input.maxLength = 4;
        form.append(input);
        let btn = document.createElement("button");
        btn.textContent = "입력"
        form.append(btn);

        let result = document.createElement("div");
        document.body.append(result);
        //숫자뽑기
        let candidate
        let chosenNum

        function selectNumFn() {
            candidate = [1, 2, 3, 4, 5, 6, 7, 8, 9];
            chosenNum = [];
            for (let i = 0; i < 4; i++) {
                let fourNum = [];
                fourNum = candidate.splice(Math.floor(Math.random() * (9 - i)), 1)[0];
                chosenNum.push(fourNum);
            }
        }
        selectNumFn();
        console.log(chosenNum);

        let tryNum = 0;
        form.addEventListener('submit', function(e) {
            e.preventDefault();
            let answer = input.value; //string
            if (answer == chosenNum.join('')) { //답이 맞으면

                result.textContent = "홈런! 축하합니다.";
                input.value = "";
                input.focus();
                //다음 문제 내기
                selectNumFn();
                tryNum = 0;

            } else { //답이 틀리면 ball, strike 안내
                let answerArray = answer.split(''); //string
                let ball = 0;
                let strike = 0;
                tryNum += 1;

                if (tryNum > 10) { //10회 이상 실패시
                    result.textContent = '횟수 초과로 실패하였습니다. 답은 ' + chosenNum.join(', ') + '입니다.';
                    input.value = '';
                    input.focus();
                    //다음 문제 내기
                    selectNumFn();
                    tryNum = 0;
                    console.log('다음문제' + chosenNum);
                } else {
                    for (let i = 0; i < 4; i += 1) {
                        if (Number(answerArray[i]) === chosenNum[i]) { //같은 자리이면 strike
                            strike += 1;
                        } else if (chosenNum.indexOf(Number(answerArray[i])) > -1) {
                            ball += 1;
                        }
                    }
                    result.textContent = `${strike}스트라이크, ${ball}볼입니다.`;
                    input.value = "";
                    input.focus();
                }
            }
        });
    </script>

 

화면 결과(Result 클릭)

 

push(), pop(), unshift(), shift() ***

push(): 배열의 끝에 추가 한 후, 변경된 배열을 반환
unshift(): 배열의 처음 자리에 추가 한 후, 변경된 배열을 반환
pop(): 배열의 끝의 요소를 제거한 후, 제거한 것을 반환
shift(): 배열의 첫번째 요소를 제거한 후, 제거한 것을 반환

let arr = [1, 2, 3, 4];
//push()
arr.push("push");  
console.log(arr);  //[1, 2, 3, 4, 'push']

//pop()
arr.pop();  //push

//unshift()
arr.unshift("unshift");  
console.log(arr);  //['unshift', 1, 2, 3, 4]

shift();
arr.shift(); //unshift
console.log(arr); //[1, 2, 3, 4]

 

unshift(), shift() 주의할 점  
배열의 index 앞부터 추가 또는 제거하므로  
뒤의 전체 요소들이 하나씩 순차적으로 앞으로 당겨지기 때문에   
끝의 요소만 담당하는 pop과 push보다 시간이 더 많이 소요됩니다. 
unshift(), shift()보다는 push(), pop()을 사용하는 것을 권장합니다.

 

splice() ***

배열의 해당 위치에 배열 요소를 추가하거나 삭제

arr.splice(start index, deleteCount, added data);
// start - 수정할 요소의 시작하는 인덱스
// deleteCount - 삭제할 갯수, 제거하지 않을 경우 0
// added data - 추가할 데이터
var arr = [1, 5, 7];
arr.splice(1, 0, 2, 3, 4);  // [], arr: [1, 2, 3, 4, 5, 7]
arr.splice(1, 2);           // [2, 3], arr: [1, 4, 5, 7]
arr.splice(1); // [4], arr: [1] 

 

splice(start)만 지정할 경우,
start index부터 마지막까지의 모든 요소를 지워버립니다. 

 

string(),  join() ***

split()는 string을 array로 반환
join()는 array를 string으로 반환

string.split('') -> array
array.join('') -> string
반응형

댓글