WEB/JAVASCRIPT

[javascript] 자바스크립트를 이용한 퀴즈 만들기 : 객관식 퀴즈

aimee418 2023. 3. 27. 21:25

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

- Frederick Philips Brooks
Mythical Man-Month 저자
728x90
반응형

자바스크립트를 이용한 퀴즈 만들기 : 객관식 퀴즈

자바스크립트를 이용하여 슬라이드형 객관식 문제를 만들어 보았습니다.

HTML과 CSS, SCRIPT를 각각 살펴보면서 어떻게 만들었는지 살펴보겠습니다.

 

 

✈. 퀴즈 완성화면

정보처리기능사 문제입니다. 같이 풀어볼까요?

 

 

 

✈. 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="quizEffect06.html">6</a></li>
        </ul>     
    </header> 
    <!-- //header -->
    <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="quiz__count"></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>
                    <div class="quiz__choice">                       
                    </div>
                    <div class="quiz__answer">
                        <!-- <button class="confirm" >정답확인하기</button>      -->
                        <button class="next" >다음문제</button>     

                    </div>
                    <div class="quiz__desc">설명</div>
                </div>
            </div>
              
        </div>

    </main>
    <!-- //main -->
    <footer id="footer">
        <a href="mailto:aimee00418@gmail.com">aimee00418@gmail.com</a>
    </footer>

🏁. POINT

 

 

✈. JAVASCRIPT :문제정보

//문제정보 //<br><img style='width:300px' src=''> 이렇게 이미지 넣기
        const quizInfo = [
            {
                infoType: "정보처리 기능사",
                infoTime: "2009년 7월 12일 5회",
                infoNumber: "20090501",
                infoQuestion: "명령어(Instruction)형식에서 첫 번째 바이트의 기능이 아닌 것은?",
                infoChoice: ["자료의 주소지정 기능", "제어 기능","자료 전달 기능","함수 연산 기능",],
                infoAnswer: "자료의 주소지정 기능",
                infoDesc: "명령어 = 명령어 코드부 + 명령어 주소부 Instruction = Op_Code + Operand 연산자의(명령어 코드) 4가지 기능 1.제어기능 2.입출력기능 3.전달기능 4.함수연산기능"            
            },{
                infoType: "정보처리 기능사",
                infoTime: "2009년 7월 12일 5회",
                infoNumber: "20090502",
                infoQuestion: "다음 불대수(Boolean algebra)의 기본법칙을 바르게 표현한 것은?<br>A+(B+C) = (A+B)+C",
                infoChoice: ["교환법칙", "분배법칙", "흡수법칙", "결합법칙",],
                infoAnswer: "결합법칙",
                infoDesc: "연산자가 모두 동일할 경우 앞으로 괄호로 결합하거나 뒤로 괄호로 결합하거나 하는 것은 결국 같다는 것이 결합 법칙 입니다."
            },{
                infoType: "정보처리 기능사",
                infoTime: "2009년 7월 12일 5회",
                infoNumber: "20090503",
                infoQuestion: "명령어 형식(Instruction Format)에서 첫 번째 바이트에 기억되는 것은?",
                infoChoice: ["Operand ", "Length", "Question Mark", "OP Code",],
                infoAnswer: "OP Code",
                infoDesc: "명령어 = 명령어 코드부 + 명령어 주소부 Instruction = Op_Code + Operand"
            },{
                infoType: "정보처리 기능사",
                infoTime: "2009년 7월 12일 5회",
                infoNumber: "20090504",
                infoQuestion: "EBCDIC 코드는 몇 개의 Zone Bit를 갖는가?",
                infoChoice: ["1",  "2", "3", "4",],
                infoAnswer: "4",
                infoDesc: "코드 비트수 BCD 코드(6) ASCII 코드(7) EBCDIC 코드(8) 모든 코드의 디지트 비트는 4임따라서 각 코드의 존비트는 코드총비트 - 4 임"
            },{
                infoType: "정보처리 기능사",
                infoTime: "2009년 7월 12일 5회",
                infoNumber: "20090505",
                infoQuestion: "주소지정방식 중 처리 속도가 가장 빠르며, 명령의 피연산자부에 피연산자의 주소가 있는 것이 아니라 피연산자의 값 그 자체를 포함하고 있는 주소지정방식은?",
                infoChoice: ["레지스터 지정(Register Addressing)", "직접주소 지정(Direct Addressing)", "즉시주소 지정(Immediate Addressing)", "간접주소 지정(Indirect Addressing)",],
                infoAnswer: "간접주소 지정(Indirect Addressing)",
                infoDesc: "주소가 있는 것이 아니고 피연산자의 값 그 자체를 포함하고 있다고 하였으므로메모리 참조회수가 0인 이미 데이타(?) 방식인 즉시주소 지정(Immediate Addressing) 입니다."
            },{
                infoType: "정보처리 기능사",
                infoTime: "2009년 7월 12일 5회",
                infoNumber: "20090506",
                infoQuestion: "다음 그림의 논리회로에서 입력 A, B, C에 대한 출력 Y의 값은?<br><img src='asset/img/img01.jpg'>",
                infoChoice: ["Y = AB + B'C","Y = A + B + C", "Y = AB + BC", "Y = A'B + B'C",],
                infoAnswer: "Y = AB + B'C",
                infoDesc: "A*B =AB . B'*C =B'C , =AB + B'C"
            }
            ]

