Home > OS >  working on a javascript quiz app and having an issue dynamically generating questions/answers
working on a javascript quiz app and having an issue dynamically generating questions/answers

Time:06-12

I'm trying to dynamically generate questions and answers in a quiz game. The questions/answers are held in an array of objects and are supposed to be generated one after another inside of a div. When the user clicks on an answer, then the next question is generated. For now there are 5 questions and the problem is that after the first two questions are generated, the 3rd one gets skipped over, the 4th one is generated, and then the 5th gets skipped. When I submit an answer for the second question, it appears in the console that the 2nd and 3rd question were answered, even though the 3rd question never appeared on the page.

here is the javascript-

const questions = [
    {
        question: "Where was the first attempted allied invasion of France?",
        choices: ['Normandy', 'Nice', 'Dieppe', "Bourdeaux"],
        answer: "Dieppe"

    },

    {
        question: "Which American general was in charge of the pacific campaign?",
        choices: ["George Patton", "Omar Bradley", "George Marshall", "Douglas MacArthur"],
        answer: "Douglas MacArthur"
    },

    {
        question: "When was VE day?",
        choices: ["April", "May", "June", "July"],
        answer: "May"
    },

    {
        question: "Which of these was considered the largest tank battle in history?",
        choices: ["Battle of the Bulge", "D-Day", "Kursk", "Stalingrad", "Market Garden"],
        answer: "Kursk"
    },

    {
        question: "When did the war start?",
        choices: ["1939", "1938", "1941", "1944"],
        answer: "1939"
    }

]

let questionIndex = 0;



//function to start the game//
const startGame = () => {

    $('.start-btn').hide()
    $('.game-header').hide()
    $('.container').show();

    renderQuestion()

}



const renderQuestion = () => {

    $('#question').text(questions[questionIndex].question);
    $('#answer1').text(questions[questionIndex].choices[0])
    $('#answer2').text(questions[questionIndex].choices[1])
    $('#answer3').text(questions[questionIndex].choices[2])
    $('#answer4').text(questions[questionIndex].choices[3])



    $('.btn').click(function () {
        let response = $(this).text()
        console.log(response)
        checkAnswer(response)
    })


}





//function to set the timer


//function to end the quiz


//function to save high score




const checkAnswer = (response) => {


    if (response === questions[questionIndex].answer) {
        window.alert('CORRECT!')
    } else {
        window.alert('INCORRECT!')
    }

    

    questionIndex  
    console.log(questionIndex)

    renderQuestion()

}




$('.start-btn').click(startGame)

I believe the problem has to do with the "questionIndex" variable that I declared after the question array. At the bottom of the checkAnswer function, I have questionIndex which is supposed to cycle through all the questions, but I'm not sure what I'm getting wrong.

and here is the html-

<body>
    <div >
        Time left
    </div>
    <div >
        <h1>Welcome to the WWII trivia game!</h1>
        <h2>Answer all the questions before the time runs out and check your score in the end!</h2>
    </div>
    <button >Start!</button>
    <div >
        <div id="question-container" >
            <div id="question">""</div>
            <div >
                <button id='answer1' >Answer 1</button>
                <button id='answer2' >Answer 2</button>
                <button id='answer3' >Answer 3</button>
                <button id='answer4' >Answer 4</button>
            </div>
        </div>
        <div >
            <button id="start-btn" >Start</button>
            <button id="start-btn" >Next</button>
        </div>

    </div>

    <script src="script.js"></script>

</body>

So to conclude, I'm trying to cycle through all the questions and corresponding answers in the array so that they are generated one after another in the quiz game. as of now, the 3rd and 5th questions are being omitted. Appreciate any help :)

CodePudding user response:

I think one the problems was that you didn't check if your questionIndex was out of range (0-4). Also when you call your checkAnswer() function from your arrow function, you assign that arrow function to every element that has a btn class. So if you click the answer button, then click the next button, you increase the value of questionIndex two times. Maybe that was the issue.

Here is my solution for your question:

JS:

const start = document.getElementById('start');
const a1 = document.getElementById('answer1');
const a2 = document.getElementById('answer2');
const a3 = document.getElementById('answer3');
const a4 = document.getElementById('answer4');
const q = document.getElementById('question');

a1.onclick = handleRes;
a2.onclick = handleRes;
a3.onclick = handleRes;
a4.onclick = handleRes;

const questions = [
    {
        question: "Where was the first attempted allied invasion of France?",
        choices: ['Normandy', 'Nice', 'Dieppe', "Bourdeaux"],
        answer: "Dieppe"

    },

    {
        question: "Which American general was in charge of the pacific campaign?",
        choices: ["George Patton", "Omar Bradley", "George Marshall", "Douglas MacArthur"],
        answer: "Douglas MacArthur"
    },

    {
        question: "When was VE day?",
        choices: ["April", "May", "June", "July"],
        answer: "May"
    },

    {
        question: "Which of these was considered the largest tank battle in history?",
        choices: ["Battle of the Bulge", "D-Day", "Kursk", "Stalingrad", "Market Garden"],
        answer: "Kursk"
    },

    {
        question: "When did the war start?",
        choices: ["1939", "1938", "1941", "1944"],
        answer: "1939"
    }

]

let questionIndex = 0;

function handleRes(res){
    console.log(res.path[0].innerHTML);
    checkAnswer(res.path[0].innerHTML);
}



//function to start the game//
const startGame = () => {

    /*$('.start-btn').hide()
    $('.game-header').hide()
    $('.container').show();*/

    renderQuestion()

}



