- 오늘은 퀴즈효과 6번째 입니다.
- 문제를 풀 때 마다 정답과 해설이 나오며 다음문제로 넘어가기를 누르면 다음문제가 나오는 형식입니다.
- 전체코드를 먼저 보고 스크립트 부분을 보겠습니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>퀴즈 이펙트05</title>
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/quiz.css">
<!-- //외부링크 -->
</head>
<body>
<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="qiuz__header">
<h2 class="quiz__title"></h2>
</div>
<div class="qiuz__main">
<div class="qiuz__question">
</div>
<div class="qiuz__view">
<div class="quiz__cnt"></div>
<div class="quiz__result"></div>
<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">
</div>
<div class="quiz__answer">
<button class="next">다음문제</button>
</div>
<div class="quiz__desc"></div>
</div>
</div>
<!-- // 1번 문제 -->
</div>
</main>
<!-- //main -->
<footer id="footer">
<a href="mailto:im.kebab00@gmail.com">im.kebab00@gmail.com</a>
</footer>
<!-- //footer -->
<script>
// 문제 정보
const quizInfo = [
{
infoType : "정보처리 기능사" ,
infoTime : "2011년 4회" ,
infoNumber : "20110401",
infoQuestion : "일반적으로 명령어의 패치 사이클 중에는 현재 수행하고 있는 명령어의 위치를 가리키고, 실행 사이클 중에는 바로 다음에 실행할 명령어의 위치를 가리키는 Register는?",
infoChoice : ["누산기(accumulator)", "프로그램 카운터(program counter)", "명령어 레지스터(instruction register)", "범용 레지스터(general purpose register)"],
infoAnswer: "프로그램 카운터(program counter)",
infoDesc : "누산기(accumulator) : 연산결과 일시 저장<br>프로그램 카운터(program counter) : 다음 수행 명령번지 기억<br>명령어 레지스터(instruction register) : 현재수행중인 명령어를 일시저장"
},{
infoType : "정보처리 기능사" ,
infoTime : "2011년 4회" ,
infoNumber : "20110402",
infoQuestion : "스택 연산에서 데이터를 삽입하거나 삭제하는 동작을 나타내는 것은?",
infoChoice : ["ADD, SUB", "LOAD, STORE", "PUSH, POP", "MOV, MUL"],
infoAnswer: "PUSH, POP",
infoDesc : "PUSH : 데이터 삽입<br>POP : 데이터 꺼내기(삭제)",
},{
infoType : "정보처리 기능사" ,
infoTime : "2011년 4회" ,
infoNumber : "20110403",
infoQuestion : "다음 중 제어장치에서 명령어의 실행 사이클에 해당하지 않는 것은?",
infoChoice : ["인출 주기(fetch cycle)", "직접 주기(direct cycle)", "간접 주기(indirect cycle)", "실행 주기(execute cycle)"],
infoAnswer: "직접 주기(direct cycle)",
infoDesc : "제어장치의 명령어 실행 사이클은 기계주기(Machine Cycle)라 하며, 다음과 같다..<br> ① 인출사이클(Fetch Cycle) - 중앙처리장치가 기억장치에서 다음에 실행할 명령을 가져오는 주기)<br>② 명령사이클(Instruction Cycle) - 기억장치의 번지를 확인하여 명령을 읽어 낼 때까지의 단계<br>③ 실행사이클(Execution Cycle) - 명령에 따라 필요한 신호를 만들어 결과를 얻을 때까지의단계",
},{
infoType : "정보처리 기능사" ,
infoTime : "2011년 4회" ,
infoNumber : "20110404",
infoQuestion : "전가산기(Full Adder)는 어떤 회로로 구성되는가?",
infoChoice : ["반가산기 1개와 OR 게이트로 구성된다.", "반가산기 1개와 AND 게이트로 구성된다.", "반가산기 2개와 OR 게이트로 구성된다.", "반가산기 2개와 AND 게이트로 구성된다."],
infoAnswer: "반가산기 2개와 OR 게이트로 구성된다.",
infoDesc : "전가산기 구성 : 반가산기 2개와 OR 게이트로 구성된다.",
},{
infoType : "정보처리 기능사" ,
infoTime : "2011년 4회" ,
infoNumber : "20110405",
infoQuestion : "CISC(Complex Instruction Set Computer)의 특징으로 틀린 것은?",
infoChoice : ["많은 수의 명령어", "다양한 주소지정 방식", "가변 길이 명령어 형식", "단일 사이클의 명령어 실행"],
infoAnswer: "단일 사이클의 명령어 실행",
infoDesc : "단일 사이클의 명령어 실행은 RISC방식입니다. <br>CISC 방식은 다양한 길이의 가변 사이클을 지원 합니다.",
},{
infoType : "정보처리 기능사" ,
infoTime : "2011년 4회" ,
infoNumber : "20110406",
infoQuestion : "EBCDIC 코드는 몇개의 Zone bit를 갖는가?",
infoChoice : ["1", "2", "3", "4"],
infoAnswer: "4",
infoDesc : "총 코드비트<br>BCD 코드(6)<br>ASCII 코드(7)<br>EBCDIC 코드(8)<br>모든 코드의 디지트 비트는 4임<br>따라서 각 코드의 존비트는 코드총비트 - 4 입니다. 즉 8-4 = 4 입니다<br>",
},{
infoType : "수고하셨습니다" ,
infoTime : " " ,
infoNumber : "20110407",
infoQuestion : " ",
infoChoice : [" ", " ", " ", " "],
infoAnswer: " ",
infoDesc : " ",
}
]
// 선택자
const quizWrap = document.querySelector(".quiz__wrap");
const quizTitle = quizWrap.querySelector(".quiz__title");
const quizChoice = quizWrap.querySelector(".quiz__choice");
const quizQuestion = quizWrap.querySelector(".qiuz__question");
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 quizLength = quizWrap.querySelector(".quiz__length");
const quizCnt = quizWrap.querySelector(".quiz__cnt");
const quizResult = quizWrap.querySelector(".quiz__result");
let quizCount = 0;
let quizScore = 0;
// 문제 출력
updateQuiz = (index) => {
let typeTag = `
<span>${quizInfo[index].infoType}</span>
<em>${quizInfo[index].infoTime}</em>
`;
const 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} 입니다.</br>
${quizInfo[index].infoDesc}
`
let cntTag = `
남은 문제는 ${quizInfo.length-quizCount-1}개 입니다
`
let ResultTag = `
<span>점수는 ${Math.ceil((quizScore / (quizInfo.length-1)) * 100)}점 입니다.<br>
맞은 문제는 ${quizScore}개고 <br> 틀린문제는 ${quizInfo.length-quizScore-1} 개 입니다.</span>
`
quizResult.innerHTML = ResultTag;
quizCnt.innerHTML = cntTag;
quizTitle.innerHTML = typeTag;
quizQuestion.innerHTML = questionTag;
quizChoice.innerHTML = choiceTag;
quizDesc.innerHTML = descTag;
// 보기 선택자
const quizChoiceSpan = quizWrap.querySelectorAll(".quiz__choice span");
const quizInput = 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)");
// quizInput[i].disabled = "true"
}
if(quizCount+1==quizInfo.length){
dogWrap.style.display = "none";
quizResult.style.display = "block";
quizCnt.style.display = "none";
quizChoice.style.display = "none";
quizQuestion.style.display = "none";
}
};
// 다음숨기기, 해설 숨기기
quizAnswer.style.display = "none";
quizDesc.style.display = "none";
quizResult.style.display = "none";
//
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";
}
updateQuiz(quizCount);
// 정답확인
quizNext.addEventListener("click", () => {
dogWrap.classList.remove("like" ,"dislike")
quizAnswer.style.display = "none";
quizDesc.style.display = "none";
quizCount++;
updateQuiz(quizCount);
})
</script>
</body>
</html>
- 크게 달라진 부분은 많이 없습니다. 정답확인 부분이 다음문제 버튼으로 바뀐 정도가 있겠네요
- 큰 틀은 main안에 넣어두고 그외 안에 들어가는 부분은 innnerHTML를 통해서 넣어주었습니다.
- 스크립트를 보시죠
<script>
// 선택자
const quizWrap = document.querySelector(".quiz__wrap");
const quizTitle = quizWrap.querySelector(".quiz__title");
const quizChoice = quizWrap.querySelector(".quiz__choice");
const quizQuestion = quizWrap.querySelector(".qiuz__question");
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 quizLength = quizWrap.querySelector(".quiz__length");
const quizCnt = quizWrap.querySelector(".quiz__cnt");
const quizResult = quizWrap.querySelector(".quiz__result");
let quizCount = 0;
let quizScore = 0;
// 문제 출력
updateQuiz = (index) => {
let typeTag = `
<span>${quizInfo[index].infoType}</span>
<em>${quizInfo[index].infoTime}</em>
`;
const 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} 입니다.</br>
${quizInfo[index].infoDesc}
`
let cntTag = `
남은 문제는 ${quizInfo.length-quizCount-1}개 입니다
`
let ResultTag = `
<span>점수는 ${Math.ceil((quizScore / (quizInfo.length-1)) * 100)}점 입니다.<br>
맞은 문제는 ${quizScore}개고 <br> 틀린문제는 ${quizInfo.length-quizScore-1} 개 입니다.</span>
`
quizResult.innerHTML = ResultTag;
quizCnt.innerHTML = cntTag;
quizTitle.innerHTML = typeTag;
quizQuestion.innerHTML = questionTag;
quizChoice.innerHTML = choiceTag;
quizDesc.innerHTML = descTag;
// 보기 선택자
const quizChoiceSpan = quizWrap.querySelectorAll(".quiz__choice span");
const quizInput = 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)");
// quizInput[i].disabled = "true"
}
if(quizCount+1==quizInfo.length){
dogWrap.style.display = "none";
quizResult.style.display = "block";
quizCnt.style.display = "none";
quizChoice.style.display = "none";
quizQuestion.style.display = "none";
}
};
// 다음숨기기, 해설 숨기기
quizAnswer.style.display = "none";
quizDesc.style.display = "none";
quizResult.style.display = "none";
//
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";
}
updateQuiz(quizCount);
// 정답확인
quizNext.addEventListener("click", () => {
dogWrap.classList.remove("like" ,"dislike")
quizAnswer.style.display = "none";
quizDesc.style.display = "none";
quizCount++;
updateQuiz(quizCount);
})
</script>
- 저번처럼 배열안에 객체를 넣어 문제 정보를 저장하였습니다.
- 그건 쉬운니까 생략하겠습니다.
- 문제를 출력하는데 저번과 차이가 있습니다.
- 저번에는 모든 태그를 반복문에 넣고 돌려서 출력하였다면 이번에는 내용부분만 따로 반복문을 사용하여 내용을 바뀌어주었습니다.
- 그리고 보기의 버튼을 눌렀을 때 바로 정답을 확인하고 다음문제를 클릭 했을 때 다음 문제로 넘어가는 것 입니다.
// 사용자가 선택한 정답을 속성 값으로 불러오기
for(let i=0; i<quizChoiceSpan.length; i++){
quizChoiceSpan[i].setAttribute("onclick", "choiceSelected(this)");
}
// 정답확인
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";
}
updateQuiz(quizCount);
// 다음문제
quizNext.addEventListener("click", () => {
dogWrap.classList.remove("like" ,"dislike")
quizAnswer.style.display = "none";
quizDesc.style.display = "none";
quizCount++;
updateQuiz(quizCount);
})
- setAttribute를 사용해서 사용자가 선택한 보기를 해당문제의 속성 값으로 가져오고 onclick, choiceSelected(this)를 클릭되었을 때 함수 choiceSelected의 매개변수로 넣어주었습니다.
- 그것을 변수 userAnswer 안에 저장을 해주고 currentAnswer안에 정답을 저장해주었습니다.
- 그리고 그 둘을 비교하는 if 문을 써주면 정답확인하는 부분은 끝이납니다.
- 그리고 다음문제를 클릭하였을 때 정답과 해설을 다시 가려주고 몇문제 남았는지 계산할 때 사용할 quizCount를 1씩 더해주면 다음문제까지는 끝이 납니다.
// 남은 문제갯수와 마지막에 점수표시
let cntTag = `
남은 문제는 ${quizInfo.length-quizCount-1}개 입니다
`
let ResultTag = `
<span>점수는 ${Math.ceil((quizScore / (quizInfo.length-1)) * 100)}점 입니다.<br>
맞은 문제는 ${quizScore}개고 <br> 틀린문제는 ${quizInfo.length-quizScore-1} 개 입니다.</span>
// 마지막 문제일 때
if(quizCount==quizInfo.length-1){
dogWrap.style.display = "none";
quizResult.style.display = "block";
quizCnt.style.display = "none";
quizChoice.style.display = "none";
quizQuestion.style.display = "none";
}
- 퀴즈를 풀 때 마다 남은 문제가 몇개인지 알려주는 문구를 만들어주었습니다.
- 마지막 문제일 때 다음문제가 없는데 문제를 받아오려고 하는 버그가 있기 때문에 저는 하나의 객체를 추가해서 내용이 없는 빈 껍데기를 하나 만들었습니다. 그렇기 때문에 남은 문제를 알려고 할 때 quizInfo.length-quizCount이 아닌 quizInfo.length-quizCount-1를 사용해서 숫자를 맞춰주었습니다.
- 이후에 들어가는 모든 quizInfo.length에도 1씩 빼주었습니다.
- 그리고 숫자를 올림하여 정수로 바꾸어 주는 Math.ceil를 통해 점수를 계산해 주었습니다 {Math.ceil((quizScore / (quizInfo.length-1)) * 100)}
- 그리고 if문을 통해 quizInfo.length-1 과 quizCount가 같아질 때 필요없는 나머지 창들을 없애고 점수와 맞춘문제의 갯수, 틀린 문제의 갯만 띄워주었습니다.
- 끝!!