🏁. POINT

배열안에 총 6문제에 대한 정보를 작성하였습니다.

🏴. 

✈.  JAVASCRIPT : 선택자, 문제출력

        //선택자
        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 quizCnt = quizWrap.querySelector(".quiz__count");
        

        let quizCount = 0;
        let quizScore = 0;

        //quizTitle.innerHtml = quizInfo[0].infoType;
        //문제출력
        //function updateQuiz(){};
        
        const updateQuiz = (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 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>      
            `;

🏁. POINT

백틱을 이용하여 input태그를 그대로 적용하였고 객체리터럴 형태로 작성하였습니다.

 

 

🏴. 

✈. JAVASCRIPT

            let descTag = `
                정답은 ${quizInfo[index].infoAnswer}입니다<br>
                ${quizInfo[index].infoDesc}
            `;


            let countTag = `
                현재 총 ${quizInfo.length}문제 중 ${index+1}번째 문제 입니다.
            `;


            quizTitle.innerHTML = typeTag;
            quizQuestion.innerHTML = questionTag;
            quizChoice.innerHTML = choiceTag;
            quizDesc.innerHTML = descTag;
            quizCnt.innerHTML = countTag;

🏁. POINT

- descTag : 문제를 풀면 답과 해설이 나오게 합니다.

- countTag : 문제화면에 총문제 개수와 현재 몇 번째 문제인지 알려줍니다.

 

 

🏴. JAVASCRIPT

            //보기 선택자
            const quizChoiceSpan = quizWrap.querySelectorAll(".quiz__choice span");
            const quizChoiceInput = quizWrap.querySelectorAll(".quiz__choice input");
           
            // quizChoiceSpan.forEach((span, num) => {
            //     span.setAttribute("onclick", "choiceSelected(this)");//setAttribute:속성주기/ getAttribute:속성가져오기
            // });

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

            //다음버튼, 해설 숨기기
            quizAnswer.style.display = "none";
            quizDesc.style.display = "none";
            
        };
         updateQuiz(quizCount);
            //사용자정답
            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";



            }


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

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

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

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

            })

 

🏁. POINT

- 문제를 풀때 정답과 해설을 숨겼다가 문제를 풀면 보여주는 스크립트를 css제어를 통해 작성합니다.

 

- 사용자가 문제에 답을 클릭(체크)했을 때 사용자의 답과 정답이 같으면 정답페이지가 나오고

오답일 경우 오답페이지가 나오게 합니다.

 

 

🏴. JAVASCRIPT

문제를 다 풀었을  때 몇문제 맟췄는지, 몇점인지, 합격인지 불합격인지 알려주는 스크립트 입니다.

let countLast = Math.ceil((quizScore/quizInfo.length)*100);    
let countResult = (countLast > 60) ? "합격" : "불합격"    

            //마지막문제 일 때
            if(quizCount == quizInfo.length-1){
                quizAnswer.style.display = "none";
                quizCnt.innerHTML = "총"+ quizScore+"문제를 맞추었습니다.<br>점수는"+countLast+ "점 입니다.<br>"+countResult+"입니다."

                // if(countLast>60){
                //     quizCnt.innerHTML = "총"+ quizScore+"문제를 맞추었습니다.<br>점수는"+countLast+ "점 입니다. <br> 축하합니다."
                // }else{
                //     quizCnt.innerHTML = "총"+ quizScore+"문제를 맞추었습니다.<br>점수는"+countLast+ "점 입니다.."
                // }
                
                
            }

🏁. POINT

Math.ceil  = 소수점 올림

 

 

🏴. THIS 

var obj = {
  a: function() { console.log(this); },
};
obj.a(); // obj
객체 메서드 a 안의 this는 객체를 가리킵니다. 이것은 객체의 메서드를 호출할 때 this를 내부적으로 바꿔주기 때문에 그렇습니다.
var a2 = obj.a;
a2(); // window

호출할 때, 호출하는 함수가 객체의 메서드인지 그냥 함수인지가 중요합니다. a2는 obj.a를 꺼내온 것이기 때문에 더 이상 obj의 메서드가 아닙니다.

var obj2 = { c: 'd' };
function b() {
  console.log(this);
}
b(); // Window
b.bind(obj2).call(); // obj2
b.call(obj2); // obj2 
b.apply(obj2); // obj2

명시적으로 this를 바꾸는 함수 메서드 삼총사 bind, call, apply를 사용하면 this가 객체를 가리킵니다.

이제 마지막으로 생성자의 경우입니다. 

function Person(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.sayHi = function() {
  console.log(this.name, this.age);
}