JAVASCRIPT

퀴즈 이펙트 만들기 5

hyejeong3283 2023. 3. 25. 11:23
728x90
반응형

이전 퀴즈 이펙트 만들기 4에 이어서 문제 정보를 추가하여 정보처리기능사 60문제를 만들어 보았습니다.

 

HTML

<!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>퀴즈 이펙트0</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 class="active"><a href="quizEffect05.html">5</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="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>
        <div class="quiz__modal">
            <div class="modal">
                <h3>[축하합니다] or [다시 공부하세요]!</h3>
                <p>총 몇 [60]문제 중에 [10]문제 맞췄습니다.</p>
                <p>[40]점입니다. 공부하세요!</p>
            </div>
        </div>
    </main>
    <!-- //main -->

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

    <script>
        // 문제 정보
        const quizInfo = [
            {
                infoType: "정보처리 기능사",
                infoTime: "2005년 5회",
                infoNumber: "20050501",
                infoQuestion: "ROM(Read Only Memory)에 대한 옳은 설명은?",
                infoChoice: {
                    1: "데이터를 읽는 것만 가능하다.",
                    2: "데이터를 읽고 기록하는 것 모두 가능하다.",
                    3: "데이터를 기록하는 것만 가능하다.",
                    4: "데이터를 읽고 기록하는 것 모두 불가능하다."
                },
                infoAnswer: "1",
                infoDesc: "ROM(Read Only Memory) 이란 읽기 전용 메모리란 뜻으로 읽는것만 가능합니다."
            },{
                infoType: "정보처리 기능사",
                infoTime: "2005년 5회",
                infoNumber: "20050502",
                infoQuestion: "중앙처리기의 제어 부분에 의해서 해독되어 현재 실행중인 명령어를 기억하는 레지스터는?",
                infoChoice: {
                    1: "PC(Program Counter)",
                    2: "IR(Instruction Register)",
                    3: "MAR(Memory Address Register)",
                    4: "MBR(Memory Buffer Register)"
                },
                infoAnswer: "2",
                infoDesc: "IR(Instruction Register)은 현재 수행중인 명령어를 기억하고 있으며 다음 수행 명령 번지는 PC(Program Counter)에 기록됩니다. "
            },{
                infoType: "정보처리 기능사",
                infoTime: "2005년 5회",
                infoNumber: "20050503",
                infoQuestion: "모든 입력이 1일 때만 출력이 1이 되고, 입력이 하나라도 0이면 출력은 0이 되는 게이트(Gate)는?",
                infoChoice: {
                    1: "OR",
                    2: "NOT",
                    3: "NAND",
                    4: "AND"
                },
                infoAnswer: "4",
                infoDesc: "모든 입력이 1이이여 1이 출력된다는 말은 둘다 참이어야 참이므로 AND 입니다."
            },{
                infoType: "정보처리 기능사",
                infoTime: "2005년 5회",
                infoNumber: "20050504",
                infoQuestion: "8비트 짜리 레지스터 A와 B에 각각 “11010101”과 “11110000”이 들어 있다. 레지스터 A의 내용이 “00100101”로 바뀌었다면 두 레지스터 A, B사이에 수행된 논리 연산은?",
                infoChoice: {
                    1: "Exclusive-OR 연산",
                    2: "AND 연산",
                    3: "OR 연산",
                    4: "NOR 연산"
                },
                infoAnswer: "1",
                infoDesc: "11010101와 11110000를 연산하였을때 00100101이므로 1+1 =0 0+1 = 1 1+0= 1 0+0=0 이므로 Exckysive-OR 연산이다"
            },{
                infoType: "정보처리 기능사",
                infoTime: "2005년 5회",
                infoNumber: "20050505",
                infoQuestion: "하나의 레지스터에 기억된 자료를 모두 다른 레지스터로 옮길 때 사용하는 논리 연산은?",
                infoChoice: {
                    1: "Rotate",
                    2: "Shift",
                    3: "Move",
                    4: "Complement"
                },
                infoAnswer: "3",
                infoDesc: "한자리씩 이동이라면 Rotate 또는 shift 이지만 전체를 다른곳으로 이동한다고 하였으므로 Move 입니다."
            },{
                infoType: "정보처리 기능사",
                infoTime: "2005년 5회",
                infoNumber: "20050506",
                infoQuestion: "명령어 내의 오퍼랜드가 지정한 곳에 실제 데이터 값이 기억된 장소를 지정하는 방식으로, 피 연산자를 구하기 위하여 두 번의 기억장소 접근을 해야 하는 방식은?",
                infoChoice: {
                    1: "직접주소",
                    2: "간접주소",
                    3: "기본주소",
                    4: "상대주소"
                },
                infoAnswer: "2",
                infoDesc: "간접주소 : 메모리 참조 2회 입니다..문제에서 두번의 기억장소 접근을 해야 한다고 했으므로 간접주소 방식 입니다."
            },{
                infoType: "정보처리 기능사",
                infoTime: "2005년 5회",
                infoNumber: "20050507",
                infoQuestion: "원격지에 설치된 입·출력장치를 무엇이라 하는가?",
                infoChoice: {
                    1: "변·복조장치(MODEM)",
                    2: "콘솔(Console)",
                    3: "단말장치",
                    4: "X-Y 플로터"
                },
                infoAnswer: "3",
                infoDesc: "단말장치 : 원격지에 설치된 입출력장치"
            },{
                infoType: "정보처리 기능사",
                infoTime: "2005년 5회",
                infoNumber: "20050508",
                infoQuestion: "진리표가 다음 표와 같이 되는 논리회로는?<br><img style='width:300px', src=../assets/img/quiz05_08.png>",
                infoChoice: {
                    1: "AND 게이트",
                    2: "OR 게이트",
                    3: "NOR 게이트",
                    4: "NAND 게이트"
                },
                infoAnswer: "4",
                infoDesc: "척보고 알수 있는 진리표가 아니므로 반대로 생각해 봅니다.. 입력이 1,1일때 1이 나온다면 AND 이므로 이와 반대로 나오기 때문에 NAND 입니다."
            },{
                infoType: "정보처리 기능사",
                infoTime: "2005년 5회",
                infoNumber: "20050509",
                infoQuestion: "JK 플립플롭(Flip-flop)에서 보수가 출력되기 위한 입력값 J, K의 입력 상태는?",
                infoChoice: {
                    1: "J=1, K=0",
                    2: "J=0, K=1",
                    3: "J=1, K=1",
                    4: "J=0, K=0"
                },
                infoAnswer: "3",
                infoDesc: "JK 플리플롭에서 J=1, K=1 입력되면 보수가 출력됩니다..T플리플롭과 동일하게 작동하며 이러한 특성으로 인하여 JK 플리플롭을 만능 플리플롭이라고도 합니다."
            },{
                infoType: "정보처리 기능사",
                infoTime: "2005년 5회",
                infoNumber: "20050510",
                infoQuestion: "명령어(Instruction) 형식에서 첫 번째 바이트의 기능이 아닌 것은?",
                infoChoice: {
                    1: "자료의 주소 지정 기능",
                    2: "제어 기능",
                    3: "자료 전달 기능",
                    4: "함수 연산 기능"
                },
                infoAnswer: "1",
                infoDesc: "명령어는 명령어코드부 + 명령어 주소부로 구성됩니다..첫번째 바이트 이므로 명령에 코드에 관한 이야기 입니다..주소 지정과는 관계가 없습니다."
            }
        ];

        // 선택자
        const quizWrap = document.querySelector(".quiz__wrap");
        let quizScore = 0;

        // 문제 출력
        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");

        }
        updateQuiz();
        // 정답 확인
        const answerQuiz = () => {
            const quizChoices = document.querySelectorAll(".quiz__choice");
            //사용자가 체크한 정답 == 문제 정답
            quizInfo.forEach((question, number) => {
                const userSelector = `input[name=choice${number}]:checked`;
                const quizSelectorWrap = quizChoices[number];
                const userAnswer = (quizSelectorWrap.querySelector(userSelector) || {}).value;
                const dogWrap = quizWrap.querySelectorAll(".dog__wrap");
                if(userAnswer == question.infoAnswer){
                    console.log("정답");
                    dogWrap[number].classList.add("like");
                    quizScore++;
                } else {
                    console.log("오답");
                    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>
</body>
</html>

정리

quiz_chioce라는 클래스명을 가진 태그 영역을 만듭니다.
그 안에 객관식 답안을 넣을 4개의 버튼 유형의 태그를 넣었습니다.

<input type="radio">
radio 유형의 <input> 요소는 보통 서로 관련된 옵션을 나타내는 라디오 버튼 콜렉션, 라디오 그룹에 사용합니다. 
임의의 그룹 내에서는 동시에 하나의 라디오 버튼만 선택할 수 있습니다. 
라디오 버튼은 흔히 원형으로 그려지며, 선택한 경우 속을 채우거나 강조 표시를 합니다.

 

60개의 정답을 한번에 확인할 수 있도록 정답확인 버튼과 점수가 나오는 영역을 push메서드를 이용해 넣었습니다.

 exam.push(`
    <div class="quiz__info">??점</div>
    <div class="quiz__check">정답 확인!</div>
`);
quizWrap.innerHTML = exam.join("");

"push()" 메소드는 배열의 끝에 새로운 요소를 추가하는 데 사용됩니다.

 

"join()" 메소드는 배열의 모든 요소를 하나의 문자열로 결합할 때 사용됩니다.

인수로 전달된 문자열은 각 요소 사이에 삽입됩니다.

인수를 전달하지 않으면 기본값인 쉼표로 구분된 문자열이 사용됩니다.

 

CSS 추가

.quiz__check {
    position: fixed;
    right: 20px;
    bottom: 20px;
    width: 130px;
    height: 130px;
    line-height: 130px;
    border-radius: 50%;
    z-index: 1000;
    text-align: center;
    background: #ca54c2;
    color: #fff;
    font-family: 'Hallym';
    cursor: pointer;
}
.quiz__info {
    position: fixed;
    right: 20px;
    bottom: 170px;
    background-color: #ff3c3c;
    text-align: center;
    width: 130px;
    height: 50px;
    line-height: 50px;
    border-radius: 10px;
    font-family: 'Hallym';
    color: #fff;
}
.quiz__info::after {
    content: '';
    position: absolute;
    left: 50%;
    margin-left: -10px;
    bottom: -10px;
    border-top: 10px solid #ff3c3c;
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
}

속성 정리

border-top: 10px solid #ff3c3c;
border-left: 10px solid transparent;
border-right: 10px solid transparent;

 

CSS 스타일 속성 중 하나로, 테두리의 스타일을 지정하는 것입니다.

이 속성은 "border-width", "border-style", "border-color" 세 가지 속성을 한 줄에 표기하는 단축 속성입니다.

여기서 "10px"는 왼쪽 테두리의 두께를 나타내며,

"solid"는 왼쪽 테두리의 스타일을 나타내는 것이고,

"transparent"는 왼쪽 테두리의 색상을 투명하게 만드는 것입니다.

 

따라서 이 코드를 사용하면 요소의 왼쪽 테두리는 10픽셀 두께의 실선이며, 색상은 완전히 투명하게 됩니다.

 

완성된 퀴즈 이펙트5 페이지