JAVASCRIPT

(6) 자바스크립트 퀴즈 사이트 만들기 !

Kim do hyun 2023. 3. 27. 19:40
728x90
반응형

퀴즈 사이트 만들기 여섯번째

 

직접 만들어본 퀴즈 사이트입니다. 답을 선택하면 틀린답인지 정답인지 구별하여 강아지가 알려주고, 

답을 선택하면 나오는 다음 문제 버튼을 누르면 다음 문제로 넘어갑니다.

 

 

 

HTML

<header id="header">
    <h1><a href="../javascript14.html">Quiz</a> <em>객관식 확인하기(여러문제) 유형 : 슬라이드 유형</em></h1>
    <ul>
        <li><a href="quizEffect01.html">1</a></li>
        <li><a href="quizEffect02.html">2</a></li>
        <li><a href="quizEffect03.html">3</a></li>  
        <li><a href="quizEffect04.html">4</a></li>         
        <li><a href="quizEffect05.html">5</a></li>         
        <li class="active"><a href="quizEffect05.html">6</a></li>           

    </ul>
</header> 
<!-- //header -->


<main id="main">
    <div class="quiz__wrap">
        <div class="quiz">
            <div class="quize__header">
                <h2 class="quiz__title"></h2>
            </div>
            <div class="quize__main">
            <div class="quiz__question"></div>
            <div class="quiz__view">
                <div class="dog__wrap">
                    <div class="question__number"></div>
                    <div class="true">정답입니다!</div>
                    <div class="false">틀렸습니다!</div>
                    <div class="card-container">
                        <div class="dog">
                            <div class="head">
                                <div class="ears"></div>
                                <div class="face"></div>
                                <div class="eyes">
                                    <div class="teardrop"></div>
                                </div>
                                <div class="nose"></div>
                                <div class="mouth">
                                    <div class="tongue"></div>
                                </div>
                                <div class="chin"></div>
                            </div>
                            <div class="body">
                                <div class="tail"></div>
                                <div class="legs"></div>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="quiz__info"></div>
                <div class="quiz__check"></div>
            </div>
            <div class="quiz__choice">
                <!-- <label for="choice1">
                    <input type="radio" id="choice1" name="choice" class="select" value="1">
                    <span></span>
                </label>
                <label for="choice2">
                    <input type="radio" id="choice2" name="choice" value="2">
                    <span></span>
                </label>
                <label for="choice3">
                    <input type="radio" id="choice3" name="choice" value="3">
                    <span></span>
                </label>
                <label for="choice4">
                    <input type="radio" id="choice4" name="choice" value="4">
                    <span></span>
                </label> -->
            </div>
            <div class="quiz__answer">
                <button class="next">다음 문제</button>
            </div>

            <div class="quiz__desc"></div>
        </div>
        </div>     
    </div>
</div>
</main>
<!-- //main -->


<footer id="footer">
    <a href="mail:kshkmn0929@naver.com">kshkmn0929@naver.com</a>
</footer>
<!-- //footer -->

 

 

JAVASCRIPT

