I've been having some fun revamping some old code for a quiz I made some years ago. Essentially, it's just HTML and Javascript.
The thing is that the code is quite the mess (hey, it was a lot of years ago I wrote that). To understand this, let's review what the code needs and how it works, and finally get to how to improve this.
Essentially, the quiz works by having 40 questions, and randomly selecting a question each time the user answers one.
Now, here is the tricky part. Some questions depend on others being answered correctly. So this added some extra complexity because a) we have to know when it is possible to randomly select a question that depends on another question (being answered correctly) and b) we must know when the user has answered all available questions (if the user incorrectly answers a question which have dependent questions, they should be marked as failed).
This was very messy implemented (and I don't really know if it actually works reliably).
I used an array that kept track of which questions had been answered. Questions that were off-limit were marked as "answered," so that the quiz wouldn't randomly select them when the prerequisite questions had not yet been answered.
When a question was answered, a hard-coded check was made to see if answering that question opened up other questions, and if so, it marked those questions as not answered.
But this approach is horrible since is requires modification in at least two places when adding new questions to the quiz or modifying questions.
Furthermore, it doesn't actually take into consideration one of the requirements.
I want to fix this. I am revamping the code in preparation for changing questions and adding new questions. The problem is how the new code should be structured to meet the requirements.
So on to the requirements I have in mind:
- I want to be able to add and modify questions in one place easily, without having to modify several places.
- It should be easy, so that I don't forget to add valuable information.
- The code must be able to handle that some questions require that other questions have been answered correctly before. That is to say, the code must not randomly pick such questions until all prerequisite questions have been answered correctly.
- If all prerequisite questions for a specific question have been answered, but at least one prerequisite question incorrectly answered, then all the questions that depend on that prerequisite question being answered correctly must be marked as answered incorrect.
- It must know when all accessible questions have been answered so it knows when the quiz has ended.
I have experimented with a small approach, which is not good enough yet. But what I have in mind so far is something like one big array containing all necessary questions and information regarding those at the beginning, like so:
Code:
var Questions =
[
{ // 34
title: "Varför gick Aleria med i klan 3?",
requirements: [ 33 ],
answered: false,
correct_answer: false,
answer: 12,
answers:
[
"Gillar att spionera",
"Gillar att lönnmörda",
"Blev tvingad",
"Gillar att spionera och lönnmörda",
"Blev tillbedd av Svarta Blomman",
"Blev tillbedd av någon annan",
"För att söka rätt på hot mot sig själv",
"För att söka rätt på och utrota hot mot sig själv",
"För att söka rätt på hot mot andra",
"För att söka rätt på och utrota hot mot andra",
"För att söka rätt på hot mot Svarta Blomman",
"För att söka rätt på och utrota hot mot Svarta Blomman"
]
},
...
];
Information so far would be the title of the question, what prerequisite questions there are, if it has been answered (and correctly answered), the correct answer and the answer options.
As for picking a question to show, I use this:
Code:
for (;;)
{
var rnd = Math.floor(Math.random() * max_q);
if (rnd >= max_q)
continue;
var _q = Questions[rnd];
if (_q.answered)
continue;
var cont = true;
for (var i = 0; i < _q.requirements.length; i++)
{
if (!Questions[_q.requirements[i]].correct_answer)
{
cont = false;
break;
}
}
if (!cont)
continue;
q = rnd;
var html = "<h1>Fråga nr " + num_q + "!</h1>" + _q.title + "<hr/><br/>";
for (var i = 0; i < _q.answers.length; i++)
html += (i + 1) + ") <a href='javascript:Answer(" + (i + 1) + ");'>" + _q.answers[i] + "</a><br/>";
document.getElementById("main").innerHTML = html;
break;
}
This is fine. This works, and it's clean.
These code snippets take care of requirements 1, 2 and 3. Whether it could be done better is arguable, and I'm open to suggestions.
But I need a good way to implement requirements 4 & 5. So that's where I'm looking for suggestions.
So, thanks for not getting bored reading through this long post, and I hope someone can offer any good ideas.