Reputation: 5660
Questions are stored like:
arr[y][x] = { "Question1text" , "answer1" , "answer2" , "answer3" , .... , "boolean" }
get random Question
randomQuestion = qrand() % questionCount;
I set nr 6 to = "1" when i already used that question, so i now look for a random one but without "1" set
while( question[randomQuestion][6] == "1" )
{
randomQuestion = qrand() % questionCount;
}
but let's say there's just 1 question out of 10k left. the chance of the random number to hit exactly that question ain't so bright. So there's gotta be a better way of achieving this, but how?
Upvotes: 0
Views: 209
Reputation: 19855
Shuffle the questions, then simply iterate through the shuffled set. When you get to the end of the set, re-shuffle and start over. Shuffling n
questions takes O(n)
work, so as long as you're storing them in memory anyway this is a cheap and simple solution.
Upvotes: 1
Reputation: 310960
You can use standard class std::bitset
that to mark questions that were already selected. Here is an example that you may use as a base
#include <iostream>
#include <bitset>
#include <cstdlib>
#include <ctime>
int main()
{
const size_t N = 10;
char s[N][3] = { "Q0", "Q1", "Q2", "Q3", "Q4", "Q5", "Q6", "Q7", "Q8", "Q9" };
std::bitset<N> b;
std::srand( ( unsigned int )std::time( 0 ) );
size_t availableQuestions = N;
while ( availableQuestions )
{
size_t i = std::rand() % availableQuestions;
size_t question = 0;
while ( i != 0 || b[question] )
{
if ( !b[question++] && i != 0 ) --i;
}
b.set( question );
std::cout << s[question] << std::endl;
--availableQuestions;
}
return 0;
}
The output at the first run is
Q1
Q9
Q8
Q4
Q6
Q5
Q3
Q2
Q7
Q0
The output at the second run is
Q7
Q5
Q0
Q1
Q2
Q4
Q9
Q8
Q6
Q3
It would be even better to use a for loop instead of the while loop
for ( size_t availableQuestions = N; availableQuestions != 0; --availableQuestions )
{
size_t i = std::rand() % availableQuestions;
size_t question = 0;
while ( i != 0 || b[question] )
{
if ( !b[question++] && i != 0 ) --i;
}
b.set( question );
std::cout << s[question] << std::endl;
}
Enjoy!:)
Upvotes: 1
Reputation: 489
do not use an array , use list instead so you can remove selected questions from it. then simply select a member of list randomly.
Upvotes: 0
Reputation: 138
How about something like that?
question[randomQuestion] = question[--questionCount];
Upvotes: 0
Reputation: 326
Instead of using an old-school array you could store your questions (define a class or struct for a single question) in a list-class like QList. Then you can remove the questions after they are used...
try something like this:
randomQuestion = qrand() % questionList.count();
nextQuestion = questionList.takeAt(randomQuestion);
Upvotes: 2