Friday, February 22, 2008 @ 5:24 PM
Part 8: Maximizing Screen Real Estate

In the previous post I included a new image of the game. Let me explain how the user is going to interact with the game grid.
Pressing on any square will active a selection (see image below) focusing on whatever horizontal (across) word includes that square. The actual square pressed will turn blue. Pressing anywhere on the now visible selection will rotate it 90° (using the blue square as a control point) to focus on the vertical (down) word. Pressing the selection a second time will deactivate it. You can also deactivate the selection at any time by pressing outside of the selection.
A clue will only be visible underneath the puzzle while a selection is activated. It will initially read something like this:
29 DOWN Starbucks order.
Press here to answer.
Press here to answer.
I decided early on that I didn't want to continually display an input field for answering. Rather, I only wanted to display it when the user was actually ready to answer.
Since iPhone applications are dynamic, we can make smart use of the screen real estate and only display certain UI elements when necessary. Here's how I implemented the "now-you-see-it-now-you-don't" input field:
HTML:
<span id="outer-answer"><input type="text" id="answer" value="" /><span style="text-decoration:underline">Press here to answer.</span></span>
CSS:
#outer-answer { position:relative; }
#answer {
width: 208px;
height: 20px;
border: none;
padding: 0;
margin: 0;
position: absolute;
opacity: 0;
text-align: center;
line-height: 20px;
margin-left: 56px;
font: bold 13px Georgia,serif;
}Javascript:
document.getElementById('answer').onfocus = function() {
this.style.opacity = 1;
};
document.getElementById('answer').onblur = function() {
if (this.value != '') {
var letters = this.value.split('');
var correct = xmlhttp.responseXML.getElementsByTagName(node)[0].getAttribute('a').split('');
var numCorrect = 0;
for (var i = 0; i < selected.length; i++) {
if (letters[i]) {
if (letters[i].toUpperCase() == correct[i]) {
eval('ctx.drawImage(i'+letters[i].toLowerCase()+'b, '+((selected[i].id%15)*18)+', '+(Math.floor(selected[i].id/15)*18)+')');
matrix[selected[i].id] = 1;
numCorrect++;
} else {
matrix[selected[i].id] = 0;
}
}
}
if (numCorrect == correct.length) {
alert('Correct!');
clearSelection();
} else if (numCorrect == 0) {
alert('Incorrect, try again.');
document.getElementById('answer').value = '';
document.getElementById('answer').focus();
} else if (numCorrect != correct.length) {
alert('Only some letters are correct.');
clearSelection();
}
checkForWin();
}
};The input field is actually always present (positioned on top of the "press here" text), but it starts off invisible. When you press to answer the field becomes active and the iPhone displays its keyboard. Press the keyboard "Done" button or anywhere on the grid to commit your answer.
So, that's how it's done. Before I wrap up this post, I'll explain some of the other things that are happening in the Javascript above.
Once the user clicks the iPhone's "Done" button we first check to make sure they have actually entered text. If they have, we create an array of the text and match it against an array of the letters that make up the correct answer to the clue. We check each letter one by one. If the letters match, we add the letter to the game grid. The matrix array keeps track of whether or not correct letters have been added to the 225 different spaces that make up the puzzle. Ultimately if all letters are correct, you've won the game.
// Ryan Jennings
Labels: crossword, game, how to, iphone development, javascript
MindComet at 5:24 PM - View Post


