Page 2. Short answer quiz

There are many applications of a sound mathematics parser. We present here an example in which we check student answers to randomly generated questions in a short answer quiz format. Other examples can be found in other tutorials on the MathAndFlash site, primarily those involving graphing expressions. A list linked to some of these other applications can be found on page 3 of this tutorial.

The basic idea for the answer checking is that program will take "numpoints" number of values (for n) between "min" and "max," and compare the user answer to the correct answer for these values. If every comparison differs by less than "tolerance", then the answer is considered to be correct. While this is not a foolproof mechanism for checking algebraic answers, it works well in this setting where we know at the outset that the answers are simple quadratic polynomials. The problems (and answers) are chosen randomly within certain parameters apparent in the script.

To create the application above, you will have to place a number of items on the stage including labels, dynamic textboxes named txtInitial, txtRecursivePart, txtResponseBox, and an input textbox called txtUserAnswer. In addition, there are buttons named btnCheck and btnNext. The fully commented script is given below.

import bkde.as3.parsers.*;

 

// The following lines set the answer-checking parameters.

 

var numpoints:Number = 12;

var tolerance:Number = 0.00001;

var min:Number = 2;

var max:Number = 5;

 

// Declare string variables to create problem statement and correct answer.

var stInit:String;

var stRecur:String;

var stAnswer:String;

 

// Function to set a random problem and correct answer.

function nextProblem():void {

var a,b,c:int;

/*

Random problem parameters: "a" is chosen from {2,4,6}, "b" is chosen

from {-3,-2,-1,0,1,2,3}, and "c" is chosen from {0,1,2,...,8}.

*/

a = 2*Math.ceil(3*Math.random());

b = 3 - Math.floor(7*Math.random());

c = Math.ceil(9*Math.random());

stInit = String(c);

/*

The following block prevents things like "(3*n + -2)" or "(2*n + 0)"

from being part of question statements.

*/

if (b < 0) {

stRecur = String(a) + "*n - " + String(-b);

}

else if (b > 0) {

stRecur = String(a) + "*n + " + String(b);

}

else {

stRecur = String(a) + "*n";

}

 

// Set the correct answer for these random parameters

stAnswer = String(a) + "*n*(n-1)/2+" + String(a+b) + "*n+" + String(c);

 

// Update textboxes on the stage.

txtInitial.text = stInit;

txtRecursivePart.text = "(" + stRecur + ")";

txtResponseBox.text = "";

txtUserAnswer.text = "";

}

 

function checkAnswer():void {

var stUserAnswer:String = txtUserAnswer.text;

 

// Do nothing if there is no user answer yet.

if (stUserAnswer.length == 0) {

return;

}

 

// Compile both the user answer and the correct answer.

var procFun:MathParser = new MathParser(["n"]);

var corrCO:CompiledObject= procFun.doCompile(stAnswer);

var userCO:CompiledObject = procFun.doCompile(stUserAnswer);

 

if (userCO.errorStatus == 1) {

txtResponseBox.text = "Error in user formula. " + userCO.errorMes;

return;

}

 

if (corrCO.errorStatus == 1) {

txtResponseBox.text = "Error in correct formula. " + corrCO.errorMes;

return;

}

 

var thisX, userY, corrY, i:Number;

for (i=0; i<numpoints; i++) {

// Evaluate the user answer and correct answer at an x-value.

thisX = min + i*(max - min)/numpoints;

userY = procFun.doEval(userCO.PolishArray,[thisX]);

corrY = procFun.doEval(corrCO.PolishArray,[thisX]);

 

// If answers differ by too much, then the user answer is wrong.

if (Math.abs(userY - corrY) > tolerance) {

txtResponseBox.text = "Incorrect";

return;

}

}

// If the loop above never stopped, then the answer is right.

txtResponseBox.text = "Correct!";

}

 

// Both the Check button and "Enter" key will check the answer.

 

btnCheck.addEventListener(MouseEvent.CLICK, btnCheckPressed);

function btnCheckPressed(e:MouseEvent):void {

checkAnswer();

}

 

stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);

function keyPressed(evt:KeyboardEvent):void {

if (evt.keyCode == Keyboard.ENTER) {

checkAnswer();

}

}

 

// The Next button picks another problem.

btnNext.addEventListener(MouseEvent.CLICK, btnNextPressed);

function btnNextPressed(e:MouseEvent):void {

nextProblem();

}

 

// Pick a problem initially...

nextProblem();

 

Download

Notes

  • To check answers more robustly, one can evaluate the answer polynomial at several integer values and check that the outputs are also integers. In a discrete math setting, we can take advantage of the fact that we know the functions are on the set of integers to guarantee numerically that an answer is correct.
  • In situations where a student can enter any expression at all (like if the question is to compute a derivative or integral), then there are many challenges to make sure that a given answer is correct.

Back to Intermediate Tutorials              Back to Flash and Math Home

We welcome your comments, suggestions, and contributions. Click the Contact Us link below and email one of us.

Adobe®, Flash®, ActionScript®, Flex® are registered trademarks of Adobe Systems Incorporated.