[Solved] Randomizing Questions


(David Williams) #1

I’m in a bit of a hurry making a trivia game for school (1 day left to do it, had 6 months). There will be 6 levels, and each level will have 5 questions. How could I make it segmented, where there are the five questions for each level, but it randomly displays those 5 questions for that level? So that the level will always be those 5 questions, but the questions won’t always be in the same order.

I’ll also be doing something similar with the questions, but I’ll probably be able to base that off of the help received from putting the questions in random order.


(Jacob Albano) #2

Let’s say your questions are stored in an array (how you fill this array doesn’t matter). For the purposes of this example I’ll assume they’re just strings.

var questions:Array = [
    "What is your name?",
    "What is your quest?",
    "What is your favorite color?",
    "What is the airspeed velocity of an unladen swallow?",
    "What do you mean? An African or European swallow?"
];

You can make sure this array is presented in a random order with no repeats with FP.shuffle().

FP.shuffle(questions);

(David Williams) #3

That makes sense, and I could do the same for the answers. The only thing further that I would need to do is determine a way to relate the set of answers to the random question.

Maybe an array populated with arrays that have been shuffled for the answers, so that way I’ll know that answers[0] will be answers to question 1, but answers[0][0-3] could be the right or wrong answer to question 1.

If I did the above, then I would have to make 30 arrays [5q’s per 6 floors], shuffle them, then put them all into 1 big array to hold the answers and make 6 seperate arrays for each of the 6 floors, each containing 5 q’s.

PS… Huh? I… I don’t know that.


(Zachary Lewis) #4

Create your own data structure and use it.

I’ve made a TriviaObject that contains its question and answers that has some helper functionality.

public class TriviaObject extends Object
{
	protected var _question:String;
	protected var _correctAnswer:String;
	protected var _answers:Vector.<String>;

	/** The trivia question. */
	public function get question():String { return _question; }
	
	/** The list of potential answers to the trivia question. */
	public function get answers():Vector.<String> { return _answers; }

	/**
	 * Constructor
	 * @param	question The trivia question.
	 * @param	correctAnswer The correct answer for the question.
	 * @param	incorrectAnswers Incorrect answers to confuse the user.
	 */
	public function TriviaObject(question:String, correctAnswer:String, ... incorrectAnswers)
	{
		// Save the question and correct answer.
		_question = question;
		_correctAnswer = correctAnswer;

		// Add the correct answer from the list of potential answers.
		_answers = new Vector.<String>();
		_answers.push(correctAnswer);

		// Add all valid incorrect answers to the list of potential answers.
		for each (var s:String in incorrectAnswers)
		{
			_answers.push(s);
		}
	}

	/**
	 * Checks if the provided guess is the correct answer.
	 * @param	guess The guess at the answer of the question.
	 * @return	Is the guess correct?
	 */
	public function checkAnswer(guess:String):Boolean
	{
		// Prevent issues with case sensitivity by converting all answers to lower case.
		return guess.toLowerCase() == _correctAnswer.toLowerCase();
	}
}

From here, you can create your questions and set up a system to shuffle them, as well as the answers.

I’ve created some sample logic flow.

// Create a list of trivia objects.
var triviaList:Vector.<TriviaObject> = new Vector.<TriviaObject>();
var currentQuestion:TriviaObject;
var currentAnswers:Vector.<String>;
var currentIndex:uint = 0;
var score:uint = 0;

// Populate that list with choices.
triviaList.push(new TriviaObject(
	"What year was HMS Active launched?",
	"1929",
	"1931",
	"1943",
	"1991"));

triviaList.push(new TriviaObject(
	"The Murchison Highway (A10) runs from the West Coast of Tasmania to where?",
	"Burnie",
	"Smithton",
	"Perth",
	"Sorell"));

triviaList.push(new TriviaObject(
	"What topics the German internet radio show \"RadioTux\" discuss?",
	"Free and open source software",
	"Bespoke formalware",
	"Germanic history",
	"Local charity events around Cologne"));

