Lumpy Space Princess - Adventure Time

JAVASCRIPT

Quiz Effect 05 - 객관식 확인하기(여러 문제) 유형에 대해 알아보자

jongyung 2023. 3. 25. 10:49

“ 지연되는 프로젝트에 인력을 더 투입하면 오히려 더 늦어진다. ”

- Frederick Philips Brooks
Mythical Man-Month 저자
728x90

이번에는 객관식을 여러 개로 늘려서 만들어 보겠습니다.

링크: 퀴즈 이펙트 05 (daanbi1345.github.io)

60문제가 담겨있기 때문에 문제 예시는 1번과 2번 문제만 쓰겠습니다. 

 

body의 main부분과 script를 나눠서 보여드리겠습니다.

body의 main

<main id="main">
    <div class="quiz__wrap">
        <!-- <div class="quiz">
            <div class="quiz__header">
                <h2 class="quiz__title"></h2>                    
            </div>
            <div class="quiz__main">
                <div class="quiz__question"></div>
                <div class="quiz__view">
                    <div class="dog__wrap">
                    <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>
                <div class="quiz__choice">
                    <label for="choice1">
                        <input type="radio" id="choice1" name="choice" 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="confirm">정답 확인하기</button>                        
                </div>
                <div class="quiz__desc"></div>
            </div>                
        </div>            -->
    </div>        
</main>

body에 이전에 했던 방식대로 div 태그에 class 명을 정해서 만들어도 됩니다.

하지만 이번에는 다른 방식을 적용해서 만들어 봤습니다.

script에서 문제 출력 부분을 보면 알 수 있습니다.

script

