이펙트 효과/퀴즈 만들기

정답에 따라 표정이 변하는 강아지 퀴즈만들기!(문제 넘어가기형식) - 6

우당당쿵당콩탕 2023. 3. 27. 18:21
728x90
반응형

 

지난 포스팅에서는 여러개의 문제를 불러와 나열하는 형식이었는데요.

오늘은 답을 맞추면 넘어가는 형식으로 해보겠습니다!

HTML

 <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="next">다음 문제</button>
                    </div>
                    <div class="quiz__desc"></div>
                </div>
            </div>
        </div>
    </main>

퀴즈 만들기 4번과 동일한 형식이지만 객관식 부분을 주석 처리해주었습니다. 한 문제를 풀면 다음 문제로 넘어가야 하는 방식이기에 한 문제 한문제 모두에 객관식을 넣기보다는 자바스크립트에서 태그를 작성해 작업하기 위해 주석처리를 해주었습니다.


Script

const quizInfo = [
{
    infoType : "정보처리기능사",
    infoTime : "2008년 2회",
    infoNumber : "20080201",
    infoQuestion : "다음 논리회로에서 출력 f의 값은?  <img style ='width:200px' src='../assets/data img/image_01.jpg' alt='image_01.jpg'>",
    infoChoice : ["-1", "0", "1/2", "1"],
    infoAnswer : "1",
    infoDesc : "1 AND 1 = 1<br>1 AND 0 = 0<br>1 OR 0 = 1이므로 최종 출력은 1그리고 게이트 문제에서 출력은 무조건 0 아니면 1입니다. 1/2 또는 -1, -2 등은 답이 될수 없습니다."
}]

퀴즈에 대한 정보는 quizInfo라는 변수로 선언해주고 배열 속의 개게 형식으로 데이터를 저장해주었습니다.

//선택자
    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 quizNext = quizWrap.querySelector(".quiz__answer .next");
    const quizDesc = quizWrap.querySelector(".quiz__desc");
    const quizAnswer = quizWrap.querySelector(".quiz__answer");
    const dogHeader = quizWrap.querySelector(".quiz__main h3")

    let quizCount = 0;
    let quizScore = 0;

선택자 부분입니다. 각각의 선택자를 변수에 저장해주었고 quizCount는 quizinfo의 인덱스 값이며 quizScore는 점수를 위한 변수입니다.

const updateQuiz = (index) =>{
    let dogHeaderTag = `
        ${quizInfo.length - quizCount} 문제 남았습니다. 
    `;

    let typeTag = `
        <span>${quizInfo[index].infoType}</span>
        <em>${quizInfo[index].infoTime}</em>
        `;
    let questionTag = `
        <em>${index+1}</em>.
        <span>${quizInfo[index].infoQuestion}</span>
    `;

    let choiceTag = `
    <label for="choice1">
        <input type="radio" id="choice1" name="choice" value="1">
        <span>${quizInfo[index].infoChoice[0]}</span>
    </label>
    <label for="choice2">
        <input type="radio" id="choice2" name="choice" value="2">
        <span>${quizInfo[index].infoChoice[1]}</span>
    </label>
    <label for="choice3">
        <input type="radio" id="choice3" name="choice" value="3">
        <span>${quizInfo[index].infoChoice[2]}</span>
    </label>
    <label for="choice4">
        <input type="radio" id="choice4" name="choice" 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;
    dogHeader.innerHTML = dogHeaderTag;

👉 updateQuiz :  이 변수는 퀴즈 정보를 지속해서 업데이트 해주기 위한 변수입니다. 이 코드에서는 매개변수로 활용 되고 있습니다.

👉  let dogHeaderTag = `${quizInfo.length - quizCount} 문제 남았습니다.`

퀴즈 인포라는 배열의 갯수 (length) 에서 퀴즈 카운트를 빼준 뒤, 뒤편에 문자열을 붙여주는 코드입니다.

👉 let typeTag = `

 <span>${quizInfo[index].infoType}</span> 

 <em>${quizInfo[index].infoTime}</em>

`;

퀴즈 인포라는 변수 내에서 index값을 불러오기 위한 코드입니다. index값 중에서도 infoType과 infoTime을 불러옵니다.

👉 let questionTag = `

<em>${index+1}</em>.

<span>${quizInfo[index].infoQuestion}</span>

`;

문제 번호를 불로오고, 퀴즈 인포의 질문을 불러오는 코드입니다.

👉let ChoiceTag 객관식 목록임과 동시에 퀴즈 인포의 객관식 선택지 데이터를 불러오는 코드입니다.

👉let descTag 문제에 대한 부연설명과 답을 가져오는 코드입니다.

   //보기 선택자
    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";

for 반복문을 사용하여 quizChoiceSpan 요소 배열을 반복합니다.

i 변수는 현재 반복하는 요소의 인덱스를 나타냅니다.

반복문의 각 단계에서, quizChoiceSpan[i] 요소의 onclick 속성을 "choiceSelected(this)"로 설정합니다. 이렇게 함으로써, 사용자가 해당 요소를 클릭할 때 choiceSelected() 함수가 호출되고, 요소 자체가 함수의 인자로 전달됩니다.

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

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

    //다음 버튼, 해설 나타나기
    quizAnswer.style.display = "block";
    quizDesc.style.display = "block";

    if(quizInfo.length - quizCount == 1){
        alert(quizScore + "개 맞았습니다." + Math.ceil((quizScore / quizInfo.length) * 100) + "점 입니다.");
    };
};

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

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

 

👉choiceSelected(answer)

함수는 객관식 답변이 선택될 때마다 호출됩니다.

함수는 사용자가 선택한 답변을 userAnswer 변수에 저장하고, 현재 문제의 정답을 currentAnswer 변수에 저장합니다.

userAnswer currentAnswer 비교하여, 사용자가 선택한 답변이 정답인지 여부를 판별합니다.

 

👉사용자가 정답을 선택한 경우, quizScore 증가시키고, dogWrap 요소에 like 클래스를 추가합니다.

* like는 강아지의 환한 표정입니다.

그렇지 않은 경우, dogWrap 요소에 dislike 클래스를 추가합니다.

* dislike는 슬픈 표정입니다.

quizAnswer quizDesc 요소를 보이도록 설정하여, 정답과 해설이 표시됩니다.

quizCount 변수를 증가시키고, 다음 문제를 보여주는 updateQuiz(quizCount) 함수를 호출합니다.

dogWrap 요소에서 like dislike 클래스를 보이지 않도록 가려줍니다.