// Randomize list
FP.shuffle(triviaList);

// Begin questions.
currentQuestion = triviaList[currentIndex];

currentAnswers = currentQuestion.answers;
FP.shuffle(answers);

// Display answers and await user selection.

...

// Handle user selection. I added a scoring system for fun.
score += currentQuestion.checkAnswer(userAnswer) ? 100 : -50;

// Proceed to the next question
currentIndex++;

(David Williams) #5

Wow, that was so much simpler than what I did. It’s really impressive to see how the same situation can be handled in two completely different ways.

Mine involves 30 of these in a for loop:

case 0:
	questions.push(new QuestionBase(String(i+1)+".  "+"For presentation purposes, a circular or oval \narrangement is conducive for:"));
	var curAnsS:Array = new Array();
	curAnsS.push(new AnswerBase("a communicator to stand and address the group"));
	curAnsS.push(new AnswerBase("an audience to focus on visuals in the front of the room"));
	curAnsS.push(new AnswerBase("a communicator to control a group"));
	curAnsS.push(new AnswerBase("group discussions and shared communications", true));
	FP.shuffle(curAnsS);
	answers.push(curAnsS);
	break;

It still works, but it’s like, man, why didn’t I think of that?! If I ever run into a similar situation, however, I’ll now be prepared.


(Jacob Albano) #6

You could go one step further and store your trivia stages in XML files.

<trivia>
    <question>What is the difference between a duck?</question>
    <correct>One of its legs is both the same.</correct>
    <incorrect>
        <item>I'm not clever enough to think of wrong answers.</item>
        <item>Deal with it.</item>
        <item>the end</item>
    </incorrect>
</trivia>

Then in as3:

var xml:XML = FP.getXML(EMBEDDED_TRIVIA);
var question:String = xml.question.text();
var correct:String = xml.correct.text();
var incorrect:Array = [];

for each (var item:XML in xml.incorrect.item)
{
    incorrect.push(String(item.text()));
}

(Ultima2876) #7

I’m curious, did you get it done in time? :slight_smile:


(David Williams) #8

Well, it actually turns out, it’s due February 28th, further fueling my procrastination. Hopefully I can motivate myself to do it before then.


(Ultima2876) #9

Know how that feels; honestly though I’d recommend getting started as soon as possible. You might find that you really enjoy it!


(Ultima2876) #10

As an interesting aside, there’s some nice discussion on reddit about randomisation in games:

The standard library random calls provide a nearly uniform “random variable”. There are a few problems with a uniform distribution that make it not work well in games. First off, it’s flat. Given a distribution range [0, 6) each of 6 sides of your dice have a 1/6th chance of getting picked. But, if you’ve ever played a board game like DnD, you end up seeing stats like 2D4 + 2, but why? Adding multiple random variables together causes the distribution to change towards a normal distribution. 2D4 has the following stats total: 2 3 4 5 6 7 8 ways to sum: 1 2 3 4 3 2 1 so you’re much more likely to get a number near the middle of the range than near the edges. Every variable you add on top of that stretches the middle even higher. Secondly, humans are really really bad at probability. Check out the “Monty Hall Paradox”. Because of this, people see “17% chance to crit” on a weapon, and get royally upset when it doesn’t crit 1 in 6 attacks, yet really happy when it crits 5 times in a row. In probability your dice rolls are totally independent. 6 rolls is not sufficient to indicate the relative probability of each die side any more than a single coin flip dictates what side of the coin you’ll get. But after sufficient number of rolls you’ll see a pattern emerge. But by that point you gamer is usually pissed that he had too long of a dry spell while the AI was getting lucky. Many games handle this by making a “bag”. There are plenty of optimizations, but the end goal is to fill a bag with the outcomes (5 white balls, 1 red). Remove each element randomly from the bag each time you need a random event. When all the items were removed from the bag, re-fill it. This spaces out events randomly, but guarentees that you get exactly the advertized probability.


(David Williams) #11

Wow, that’s a really interesting concept that I never really thought of before. Thanks for the awesome share!