To play magic squares, make all row and columns equal. Select game type.
Rows and columns will be added. Press start to begin.
Rows and columns will be multiplied. Press start to begin.
Row (1 - 4):
Column (1 - 4):
Value (1 - 100):
$disrow1
$disrow2
$disrow3
$disrow4
$disrow5
FormRow: This function takes one new value/coordinate pair, tests it, inserts it in its proper line, and calculates the new game array.
extern function FormRow () {
var gametype = WMLBrowser.getVar ("gametype");
var row = WMLBrowser.getVar ("row");
var col = WMLBrowser.getVar ("col");
var val = WMLBrowser.getVar ("value");
var row1vals = WMLBrowser.getVar ("row1");
var row2vals = WMLBrowser.getVar ("row2");
var row3vals = WMLBrowser.getVar ("row3");
var row4vals = WMLBrowser.getVar ("row4");
var colindex = (Lang.parseInt(col) - 1);
var localdisrow;
var localrowvals;
// Test for appropriate values
var validinputs = false;
while (validinputs == false) {
if (Lang.parseInt(row) > 4) {
row = Dialogs.prompt("Re-enter row value 1 - 4","");
continue;
}
if (Lang.parseInt(col) > 4) {
col = Dialogs.prompt("Re-enter column value 1 - 4","");
colindex = (Lang.parseInt(col) - 1);
continue;
}
val = Lang.parseInt(val);
if (val > 100) {
val = Dialogs.prompt("Re-enter value 0 - 100","");
continue;
}
validinputs = true;
}
// Inputs tested, time to process.
row = Lang.parseInt (row);
if ( row == 1 ) {
localrowvals = row1vals;
} else if ( row == 2 ) {
localrowvals = row2vals;
} else if ( row == 3 ) {
localrowvals = row3vals;
} else if ( row == 4 ) {
localrowvals = row4vals;
}
localrowvals = String.removeAt ( localrowvals, colindex, ",");
localrowvals = String.insertAt ( localrowvals, val, colindex, ",");
// Sum each row and format the output.
localdisrow = ">";
var rowsum = 0;
if (gametype == "prod") rowsum = 1;
for ( var i = 0; i < 4; i++ ) {
var newelement = String.elementAt(localrowvals, i, ",");
newelement = Lang.parseInt(newelement);
if (gametype == "sum") {
rowsum = rowsum + newelement;
}
if (gametype == "prod") {
rowsum = rowsum * newelement;
}
newelement = String.format("%3.1d", newelement);
localdisrow = (localdisrow + newelement);
}
rowsum = String.format("%3.1d", rowsum);
localdisrow = (localdisrow + "|" + rowsum);
if ( row == 1 ) {
WMLBrowser.setVar ("disrow1", localdisrow);
WMLBrowser.setVar("row1", localrowvals);
row1vals = localrowvals;
} else if ( row == 2 ) {
WMLBrowser.setVar ("disrow2", localdisrow);
WMLBrowser.setVar("row2", localrowvals);
row2vals = localrowvals;
} else if ( row == 3 ) {
WMLBrowser.setVar ("disrow3", localdisrow);
WMLBrowser.setVar("row3", localrowvals);
row3vals = localrowvals;
} else if ( row == 4 ) {
WMLBrowser.setVar ("disrow4", localdisrow);
WMLBrowser.setVar("row4", localrowvals);
row4vals = localrowvals;
}
// Sum each column and format the last row.
var discolsums = "-";
var colchars;
for (i = 0; i < 4; i++) {
var colsum = 0;
if (gametype == "prod") colsum = 1;
colchars = String.elementAt(row1vals, i, ",");
if (gametype == "sum") colsum = colsum + Lang.parseInt(colchars);
if (gametype == "prod") colsum = colsum * Lang.parseInt(colchars);
colchars = String.elementAt(row2vals, i, ",");
if (gametype == "sum") colsum = colsum + Lang.parseInt(colchars);
if (gametype == "prod") colsum = colsum * Lang.parseInt(colchars);
colchars = String.elementAt(row3vals, i, ",");
if (gametype == "sum") colsum = colsum + Lang.parseInt(colchars);
if (gametype == "prod") colsum = colsum * Lang.parseInt(colchars);
colchars = String.elementAt(row4vals, i, ",");
if (gametype == "sum") colsum = colsum + Lang.parseInt(colchars);
if (gametype == "prod") colsum = colsum * Lang.parseInt(colchars);
discolsums = (discolsums + String.format("%3.1d", colsum));
}
WMLBrowser.setVar ("disrow5", discolsums);
WMLBrowser.go ( "magic.wml#DisplayResult" );
WMLBrowser.refresh();
}
Once the user provides a row, column and value to be inserted in the array, the WML deck calls the script function, which first checks the validity of each input. Note the loop that allows the user to keep trying until they get it right:
// Test for appropriate values
var validinputs = false;
while (validinputs == false) {
if (Lang.parseInt(row) > 4) {
row = Dialogs.prompt("Re-enter row value 1 - 4","");
continue;
}
if (Lang.parseInt(col) > 4) {
col = Dialogs.prompt("Re-enter column value 1 - 4","");
colindex = (Lang.parseInt(col) - 1);
continue;
}
val = Lang.parseInt(val);
if (val > 100) {
val = Dialogs.prompt("Re-enter value 0 - 100","");
continue;
}
validinputs = true;
}
With inputs validated, summing the row and formatting the output is straightforward,
localdisrow = ">";
var rowsum = 0;
if (gametype == "prod") rowsum = 1;
for ( var i = 0; i < 4; i++ ) {
var newelement = String.elementAt(localrowvals, i, ",");
newelement = Lang.parseInt(newelement);
if (gametype == "sum") {
rowsum = rowsum + newelement;
}
if (gametype == "prod") {
rowsum = rowsum * newelement;
}
newelement = String.format("%3.1d", newelement);
localdisrow = (localdisrow + newelement);
}
rowsum = String.format("%3.1d", rowsum);
localdisrow = (localdisrow + "|" + rowsum);
, but dealing with the columns brings out a limitation in the WMLScript language. There is no indirection provided within WMLScript, so processing the ith element of the jth row gets ugly. I found the code most legible by just explicitly processing each row
for (i = 0; i < 4; i++) {
var colsum = 0;
colchars = String.elementAt(row1vals, i, ",");
colsum = colsum + Lang.parseInt(colchars);
colchars = String.elementAt(row2vals, i, ",");
colsum = colsum + Lang.parseInt(colchars);
colchars = String.elementAt(row3vals, i, ",");
colsum = colsum + Lang.parseInt(colchars);
colchars = String.elementAt(row4vals, i, ",");
colsum = colsum + Lang.parseInt(colchars);
discolsums = (discolsums + String.format("%3.1d", colsum));
}
but it is possible to build up a variable name in a loop before retrieving an array from the WML deck, in essence providing indirection:
for (var i = 0; i < 4; i++) {
var colsum = 0;
var rowvals = "";
for (var j = 1; j < 5; j++) {
rowvals = WMLBrowser.getVar ("row" + String.format("%1d", j));
colchars = String.elementAt(rowvals, i, ",");
colsum = colsum + Lang.parseInt(colchars);
}
discolsums = (discolsums + String.format("%3.1d", colsum));
}
The full example adds a few playing enhancements to the game that illustrate other aspects of interaction between WML decks and WMLScript functions. The user can select whether rows and columns will be summed or multiplied. The initial card presented to the player uses an option element to guide the selection, and separate cards to initialize the game based on the selection. There is also a "reset game" option presented when the calculated game is displayed (card DisplayResult). It is also possible to present this game reset capability throughout the interaction by binding the do element to the entire deck using the template element. However, this results in a menu of options (OK, Reset) being presented to the user each time they enter a value during the game. I found these extra key strokes more annoying than helpful, so I bound the appropriate do element to just one card. By binding it to a card, the user agent binds each option (OK, reset) to different keys.
TechCrawler
--------------------------------------------------------------------------------
Want more information on WAP? Search the Web.
There are of course other enhancements that could be added to the game if one wished. A guess counter could track how many tries it took a player to complete a square; it would be nice if the user could select an array size less than the code currently fills and have the display of empty squares suppressed. It would even be possible to allow two players to collaborate (or challenge each other) on the same game. Whatever enhancements might be added, though, will use the same basic principles of design. WML decks provide the user interface and data interaction in a declarative environment, WMLScripts provide logic with an imperative structure, and standard libraries provide much of the real power.
--------------------------------------------------------------------------------
About the author:
Kevin Sharp is a registered professional engineer, writer, and yoga teacher living in Tucson, Arizona. His engineering outlets include web consulting for ID Systems Magazine focusing on the fulfillment side of electronic commerce. His writing interests have produced books and articles on the economic impact of technology on manufacturing and distribution organizations. Personal milestones include the 20-year anniversary of the beginning of a most amazing relationship and the recent embarkation on a yoga teaching path in the ashtanga style.