const renderQuestion = () => {

    /*$('#question').text(questions[questionIndex].question);
    $('#answer1').text(questions[questionIndex].choices[0])
    $('#answer2').text(questions[questionIndex].choices[1])
    $('#answer3').text(questions[questionIndex].choices[2])
    $('#answer4').text(questions[questionIndex].choices[3])*/

    q.innerHTML = questions[questionIndex].question;
    a1.innerHTML = questions[questionIndex].choices[0];
    a2.innerHTML = questions[questionIndex].choices[1];
    a3.innerHTML = questions[questionIndex].choices[2];
    a4.innerHTML = questions[questionIndex].choices[3];

    

    /*$('.btn').click(function () {
        let response = $(this).text()
        console.log(response)
        checkAnswer(response)
    })*/


}





//function to set the timer


//function to end the quiz


//function to save high score




const checkAnswer = (response) => {

    if (response === questions[questionIndex].answer) {
        window.alert('CORRECT!')
    } else {
        window.alert('INCORRECT!')
    }

    if(questionIndex == questions.length-1){
        return;
    }

    questionIndex  
    console.log(questionIndex)

    renderQuestion()
}

start.addEventListener('click', startGame);
//$('.start-btn').click(startGame);

Html:

<!DOCTYPE html>
<html lang="en">
<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">
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <title>Document</title>
</head>
<body>
    <div >
        Time left
    </div>
    <div >
        <h1>Welcome to the WWII trivia game!</h1>
        <h2>Answer all the questions before the time runs out and check your score in the end!</h2>
    </div>
    <button id="start" >Start!</button>
    <div >
        <div id="question-container" >
            <div id="question">""</div>
            <div >
                <button id='answer1' onclick="handleRes(this.innerHTML)" >Answer 1</button>
                <button id='answer2' onclick="handleRes(this.innerHTML)" >Answer 2</button>
                <button id='answer3' onclick="handleRes(this.innerHTML)" >Answer 3</button>
                <button id='answer4' onclick="handleRes(this.innerHTML)" >Answer 4</button>
            </div>
        </div>
        <div >
            <button id="start-btn" >Start</button>
            <button id="start-btn" >Next</button>
        </div>

    </div>

    <script src="script.js"></script>
</body>
</html>

CodePudding user response:

As mentioned in a comment, you should separate out the different tasks that you need to perform into their own functions. You catch mistakes in logic much, much faster amongst other benefits. If you increment the questionIndex each time someone tries an answer, you've got problems when they get the answer wrong. They'll need to hit the button more than once, which will change the questionIndex more than once.

Here's a version that works here on the page without jQuery.

"use strict";
function byId(id){return document.getElementById(id)}
function qsa(sel,par=document){return par.querySelectorAll(sel)}
function qs(sel,par=document){return par.querySelector(sel)}

var questionIndex;

window.addEventListener('load', onl oaded, false);

function onl oaded(evt)
{
    let ansBtns = qsa('.answers > .btn');
    ansBtns.forEach( btn => btn.addEventListener('click', onAnswerBtnClicked, false) );
    startGame();
}

function startGame()
{
    qs('.start-btn').style.display = 'none';
    qs('.game-header').style.display = 'none';
    qs('.container').style.display = '';
    questionIndex = 0;
    
    renderQuestion(questionIndex);
}

function renderQuestion(index)
{
    let curQ = questions[index];
    qs('#question').textContent = curQ.question;
    qs('#answer1').textContent = curQ.choices[0];
    qs('#answer2').textContent = curQ.choices[1];
    qs('#answer3').textContent = curQ.choices[2];
    qs('#answer4').textContent = curQ.choices[3];
}

function isAnswerCorrect(answer, questionIndex)
{
    let curQ = questions[questionIndex];
    if (answer == curQ.answer)
        return true;
    else
        return false;
}

function onAnswerBtnClicked(evt)
{
    let answer = this.textContent;
    if (isAnswerCorrect(answer, questionIndex))
    {
        alert('correct');
        if (questionIndex < 3)
        {
            questionIndex  ;
            renderQuestion(questionIndex);
        }
        
        // all questions dealt with.
        // quiz finished.
        else
        {
        }
    }
    else
        alert('incorrect');
}

const questions = [
    {
        question: "Where was the first attempted allied invasion of France?",
        choices: ['Normandy', 'Nice', 'Dieppe', "Bourdeaux"],
        answer: "Dieppe"
    },

    {
        question: "Which American general was in charge of the pacific campaign?",
        choices: ["George Patton", "Omar Bradley", "George Marshall", "Douglas MacArthur"],
        answer: "Douglas MacArthur"
    },

    {
        question: "When was VE day?",
        choices: ["April", "May", "June", "July"],
        answer: "May"
    },

    {
        question: "Which of these was considered the largest tank battle in history?",
        choices: ["Battle of the Bulge", "D-Day", "Kursk", "Stalingrad", "Market Garden"],
        answer: "Kursk"
    },

    {
        question: "When did the war start?",
        choices: ["1939", "1938", "1941", "1944"],
        answer: "1939"
    }
];
<body>
    <div >
        Time left
    </div>
    <div >
        <h1>Welcome to the WWII trivia game!</h1>
        <h2>Answer all the questions before the time runs out and check your score in the end!</h2>
    </div>
    <button >Start!</button>
    <div >
        <div id="question-container" >
            <div id="question">""</div>
            <div >
                <button id='answer1' >Answer 1</button>
                <button id='answer2' >Answer 2</button>
                <button id='answer3' >Answer 3</button>
                <button id='answer4' >Answer 4</button>
            </div>
        </div>
        <div >
            <button id="start-btn" >Start</button>
            <button id="start-btn" >Next</button>
        </div>
    </div>
</body>

  • Related