<script>
    const quizInfo = [
        {
            infoType: "정보처리 기능사",
            infoTime: "2007년 04월 01일(2회)",
            infoNumber: "20070201",
            infoQuestion: "flip-flop의 종류에 해당하지 않는 것은?",
            infoChoice: ["R-S","J-K","D","R"],
            infoAnswer: "R",
            infoDesc: "R 플립플롭은 존재 하지 않습니다."
        },{
            infoType: "정보처리 기능사",
            infoTime: "2007년 04월 01일(2회)",
            infoNumber: "20070202",
            infoQuestion: "보기의 도형과 관련 있는 사항은?<br><img style='width:300px' src='../assets/img/noname01.tmp'>",
            infoChoice: ["OR 게이트", "버퍼(buffer)", "NAND 게이트", "인버터(Inverter)"],
            infoAnswer: "인버터(Inverter)",
            infoDesc: "그림은 인버터(NOT)입니다."
        },{
            infoType: "정보처리 기능사",
            infoTime: "2007년 04월 01일(2회)",
            infoNumber: "20070203",
            infoQuestion: "<img style='width:300px' src='../assets/img/question3.jpg'>",
            infoChoice: ["1번","2번","3번","4번"],
            infoAnswer: "4번",
            infoDesc: "드모르간 정리는 위에 긴 막대를 쪼개고 안의 부호를 바꾸는 방식입니다."
        },{
            infoType: "정보처리 기능사",
            infoTime: "2007년 04월 01일(2회)",
            infoNumber: "20070204",
            infoQuestion: "논리적 연산의 종류에 해당되지 않는 것은?",
            infoChoice: ["AND","OR","Rotate","ADD"],
            infoAnswer: "ADD",
            infoDesc: "ADD는 덧셈을 의미하며 논리연산이 아닌 산술 연산 입니다.<br>산술적연산은 4가지입니다.<br>ADD - 덧셈 / SUB - 뺄셈 / MUL - 곱셈 / DIV - 나눗셈<br>그외에 산술적 shift 가 있는데 좌로 2shift x2를 의미하며,<br> 우로 2shift 는 1/2를 의미"
        },{
            infoType: "정보처리 기능사",
            infoTime: "2007년 04월 01일(2회)",
            infoNumber: "20070205",
            infoQuestion: "다음 블록화 레코드에서 블록화 인수는?<br><img style='width:300px' src='../assets/img/noname02.tmp'>",
            infoChoice: ["1","2","3","4"],
            infoAnswer: "3",
            infoDesc: "블록화 인수(BF)는 IBG와 IBG 사이의 논리 레코드 갯수를 의미 합니다."
        },{
            infoType: "정보처리 기능사",
            infoTime: "2007년 04월 01일(2회)",
            infoNumber: "20070206",
            infoQuestion: "로더(loader)의 기능이 아닌 것은?",
            infoChoice: ["할당(allocation)","링킹(linking)","재배치(relocation)","스케줄링(scheduling)"],
            infoAnswer: "스케줄링(scheduling)",
            infoDesc: "로더는 메모리로 프로그램을 불러 주는 기능을 합니다..스케쥴링이란 CPU의 스케쥴을 짜주는것을 말합니다."
        }
    ]

    // 선택자
    const quizWrap = document.querySelector(".quiz__wrap");
    const quizTitle = quizWrap.querySelector(".quiz__title");
    const quizQuestion = quizWrap.querySelector(".quiz__question");
    const quizChoice = quizWrap.querySelector(".quiz__choice");
    const dogWrap = quizWrap.querySelector(".dog__wrap");
    const quizAnswer = quizWrap.querySelector(".quiz__answer");
    const quizNext = quizWrap.querySelector(".quiz__answer .next");
    const quizDesc = quizWrap.querySelector(".quiz__desc");
    const quizQuestionNum = quizWrap.querySelector(".question__number")
    const quizInfO = quizWrap.querySelector(".quiz__info");
    const quizCheck = quizWrap.querySelector(".quiz__check");

    let quizCount = 0;
    let quizScore = 0;


    // 문제출력
    const updateQuize = (index) => {
        let typeTag = `
            <span>${quizInfo[index].infoType}</span>
            <em>${quizInfo[index].infoTime}</em>
        `;
        let questionTag = `
            <em>${index+1}</em>.
            <span>${quizInfo[index].infoQuestion}</span>
        `;
        let questionnumTag = `
            <div class="question__number">현재 남은 문제는 ${[quizInfo.length-index]} 현재 ${[index+1]} 번</div>                
        `;
        let choiceTag = `
                <label for="choice1">
                    <input type="radio" id="choice1" name="choice" class="select" value="1">
                    <span>${quizInfo[index].infoChoice[0]}</span>
                </label>
                <label for="choice2">
                    <input type="radio" id="choice2" name="choice" class="select"  value="2">
                    <span>${quizInfo[index].infoChoice[1]}</span>
                </label>
                <label for="choice3">
                    <input type="radio" id="choice3" name="choice" class="select"  value="3">
                    <span>${quizInfo[index].infoChoice[2]}</span>
                </label>
                <label for="choice4">
                    <input type="radio" id="choice4" name="choice" class="select"  value="4">
                    <span>${quizInfo[index].infoChoice[3]}</span>
                </label>
            `;
        let descTag = `
            정답은 ${quizInfo[index].infoAnswer} 입니다.
            ${quizInfo[index].infoDesc}
        `;


        quizTitle.innerHTML = typeTag;
        quizQuestion.innerHTML = questionTag;
        quizChoice.innerHTML = choiceTag;
        quizDesc.innerHTML = descTag;
        quizQuestionNum.innerHTML = questionnumTag;
        quizInfO.innerHTML = "??"
        quizCheck.innerHTML = "정답 확인"

        // 보기 선택자
        const quizChoiceSpan = quizWrap.querySelectorAll(".quiz__choice span");
        const quizChoiceInput = quizWrap.querySelectorAll(".quiz__choice input");

        // quizChoiceSpan.forEach((span, num) => {
        //     span.setAttribute("onclick", "choiceSelected(this)")
        // });

        for(let i=0; i<quizChoiceSpan.length; i++){
            quizChoiceSpan[i].setAttribute("onclick", "choiceSelected(this)");
            // quizChoiceInput.disabled = "true";
        }


        // 다음 버튼, 해설 숨기기
        quizAnswer.style.display = "none";
        quizDesc.style.display = "none";
    };

    updateQuize(quizCount);


    // 객관식 선택
    function choiceSelected(answer){
        let userAnswer = answer.textContent;                    // 사용자 정답
        let currentAnswer = quizInfo[quizCount].infoAnswer;     // 문제 정답


        if(userAnswer == currentAnswer){
            console.log("정답입니다.");
            dogWrap.classList.add("like");
        } else {
            console.log("오답입니다.");
            dogWrap.classList.add("dislike");
        }

        // 다음 버튼, 해설 나타나기

        quizAnswer.style.display = "block";
        quizDesc.style.display = "block";
    }


    // 정답 확인
    quizNext.addEventListener("click", () => {
        quizCount++;
        updateQuize(quizCount);

        dogWrap.classList.remove("like", "dislike");
    });


    document.querySelector(".quiz__check").addEventListener("click", answerQuiz);
