Question game skips questions the second time around
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Question game skips questions the second time around
Hello,
This is from the book Javascript: Novice To Ninja. The game works correctly the first time around (3 questions) but will skip questions in subsequent games. I think it has something to do with the event listener or maybe "this". I've tried enough times to solve this... Here's the code:
(function () {
"use strict";
// DOM references
var $question = document.getElementById('question');
var $score = document.getElementById('score');
var $feedback = document.getElementById('feedback');
var $start = document.getElementById('start');
var $form = document.getElementById('answer');
var $timer = document.getElementById('timer');
// View functions
function update(element,content,klass) {
var p = element.firstChild || document.createElement('p');
p.textContent = content;
element.appendChild(p);
if (klass) {
p.className = klass;
}
}
// Event listeners
$start.addEventListener('click',function() {
new Game(quiz);
},false);
var quiz = {
"name": "Super Hero Name Quiz",
"description": "How many super heroes can you name?",
"question": "What is the real name of ",
"questions": [
{"question": "Superman", "answer": "Clarke Kent", "asked": "false"},
{"question": "Wonder Woman", "answer": "Dianna Prince", "asked": "false"},
{"question": "Batman", "answer": "Bruce Wayne", "asked": "false"}
]
};
function hide(element) {
element.style.display = 'none';
}
function show(element) {
element.style.display = 'block';
}
// Hide the form at the start of the game
hide($form);
var score = 0; // Initialize score
function random(a,b,callback) {
if (b === undefined) {
// If only one argument is supplied, assume the lower limit is 1
b = a, a = 1;
}
var result = Math.floor((b - a + 1) * Math.random()) + a;
if (typeof callback === 'function') {
result = callback(result);
}
return result;
}
// Method definitions
Game.prototype.chooseQuestion = function() {
console.log("chooseQuestion() called");
var questions = this.questions.filter(function(question) {
return question.asked === "false";
});
// Added by gacl
if (questions == false) {
return this.gameOver();
}
// Set the current question
this.question = questions[random(questions.length) - 1];
this.ask(this.question);
}
Game.prototype.ask = function(question) {
console.log("ask() called");
var quiz = this;
// Set the question.asked property to true so it's not asked again
question.asked = true;
update($question,this.phrase + question.question + "?");
// Clear the previous options
$form.innerHTML = "";
// Create an array to put the different options in and a button variable
var options = [], button;
var option1 = chooseOption();
options.push(option1.answer);
var option2 = chooseOption();
options.push(option2.answer);
// Add the actual answer at a random place in the options array
options.splice(random(0,2),0,this.question.answer);
// Loop through each option and display it as a button
options.forEach(function(name) {
button = document.createElement("button");
button.value = name;
button.textContent = name;
$form.appendChild(button);
});
// Choose and option from all the possible answers but without choosing the answer or the same option twice
function chooseOption() {
var option = quiz.questions[random(quiz.questions.length) - 1];
// Check to see if the option chosen is the current question or already one of the options, if it is then recursively call this function until it isn't
if (option === question || options.indexOf(option.answer) !== -1) {
return chooseOption();
}
return option;
}
}
Game.prototype.check = function(answer) {
console.log("check() called");
if (answer === this.question.answer) {
update($feedback,"Correct!","right");
// Increase score by 1
this.score++;
update($score,this.score);
} else {
update($feedback,"Wrong!","wrong");
}
this.chooseQuestion();
}
Game.prototype.countDown = function() {
// This is called every second and decreases the time
// Decrease time by 1
this.time--;
// Update the time displayed
update($timer,this.time);
// The game is over if the timer has reached 0
if (this.time <= 0) {
this.gameOver();
}
}
Game.prototype.gameOver = function() {
console.log("gameOver() invoked");
// Inform the player that the game has finished and tell them how many points they have scored
update($question,"Game over. You scored " + this.score + " points");
// Stop the countdown interval
window.clearInterval(this.interval);
hide($form);
show($start);
}
function Game(quiz) {
this.questions = quiz.questions;
// Added by gacl
for (let question of this.questions) {
question.asked = "false";
}
this.phrase = quiz.question;
this.score = 0; // Initialize score
update($score,this.score);
// Initialize timer and set up an interval that counts down
this.time = 20;
update($timer,this.time);
this.interval = window.setInterval(this.countDown.bind(this),1000);
// Hide button and show form
hide($start);
show($form);
// Add event listener to form for when it's submitted
$form.addEventListener('click', function(event) {
event.preventDefault();
this.check(event.target.value);
}.bind(this),false);
this.chooseQuestion();
}
} ())
There's a CSS file but I don't think we need it here. Thanks!
Hello,
I've tried enough times to solve this... Here's the code:
There is no magic number of tries I am aware of which passes responsibility for debugging your code to others, and you do not say what you consider to be enough times, so we are kind of in the dark here!
It would also be helpful to others willing to offer assistance if you would explain what you have done to try to resolve the problem and what you found out in the process, including any error messages that may have been passed to the debug console.
Please review the Site FAQ for guidance in posting your questions and general forum usage. Especially, read the link in that page, How To Ask Questions The Smart Way. The more effort you put into understanding your problem and framing your questions, the better others can help!
The JavaScript only has three questions. It also contains code to use each question only once.
So, once they have all been displayed, there are no more questions to ask.
It’s doing what it’s coded to do. (As programs always do)
Note that I made the above determinations by only reading the comments...not by analyzing the code. It is, of course, possible that the code doesn’t do what the comments say. Been there, done that.
If you want to play it again, you’ll need to reload the web page, or add code to reset the use each question once flags. The latter would be a good learning experience.
Does your book not offer suggestions for debugging code? I like to use alert() to output variables I want to inspect, but they can also be output to the web page.
Does you browser offer a debugging console? The current Firefox does.
That said, I second what astrogeek posted. As you’re doing this to learn, you need to tell what you’ve tried and what result you got.
If the code is taken directly from the book, then you should be aware that it's both outdated and bad.
For example, it has "var" statements in the middle of code blocks. These should always be at the beginning, because the interpreter actually moves them up there. If you want to declare variables mid-block, then you use "let", which isn't subjected to hoisting.
Sorry, I did try to debug it with the console (Chromium). No errors. The steps to reproduce the issue are:
1. Click on the button "Click to play Quiz Ninja"
2. Answer question 1
3. Answer question 2
4. Answer question 3
5. Do not reload the page. Instead click on the button "Click to play Quiz Ninja"
6. Attempt to answer all three questions again (It's supposed to ask the same three questions). You will not succeed because the game will only ask you two questions before going to "Game over".
7. If you keep playing (without reloading) it will ask only one question from then on.
At this point when I use the debugger I can see that after the first question is asked it goes back to the event listener but does not wait for user input. Instead it keeps going through the question/answer cycle by itself. I think that this is the problem, that the event listener for the form stops listening. What could cause it to stop listening?
Make sure to reset the game state to the initial, clean slate properly at the end of the game.
I'm not too knowledgable with javascript, but maybe the fault is somewhere where "questions" was used with "this." and without "this."
Aka, some sort of scope error which is valid code (aka not a syntax error or anything), but just a messup by the programmer.
Edit:
By the way, this program seems kinda awful all around.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.