Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

How do I use Math.random() on an array of questions?

I have an array of questions, with the question in index 0 and the answer choices in index 1 2 3 4 and the answer in index 5. How do I create function that randomly selects 15 questions from this array that has 100 questions, without repeating a question? I am trying to use the Math.random function but I have no idea if thats possible cause it returns an integer.

13 Answers

Hi Zecare,

I ran into the same problem some time back on a personal project of mine. I wanted 3 random numbers between 1-6 but I didn't want any repeats. The solution to this problem can vary, there are many ways to solve it. I'm not entirely sure which is the best way to go about it, especially considering performance, but I got it to work.

I wrote a CodePen for you here here so you can see how it works. Reload the page to display a new set of questions.

Here's the JavaScript code -

var display = document.getElementById("questions");
var questions = ['What color is the sky?',
                'What sound does a cow make?',
                'How many stars are on the US flag?',
                'How mad is Max?',
                'Is this another question?'];

var questionTracker = [];
var questionAmount = 3;

// Iterate however many times
for (var i = 0; i < questionAmount; i++) {
  // Keep creating random numbers until the number is unique
  do {
    var randomQuestion = Math.floor(Math.random() * questions.length);
  } while (existingQuestions());

  display.innerHTML += questions[randomQuestion] + '<br>';
  // Add the question to the tracker
  questionTracker.push(randomQuestion);
}

// If the current random number already exists in the tracker, return true
function existingQuestions() {
  for (var i = 0; i < questionTracker.length; i++) {
    if (questionTracker[i] === randomQuestion) {
      return true;
    }
  }
  return false;
}

In this implementation, I used the questionTracker array to keep track of which questions were already used.

You would have to do a few things differently with your code, since you have answers to your questions. Also, you would need to reset the tracker array if you wanted to display another set of questions without reloading the page.

I'd also recommend creating the questions as objects, and storing all the related information inside each of those question objects, such as the answer. That way you could simply use question[i].answer when you need the answer, or answers.

It's a nice sized project, but hopefully this will get you started.

Let me know if you have any questions.

I tried this attempt but my array is multidimensional, with a few tweaks I got it to print out a random question but it, prints the answers with it. I just want to print random questions.

Can you post your array here? I'd like to see it. I'm not sure if I'd use a multidimensional array for this, but I may be able to get my example working with one.

var questions = [
["Taxonomy is the __________ of organisms.","structure","classification","dissecting","opening","B"], ["How many charactersitics do all living things have in common?", "7","4","6","3","A"], ["Which of the following is not a taxanomic classifcation?", "kingdom", "height", "phyla","class","B"], ["Various species are located and classified in an _________.", "habitat","chart","ecosystem","group","C"], ["The three main symbiotic relationships are: Mutalism, Paramatism and _________.", "commensalism,","existentialism","communism","pragmatism","A"],
];

Okay, check this out - CodePen.

We can use a for loop to access each of the question's choices. As you can see here (var i = 1; i <= 4; i++) we skip 0 (the question) and stop at 4 (the last choice).

We can also use an ordered list, and the type="A" attribute will allow the choices to display appropriately.

A downside to writing questions as arrays is that they aren't extendable. If we had a question with say 5 choices, the code would break. If it will always be four choices, then the code is fine, but it is good practice to plan for the future. Something to maybe play with afterwards.

Now you would need to write the user input and answer checking code.

Let me know if you have any questions or need anymore help!

Thanks for trying to help me, I really appreciate it.

Sure thing. Don't be afraid to ask for help in the future if you're stuck with something. When you finish your app be sure to post it back here on the forums, we like to see people's projects. :)

can you explain to me exactly how the Math.random function works with characters and strings, I feel quite confused about.

Sure.

So say that we have a simple array.

var food = [ 'broccoli', 'apple', 'potato', 'artichoke' ];

We know that to gain access to a specific element in this array, we'll need to use an index number. Since array elements start at 0, broccoli would be 0, apple would be 1, potato would be 2, etc.

console.log(food[0]); // Outputs broccoli
console.log(food[3]); // Outputs artichoke

So then how would we print a random string from the food array? The answer is what you originally assumed, and that is by using the Math.random() method.

var randomFoodIndex= Math.floor(Math.random() * food.length);

This will create a random number, from 0 to the length of the array. In this case, since the array has 4 elements inside of it, the last element is at an index of 3. So randomFoodIndex will create a random number from 0 to 3. Now we can use the variable we stored the random number in to access the food array.

var food = [ 'broccoli', 'apple', 'potato', 'artichoke' ];
var randomFoodIndex= Math.floor(Math.random() * food.length);
console.log(food[randomFoodIndex]); // Outputs the random chosen food string

Since you're working with multidimensional arrays, it would work like this, using the second index -

var food = [ 
['broccoli', 'vegetable'], 
['apple', 'fruit'], 
['potato', 'root vegetable'], 
['artichoke', 'vegetable'] 
];
var randomFoodIndex= Math.floor(Math.random() * food.length);
console.log(food[randomFoodIndex][0]); // Outputs the random chosen food string
console.log(food[randomFoodIndex][1]); // Outputs the food type string

This is how all of the array elements are accessed in the CodePen I provided. Other than that, we use a few loops to check if there are repeats, and more loops to iterated through the question indexes.

Hope this makes sense. Is there anything specific from this that you need help understanding? I can try to explain more in depth if there's a specific step that you're having trouble with.

Hey, thanks a lot I got the quiz to display random questions, but now it won't increment on click,

var randomQuestionIndex= Math.floor(Math.random() * questions.length);
var question = questions[randomQuestionIndex][0];
var correctAnswer = questions[randomQuestionIndex][5];