<script>
    //선택자
    const quizWrap = document.querySelector(".quiz__wrap");
    const quizTitle = quizWrap.querySelector(".quiz__title");
    const quizQuestion = quizWrap.querySelector(".quiz__question");
    const quizChoice = quizWrap.querySelectorAll(".quiz__choice span");
    const quizSelect = quizWrap.querySelectorAll(".quiz__choice input");
    const quizDesc = quizWrap.querySelector(".quiz__desc");
    const quizConfirm = quizWrap.querySelector(".quiz__answer .confirm");//정답 버튼
    const dogWrap = quizWrap.querySelector(".dog__wrap");
    const quizAnswer = quizWrap.querySelector(".quiz__answer")
    let quizScore = 0;

   	//문제 정보
   	const quizInfo = [
    {
        infoType : "정보처리 기능사",
        infoTime : "2011년 5회",
        infoNumber : "20110501",
        infoQuestion : "입출력 조작의 시간과 중앙처리장치의 처리시간과의 불균형을 보완하는 것은?",
        infoChoice : {
            1: "채널장치",
            2: "제어장치",
            3: "터미널장치",
            4: "콘솔장치",
        },
        infoAnswer : "1",
        infoDesc : "채중입 : 채널은 중앙처리장치와 입출력장치 사이에 존재하며 서로의 속도 차이를 보완 합니다."
    }, {
        infoType : "정보처리 기능사",
        infoTime : "2011년 5회",
        infoNumber : "20110502",
        infoQuestion : " 명령어 형식(instruction format)에서 첫 번째 바이트에 기억되는 것은?",
        infoChoice : {
            1: "operand",
            2: "length",
            3: "question mark",
            4: "opcode",
        },
        infoAnswer : "4",
        infoDesc : "명령어의 구성명령어 코드부 + 주소부 (한글),<br> OP-code + Operand (영문)"
    }
    ]

    //    quizQuestion.innerHTML = "<em>"+quizInfo[0].infoNumber+"</em>" +". "+quizInfo[0].infoQuestion;

    //    console.log(quizInfo[2].infoChoice[1])

    //문제 출력
    const updateQUiz = () => {
        const exam = [];

        quizInfo.forEach((question, number) => {
            exam.push(`
            <div class="quiz">
                <div class="quiz__header">
                    <h2 class="quiz__title">${question.infoType} ${question.infoTime}</h2>                    
                </div>
                <div class="quiz__main">
                    <div class="quiz__question"><em>${number+1}</em>. ${question.infoQuestion}</div>
                    <div class="quiz__view">
                        <div class="dog__wrap">
                        <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>
                    <div class="quiz__choice">
                        <label for="choice1${number}">
                            <input type="radio" id="choice1${number}" name="choice${number}" value="1">
                            <span>${question.infoChoice[1]}</span>
                        </label>
                        <label for="choice2${number}">
                            <input type="radio" id="choice2${number}" name="choice${number}" value="2">
                            <span>${question.infoChoice[2]}</span>
                        </label>
                        <label for="choice3${number}">
                            <input type="radio" id="choice3${number}" name="choice${number}" value="3">
                            <span>${question.infoChoice[3]}</span>
                        </label>
                        <label for="choice4${number}">
                            <input type="radio" id="choice4${number}" name="choice${number}" value="4">
                            <span>${question.infoChoice[4]}</span>
                        </label>                        
                    </div>                    
                    <div class="quiz__desc"><em>${question.infoAnswer}</em>번 입니다.<br>${question.infoDesc}</div>
                </div>                
            </div> 
            `);
        });
        exam.push(`
            <div class="quiz__info">??점</div>
            <div class="quiz__check">정답 확인</div>
        `);
        quizWrap.innerHTML = exam.join(" ");

        //설명 숨기기        
            // document.querySelectorAll(".quiz__desc").forEach((el) => {
            //     el.style.display = "none";
            // });

            document.querySelectorAll(".quiz__desc").forEach(el => el.style.display = "none");      
    };
    updateQUiz();

    //정답 확인
    const answerQuiz = () => {
        const quizChoices = document.querySelectorAll(".quiz__choice");

        //사용자가 체크한 정답 == 문제 정답
        quizInfo.forEach((question, number) => {
            const userSelector = `input[name=choice${number}]:checked`; //choice${number}는 속성 선택자
            const quizSelectorWrap = quizChoices[number];
            const userAnswer = (quizSelectorWrap.querySelector(userSelector) || {}).value;
            const dogWrap = quizWrap.querySelectorAll(".dog__wrap");

            if(userAnswer == question.infoAnswer){
                // alert("정답")
                dogWrap[number].classList.add("like");
                quizScore++;
            } else {
                // alert("오답")
                dogWrap[number].classList.add("dislike");                
            }
        });

        //설명 보이기
        document.querySelectorAll(".quiz__desc").forEach(el => el.style.display = "block");

        //점수 보이기
        document.querySelector(".quiz__info").innerHTML = Math.ceil((quizScore / quizInfo.length) * 100) + "점";        
    }

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

선택자를 querySelector와 querySelectorAll로 만들었습니다.

querySelector()는 Element 인터페이스의 메소드 입니다. 
CSS 선택자에 매치되는 하나 이상의 element 중 첫 번째 항목을 반환해줍니다. 
document 객체나 모든 Element 객체에서 사용 가능합니다. 

querySelector() 외에도 querySelectorAll() 메소드도 사용할 수 있는데,

이는 CSS 선택자나 CSS 선택자 그룹에 매치되는 모든 element를 반환합니다.

문제 정보는 배열안에 객체를 넣은 형태로 만들었습니다. 
키와 값을 정해서 불러오기 쉽게 하기 위해서 입니다.

 

push() 메서드는 배열의 끝에 하나 이상의 요소를 추가하고, 배열의 새로운 길이를 반환합니다.

이 메서드로 문제를 출력해봤습니다.

 

body에 썼던 부분을 복사해서 push(``) 안에 입력하고, 문제 정보가 들어가야 할 자리에 해당하는 정보를 입력해주는데,

이 때 ${} 안에 입력하면 됩니다.

문제 정보는 배열 안에 객체를 넣은 형태이므로 이를 유의해서 입력어를 입력하면 됩니다.