reptile7's JavaScript blog
Wednesday, June 19, 2019

Approaching Quizmo, Part 2
Blog Entry #400

Welcome back to our ongoing deconstruction of the Java/JavaScript Goodies Math Check. In the previous post we walked through the checker's addition functionality and we now turn our attention to its subtraction, multiplication, and division code.

Subtract, multiply, divide

Clicking the rekenen form's , , and buttons calls subtract( ), multiply( ), and divide( ) functions, respectively. The subtract( ) and multiply( ) functions are exactly like the add( ) function except they've got - and * operators in place of the + operator; the divide( ) function largely parallels the add( ) function although it does feature some noteworthy differences.

Recall that the Math Check metatext includes a This page is best viewed with Netscape 3.0 line. With Navigator 3.04 on my iMac, x / 0 for x 0 and 0 / 0 both return NaN; the former division returns Infinity with Netscape 4+ and all modern browsers. These divisions are legitimate but their usefulness leaves something to be desired vis-à-vis testing the user's division skills: the divide( ) function staves them off by adding one to the random( ) and ranom( ) % remainders.

numA = random(maxValue) + 1;
numB = ranom(maxValue) + 1;

The divide( ) function subsequently carries out a numA / numB division for which the numA dividend is greater than or equal to the numB divisor; if a first numA = random(maxValue) + 1; is less than a first numB = ranom(maxValue) + 1;, then divide( ) is re-called as many times as needed until numAnumB.

if (numA < numB) { divide( ); }
numC = numA / numB;

The numC quotient is round( )-ed to the nearest integer; a following alert( ) asks the user to follow suit.

numC = Math.round(numC);

Each divide( )/ans( ) run therefore displays four dialogs:

(2) window.prompt(numA + "/" + numB + " = ", 0);

If it takes three divide( ) calls to obtain a numAnumB, then the user will be subjected to twelve dialogs for the same, ultimate numA / numB division, and we don't want that; this situation is easily cleaned up by placing a return statement after the divide( ) re-call so as to end the current divide( ) run.

if (numA < numB) { divide( ); return; }

Alternatively and preferably, we can lose the divide( ) re-call and just exchange the numA and numB values via:

if (numA < numB) {
var divisor = numA;
numA = numB;
numB = divisor; }

Function consolidation

Do we really need separate add( ), subtract( ), multiply( ), and divide( ) functions? Nah. Upon setting up a

var opArray = ["+", "-", "*", "/"];

operator string Array (N.B. a var opArray = [+, -, *, /]; Array of non-stringified operators throws an expected expression, got ',' SyntaxError) the four functions can be formulated as a single operate( ) function that is operator-differentiated by an opIndex parameter (0 for addition, 1 for subtraction, etc.) and whose operator characters are fetched by an opArray[opIndex] expression:

function operate(opIndex) {
...beginning maxValue, numA, and numB assignments...
if (opIndex == 3) { numA++; numB++; if (numA < numB) { ...numAnumB exchange... } }
numC = eval(numA + opArray[opIndex] + numB);
Answer = window.prompt(numA + " " + opArray[opIndex] + " " + numB + " = ", 0);
if (window.confirm("Do you want your browser to check your answer to the problem " + numA + " " + opArray[opIndex] + " " + numB + "?")) ans( );

Note that the numC = numA +|-|*|/ numB operations are merged via the somewhat-notorious eval( ) function; if the use of eval( ) here bothers you for whatever reason, you can write out the operations 'in longhand' instead per the original code:

if (opIndex == 0) numC = numA + numB;
if (opIndex == 1) numC = numA - numB;
if (opIndex == 2) numC = numA * numB;
if (opIndex == 3) numC = numA / numB;

One last function

Clicking the button calls a check( ) function that displays the user's correct and wrong tallies on an alert( ) box.

function check( ) {
window.alert("YOUR SCORE\n : " + correct + " correct\n : " + wrong + " incorrect"); }

The user can problem-wise flit freely between
the add, subtract, multiply, and divide operations and
the A, B, and C difficulty levels
and check( ) will score-wise keep track of it all.
In the next entry we'll revisit the random generation of numA and numB and then wrap things up with a refurbished demo.