function renderQuestionsAndAnswer() {

    score.innerHTML = (correct)+" / "+questions.length;
    test.innerHTML = "<div id='question'>"+questionNumber++ +") "+ question++ +"</div>";
    chA = questions[randomQuestionIndex][1];
    chB = questions[randomQuestionIndex][2];
    chC = questions[randomQuestionIndex][3];
    chD = questions[randomQuestionIndex][4];
    test.innerHTML +="<div><button onclick='checkAnswer(value)' value='A' name='choices'>"+"(a) "+chA+"</button></div>";
    test.innerHTML +="<div><button onclick='checkAnswer(value)' value='B' name='choices'>"+"(b) "+chB+"</button></div>";
    test.innerHTML +="<div><button onclick='checkAnswer(value)' value='C' name='choices'>"+"(c) "+chC+"</button></div>";
    test.innerHTML +="<div><button onclick='checkAnswer(value)' value='D' name='choices'>"+"(d) "+chD+"</button></div>";    
};

renderQuestionsAndAnswer();



function checkAnswer(value) {
    if(value === correctAnswer) {
        correct++;
                question ++;
    };  
    renderQuestionsAndAnswer();
};

It's because you're only generating a single random number. That calculation needs to run every time you want a new number.

Try adding this line -

randomQuestionIndex = Math.floor(Math.random() * questions.length);

at the beginning of your renderQuestionsAndAnswer() function. Keep the original declaration of the randomQuestionIndex variable too, don't remove it. You should then see randomization. Of course, this implementation will sometimes run into repeats, i.e. you click on an answer but the next question is the same. You'll need to look at the CodePen I provided to see how I fixed that problem.

I do have the line, like this is my final code, I made pen http://codepen.io/Viura/pen/mJZErK and it's only displaying a random question at first and the it increments from where it starts it doesn't display another random question. Like that's what I am trying to solve now, only one question is displayed at a time no more and when the right answer is clicked it increments from the random position.

I think you misread my previous post. I'm aware you have that already declared, but you'll need to assign a new random number to that variable again, specifically within your renderQuestionsAndAnswer() function.

Try adding this line -

randomQuestionIndex = Math.floor(Math.random() * questions.length);

at the beginning of your renderQuestionsAndAnswer() function.

This will make sure that a new random number is generated every time a new question is loaded, instead of the single time at the beginning of the file.

Looking good so far, though! I think after adding that you'll pretty much have it working like you want it to.

I do have that line at within my render function but it makes the entire quiz not render, I really appreciate you trying to help me much you did get me render a question randomly from the array but when I click any one of the answers it doesn't render another random question from anywhere in array. it's just so strange.

Ah okay, I didn't see the line in the CodePen link you pasted above. If you want, you can post all of the code (preferably through a CodePen link) and I can see what's going on with it.

http://codepen.io/Viura/pen/bdPLyx?editors=101 there is the code, the line is stored in a variable called random.

See here.

Without running random each time, it's only going to be random the first time. I created a function that recalculates random every time one of the choices is clicked, and wrote the function call in the next() function. This could be cleaned up a little bit but this is essentially how it works.

OMG thankkkk youuuuuuuuuuuuuuuuuuuuuu T_T can I credit you on my site when it's finished as I am sooo grateful, thank you xxxx.

Glad it worked! And no need, just a simple fix. :)

If you can, select one of my answers as "Best Answer" so that other students searching for topics will see that your problem was solved.

Good luck!

Alright thank you so much, one more thing, my logic was is that if I created a variable called correctAnswer and = it to questions[random][5] and then attach it to the next(); function as well as the randomize() and then include an if statement in next(); like this if(value === correctAnswer) { correct++; };

when the button is pressed a random value is returned instead of the matcing value in the array index of 5.

I tried questions[this.random][5] questions[question.random][5] questions[question[random]][5] question[this.random][5] questions[0[random]][5]

like can you show me the logic on how I would implement, like a hint I don't want the answer unless I really can't figure it out.

How would I logically apply this statement to my next(); function // when the button is clicked if the value of the random question's answer is equal to the index of 5 of that individual question array

Also why doesn't this work questions[random][5], why doesn't it return the matching index 5 of the random question ?

questions[random][5] should work.

I tested this on my CodePen.

On line 35 -

test.innerHTML += questions[random][5];

This prints the answer to the matching question.

So you have the right idea, you would write this out as -

if (value === questions[random][5]) {
    correct++;
}

But it is very important that you write this condition above the randomize(); function call, because if you don't then you'll be matching the value to a completely different answer, giving incorrect results. There should be no randomization between the choice click and the condition check.

function next() {
      if (value === questions[random][5]) {
         correct++;
      }
      randomize();
      renderQuestions();
}

It does nothing, my code doesn't move onto the next line anymore it just renders a question and doesn't even increment the correct variable.

You made sure that the if statement is ran before the randomize() function call? You can try to check my CodePen and compare it to yours to see what the issue is. Worst case, post that code again and I'll look at it.

http://codepen.io/Viura/pen/oXKvvr?editors=101

See, it won't move now and nothing happens.

Okay, I see. The issue is that the "value" variable doesn't exist, the value property on your tag doesn't get sent to the next() function.

Ideally, you would write -

test.innerHTML +="<div><button onclick='next('B')' value='B' name='choices'>"+"(b) "+answerB+"</button></div>";

And then write next like -

function next(value) {
      if(value === questions[random][5]) {
        correct++;
      }
      randomize();
      renderQuestions();
}

But it looks like the onclick event doesn't like sending arguments to the function, so it doesn't work.

I would recommend writing the on clicks as JavaScript functions. I highly recommend taking the jQuery course here on Treehouse to learn how to do this, it will do some amazing things for your program and make your life a lot easier!

If you'd like, I could write my own example on how I would go about this. Let me know.

No it still does nothing, I find it so odd.