기초부터 시작하는 코딩/Javascript

Javascript를 이용한 사이트 만들기! - 퀴즈 효과 사이트 만들기05

kebab00 2023. 3. 25. 12:34

728x90

- 5번째는 문제가 60개 있는 사이트를 만들어 보았습니다.

- 정답확인을 눌렀을 때 틀렸는지 맞았는지와 함께 점수를 알려주는 버튼도 만들었습니다.

- 바로 스크립트 코드로 넘어가 보도록하죠

const quizInfo = [
            {
                infoType : "정보처리 기능사" ,
                infoTime : "2011년 4회" ,
                infoNumber : "20110401",
                infoQuestion : "일반적으로 명령어의 패치 사이클 중에는 현재 수행하고 있는 명령어의 위치를 가리키고, 실행 사이클 중에는 바로 다음에 실행할 명령어의 위치를 가리키는 Register는?",
                infoChoice : {
                     1: "누산기(accumulator)",   
                     2: "프로그램 카운터(program counter)",    
                     3: "명령어 레지스터(instruction register)",   
                     4: "범용 레지스터(general purpose register)"
                },
                infoAnswer: "2",
                infoDesc : "누산기(accumulator) : 연산결과 일시 저장<br>프로그램 카운터(program counter) : 다음 수행 명령번지 기억<br>명령어 레지스터(instruction register) : 현재수행중인 명령어를 일시저장"
            },{
                infoType : "정보처리 기능사" ,
                infoTime : "2011년 4회"  ,
                infoNumber : "20110402",
                infoQuestion : "스택 연산에서 데이터를 삽입하거나 삭제하는 동작을 나타내는 것은?",
                infoChoice : {
                     1: "ADD, SUB",   
                     2: "LOAD, STORE",    
                     3: "PUSH, POP",   
                     4: "MOV, MUL"
                },
                infoAnswer: "3",
                infoDesc : "PUSH : 데이터 삽입<br>POP : 데이터 꺼내기(삭제)",
            },{
                infoType : "정보처리 기능사" ,
                infoTime : "2011년 4회" ,
                infoNumber : "20110403",
                infoQuestion : "다음 중 제어장치에서 명령어의 실행 사이클에 해당하지 않는 것은?",
                infoChoice : {
                     1: "인출 주기(fetch cycle)",   
                     2: "직접 주기(direct cycle)",    
                     3: "간접 주기(indirect cycle)",   
                     4: "실행 주기(execute cycle)"
                },
                infoAnswer: "2",
                infoDesc : "제어장치의 명령어 실행 사이클은 기계주기(Machine Cycle)라 하며, 다음과 같다..<br> ① 인출사이클(Fetch Cycle) - 중앙처리장치가 기억장치에서 다음에 실행할 명령을 가져오는 주기)<br>② 명령사이클(Instruction Cycle) - 기억장치의 번지를 확인하여 명령을 읽어 낼 때까지의 단계<br>③ 실행사이클(Execution Cycle) - 명령에 따라 필요한 신호를 만들어 결과를 얻을 때까지의단계",
            }
]
//선택자 
let quizScore = 0;
// console.log(quizInfo[2].infoChoice[1]);
// 문제 출력
const updateQuiz = () => {
    const exam = [];
    quizInfo.forEach((question, number) => {
        exam.push(`
            <div class="quiz">
                <div class="qiuz__header">
                    <h2 class="quiz__title">${question.infoType} ${question.infoTime}</h2>
                </div>
                <div class="qiuz__main">
                    <div class="qiuz__question"><em>${number+1}</em>.${question.infoQuestion}
                    </div>
                    <div class="qiuz__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");

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

    //사용자가 체크한 정답 == 문제 정답 
    quizInfo.forEach((question, number) => {
        const userSelector = `input[name=choice${number}]:checked`;  //사용자가 체크한 정답을 찾는 방법 체크를 했을때 checked라는 속성이 추가된다.
        const quizSelectorWrap = quizChoices[number];
        const userAnswer = (quizSelectorWrap.querySelector(userSelector)||{}).value;
        const dogWrap = quizWrap.querySelectorAll(".dog__wrap");
        if (userAnswer == question.infoAnswer){
            dogWrap[number].classList.add("like");
            quizScore++;
        } else {
            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);

- 배열 안에 객체를 넣고 그 객체 안에 문제에 대한 정보들을 넣어 줍니다. 그렇게 60개를 해야되는데 여기에는 3개만 넣어 놨습니다.

- updateQuiz라는 익명함수를 만들고 그 안에 exam이라는 변수에 빈 배열을 만들어 두었습니다.

- 그리고 quizInfo를 대상으로 하는 forEach문을 만들어 반복시켜주고 그 안의 데이터는 question, index값은 number로 설정해주고 .push를 사용해 exam 안에 태그들을 넣어 주었습니다. 

- 중간에 문제의 데이터가 필요한 부분에 ${question.infoType} 와 같이 데이터를 넣어주었습니다.

- 이렇게 하면 문제는 끝이 납니다. 

- 이제 문제를 채점해주는 방법을 알아보도록하죠

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

    //사용자가 체크한 정답 == 문제 정답 
    quizInfo.forEach((question, number) => {
        const userSelector = `input[name=choice${number}]:checked`;  //사용자가 체크한 정답을 찾는 방법 체크를 했을때 checked라는 속성이 추가된다.
        const quizSelectorWrap = quizChoices[number];
        const userAnswer = (quizSelectorWrap.querySelector(userSelector)||{}).value;
        const dogWrap = quizWrap.querySelectorAll(".dog__wrap");
        if (userAnswer == question.infoAnswer){
            dogWrap[number].classList.add("like");
            quizScore++;
        } else {
            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);

- 아까처럼 forEach문을 하나만들어 줍니다.

- const userSelector = `input[name=choice${number}]:checked`; 를 통해 사용자가 체크한 답을 찾아주고 

- 그 답과 정답이 같은지 비교를 한 뒤  같으면 like와 스코어를 더해주고 틀리면 dislike를 클라스를 더해주는 조건문을 만들어 주었습니다.

- 그리고  실행되었을 때 설명과 점수가 보이게 만들어 주었습니다. 

- 그리고 addEventListener - click를 사용해서 정답확인을 클릭했을 때 함수가 실행되게 만들어 주면~~

- 끝!!