</script>

자바스크립트 설명

quizInfo 안에 배열 안에 객체 데이터를 저장하는 방식을 이용하여 정보처리기능사 문제 6개를 저장합니다.

 

문제출력

이 함수는 매개변수로 인덱스 값을 받아와서 해당 인덱스에 해당하는 퀴즈 정보를 화면에 출력하는 기능을 가지고 있습니다.
함수 내부에서는 문자열 템플릿 리터럴을 사용하여 HTML 요소들을 동적으로 생성합니다. typeTag 변수에는 quizInfo 배열의 index번째 요소의 infoType과 infoTime을 포함하는 span과 em 요소를 생성합니다. questionTag 변수에는 quizInfo 배열의 index번째 요소의 infoQuestion과 index+1을 포함하는 em과 span 요소를 생성합니다.
이렇게 생성된 typeTag과 questionTag 문자열은 이후 다른 코드에서 DOM 요소에 추가되어 브라우저에 출력될 것입니다. 즉, 이 함수는 동적인 HTML 생성을 위한 코드입니다

이어서 innerHTML을 이용하여 저장된 문제정보 데이터들을 출력합니다.

 

다음 버튼, 해설 숨기기

style.display = "none";을 이용해서 다음 버튼과 해설을 숨깁니다.

 

다음 버튼, 해설 나타나기

style.display = "block";을 이용해서 다음 버튼과  해설을 나타냅니다.

 

 

for(let i=0; i<quizChoiceSpan.length; i++){
    quizChoiceSpan[i].setAttribute("onclick", "choiceSelected(this)");

}

이 반복문은 quizChoiceSpan 배열의 길이만큼 반복하면서, 각각의 quizChoiceSpan 요소에 클릭 이벤트를 등록합니다.

setAttribute() 함수는 DOM 요소의 속성을 변경하는 메소드입니다. 첫 번째 인자로는 변경하고자 하는 속성의 이름을, 두 번째 인자로는 해당 속성의 값으로 설정할 값을 전달합니다. 이 코드에서는 setAttribute() 함수를 사용하여 onclick 속성을 변경합니다.

onclick 속성은 클릭 이벤트가 발생할 때 실행될 코드를 정의하는 속성입니다. 여기서는 choiceSelected(this) 함수를 실행하도록 설정되어 있습니다. this 키워드는 현재 클릭한 요소(quizChoiceSpan[i])를 가리킵니다.

즉, 이 코드는 quizChoiceSpan 배열에 속한 각각의 요소에 대해 클릭 이벤트를 등록하고, 클릭 이벤트가 발생하면 choiceSelected() 함수를 실행하도록 설정하는 기능을 수행합니다. 이 함수는 해당 퀴즈 선택지에 대한 처리를 수행하는 역할을 할 것입니다.

 

quizNext.addEventListener("click", () => {
    quizCount++;
    updateQuize(quizCount);

    dogWrap.classList.remove("like", "dislike");
});

해당 코드는 JavaScript로 작성된 이벤트 리스너 코드입니다. quizNext DOM 요소에 클릭 이벤트가 발생했을 때 실행되는 콜백 함수를 등록합니다.

이벤트 리스너의 콜백 함수 내부에서는 quizCount 변수 값을 1 증가시킵니다. 이후 updateQuize() 함수를 호출하여 quizCount에 해당하는 다음 퀴즈 정보를 화면에 출력합니다.

마지막으로, dogWrap 요소의 like와 dislike 클래스를 모두 제거합니다. 이 요소는 이전 퀴즈에서 선택된 강아지 이미지를 표시하기 위한 용도로 사용되는 것으로 보입니다. like와 dislike 클래스는 각각 좋아요/싫어요 버튼을 클릭했을 때 추가되는 클래스로, 이전 퀴즈에서 선택된 이미지를 초기화하기 위해 제거하는 것입니다.