Randomize Questions

Recently i was faced with a problem wherein, given a list of question, the order in which they were displayed must vary every time it is presented in a webpage. In this article I will illustrate how we can use The Fisher–Yates shuffle algorithm to solve this problem and dynamically display the order of the questions

The Algorithm:

// To shuffle an array a of n elements (indices 0..n-1):
for i from n−1 downto 1 do
     j ← random integer such that 0 ≤ ji
     exchange a[j] and a[i]

// -(Source Wikipedia)

Steps:

As we need to shuffle only certain items in the page, it would be wise to first group them together. Lets assign a class .random to the elements. Here we will also need to identify a parent container which will contain all the shuffled questions. #question-container

<!-- index.html -->
<ul id="question-container">
 <li class="random">Question 1</li>
 <li class="random">Question 2</li>
 <li class="random">Question 3</li>
 <li class="random">Question 4</li>
</ul>

Now we need to select them in our scripts. We can use jQuery or plain old javascript to do this. Let us also remove the questions once selected from the DOM

// shuffle.js
var questions = $(".random");
var container = $("#question-container");

questions.remove();

Now that the questions don’t exist in the DOM and are selected, lets write the algorithm to shuffle them. We will use the Fisher–Yates shuffle algorithm to do this.

// Fisher–Yates shuffle algorithm
for (var i = questions.length - 1; i > 0; i--) {
 var rand_int = getRandomInt(0, i);
 var temp = questions[i];
 questions[i] = questions[rand_int];
 questions[rand_int] = temp
}

Now our questions array will contain all the questions in a shuffled manner. The getRandom(a,b) function is used to get a random number between a and b, inclusive of a and b. You can write the function as below.

// Get random integer within a range inclusive of min and max values
 function getRandomInt(min, max) {
 min = Math.ceil(min);
 max = Math.floor(max);
 return Math.floor(Math.random() * (max - min + 1)) + min;
 }

Now all that is left to complete this is adding the questions back to the paretn container. We can do this using the append() function in jQuery (similar functions exist in javascript too).

for (var i = 0; i < questions.length; i++) {
 container.append(questions[i]);
}

And we are done. The whole code for this is as follows:

<!-- index.html -->
<!DOCTYPE html>
<html>
 <head>
   <meta charset="utf-8">
   <title>Shuffle</title>
 </head>
 <body>
   <ul id="question-container">
     <li class="random">Question 1</li>
     <li class="random">Question 2</li>
     <li class="random">Question 3</li>
     <li class="random">Question 4</li>
   </ul>
 <!-- Load Jquery -->
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" charset="utf-8"></script>
 <script src="shuffle.js" charset="utf-8"></script>
 </body>
</html>

and our script file as

// shuffle.js
var questions = $(".random");
var container = $("#question-container");

questions.remove();

// Fisher–Yates shuffle algorithm
for (var i = questions.length - 1; i > 0; i--) {
 var rand_int = getRandomInt(0, i);
 var temp = questions[i];
 questions[i] = questions[rand_int];
 questions[rand_int] = temp
}

for (var i = 0; i < questions.length; i++) {
 container.append(questions[i]);
}


// Get random integer within a range inclusive of min and max values
 function getRandomInt(min, max) {
   min = Math.ceil(min);
   max = Math.floor(max);
   return Math.floor(Math.random() * (max - min + 1)) + min;
 }

Cheers!

Leave a Reply

Your email address will not be published. Required fields are marked *