Question

I have a function that gets questions from an array called quizQuestions, displays the choosed question, splice it from the array and pushes the question and correct answer to a new array to be used later in the results screen:

// The questions are stored in an array called "quizQuestions"
function makeQuestion()
    var randNum:Number = Math.round(1 + (quizQuestions.length - 1) * Math.random());
    mc_quiz.question.text = quizQuestions[randNum][0];
    answer = quizQuestions[randNum][1];
    quizQuestions.splice(randNum,1);    
    printQuestions.push(new Array(mc_quiz.question.text, answer));
}

It runs fine but time to time, a question is asked twice. You can continue with the test but the result doesn't show the info. In fact, it only shows the results for the questions answered before the duplication. I have checked visually and with a "duplicated elements finder" and there are no duplicated questions in the array.

Could the splice non being executed time to time? Can you see any "bug" in the function? Could it happen due to hardwer issue?

Thanks in advance.

Was it helpful?

Solution

Your random number generation is not only mathematically wrong (i.e. it won't generate truly random items), it will also from time to time generate a number that is beyond the array's bounds. To explain this: 1+(array.length-1) * Math.random() will generate any number greater or equal to 1 (this will also result in the first item of the array never to be returned, because arrays are 0-based), up to a fraction less than the actual length of the array. If you Math.round() the highest possible result, it will round up to the next highest integer, which is the full length again - and if you access array[array.length], an error is thrown, which is probably responsible for the weird behavior you are seeing.

Here's a possible solution:

Math.round() creates random number bias, anyway (see @OmerHassans link), so you're better off using int() or Math.floor(). Also, Math.random() is defined as 0 <= n < 1, so it will never return 1. Therefore, you can simplify your random index generator to int(Math.random()*array.length) => any integer smaller than the length of the array. splice(), then, returns an array of the items that were removed, so you can pass its first item, instead of creating a new array.

function getRandomItem( arr:Array ):* {
    var rand:int = Math.random()*arr.length;
    return arr.splice( rand, 1 )[0];
}

function makeQuestion():void {
    var q:Array = getRandomItem( quizQuestions );
    mc_quiz.question.text = q[0];
    answer=q[1];
    printQuestions[printQuestions.length] = q;
}

FYI: It won't matter much in this context, but you get much faster performance by replacing array.push(item) with array[array.length]=item;.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top