Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

Saturday, September 13, 2008

Javascript Hangman

Hangman is a popular pencil and paper game. One player chooses a word and draws dashes to represent the length of the word.

The other player guesses letters. If the letter is in the word the dash is replaced with the letter. If the guessed letter is not in the word then a part of the hanging body is drawn (head, body, left leg, right leg, left arm, right arm) once the body is completely drawn or the entire word has been guessed the game is over.

I decided to re-create this game using Javascript and the html canvas object. Javascript is used to handle the game while the canvas is used to draw the hangman character when the guesses are incorrect.

To start lets define a simple html page that includes our canvas and a couple of spans to hold the word and messages for the user.

<html>
<body onload="draw();" onkeyup="handleKeyUp(event);">
<table>
<tr>
<td colspan=2>
<span id='alreadyGuessed' style="visibility:hidden">Letter already guessed</span>
<span id='strike' style="visibility:hidden">Strike!</span>
</td>
</tr>
<tr>
<td>
<canvas id='hangman' width=150 height=150>
</td>
<td>
<span id='word'></span>
</td>
</tr>
</table>
</body>
</html>


When the page is loaded we call 'draw()' and we setup a keyboard listener to listen to keystrokes. We've defined a few simple span's that will be messages to the user, a canvas to draw the victim and a span to hold the word that the user will be guessing.

The game expects a character from A-Z so our keyboard listener should filter out all other values here is what our listener looks like:

function handleKeyUp(evt) {
var e = evt ? evt : event;
if (e.keyCode >= 65 && e.keyCode < (65+26) ) {
guess(String.fromCharCode(e.keyCode));
}
draw();
}



The keyCode value is the ASCII representation we know that the ASCII characters are in sequence with capital 'A' being 65 and capital 'Z' being 65+26 characters away. If the user enters a valid character we enter our 'guess' function else we do nothing. After guessing our draw() function is called to redraw the screen.

The draw function as you have now seen is called when the game is first loaded and after each keypress lets see what it does.

function draw() {
var str='';
for(i=0;i<word.length;++i) {
if (foundLetters[i]) {
str += word[i];
} else {
str += '_';
}
str += ' ';
}
document.getElementById('word').innerHTML = str;
}



The draw function looks at our internal data structures which will explore later and determines if the user has guessed a letter yet or not. If the letter has been guessed the letter is shown, else a '_' is shown instead.


So now to the heart of the game, the guess function.

function guess(key) {
hideMessages();
if (guessedLetters[key]) {
showAlreadyGuessed();
return;
}
guessedLetters[key] = true;
var found = false;
for(i=0;i<word.length;++i) {
if (word[i] == key) {
foundLetters[i] = true;
found=true;
}
}
if(!found) showStrike();
return found;

}



The guess function iterates over the chosen word and determines if the character in the word has been guessed. If it has it marks foundLetters[index] where index is the index of the character that has been revealed. We saw in the 'draw' function how this is used to change the display.

The last thing to note is how we use the canvas element to draw a very crude hangman as the user guesses incorrectly.


function drawHangMan(numberOfStrikes) {
var canvas = document.getElementById('hangman');
if(canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.save() ;
ctx.translate(45,45);
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.beginPath();
if(numberOfStrikes >= 1) ctx.fillRect(0,0,10,10); //head
if(numberOfStrikes >= 2) ctx.fillRect(-5,10,20,20); //body
if(numberOfStrikes >= 3) ctx.fillRect(-20,10,20,5); //left arm
if(numberOfStrikes >= 4) ctx.fillRect(0,10,30,5); // right arm
if(numberOfStrikes >= 5) ctx.fillRect(-5,30,5,10); // left leg
if(numberOfStrikes >= 6) ctx.fillRect(10,30,5,10); // right leg

ctx.fill();
ctx.restore();
}
}



This method is pretty self explanatory. Based on the number of strikes more of the hangman's body will be revealed.

Here is the entire code listing, let me know if you have any questions. Enjoy...


<html>
<head>
<script type="application/x-javascript">

var words = new Array();
words[0] = "Ford";
words[1] = "Chevy";
words[2] = "Mazda";
words[3] = "Volvo";
words[4] = "Javascript";
words[5] = "Google";
words[6] = "Microsoft";
words[7] = "Nvidia";


var rand_no = Math.random();
rand_no = Math.ceil(rand_no * words.length)-1;


word = words[rand_no].toUpperCase();
var foundLetters = new Array();


var guessedLetters = new Array();
function hideMessages() {
document.getElementById("alreadyGuessed").style.visibility='hidden';
document.getElementById("strike").style.visibility='hidden';
}
function showAlreadyGuessed() {
document.getElementById("alreadyGuessed").style.visibility='';
}

function drawHangMan(numberOfStrikes) {
var canvas = document.getElementById('hangman');
if(canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.save() ;
ctx.translate(45,45);
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.beginPath();
if(numberOfStrikes >= 1) ctx.fillRect(0,0,10,10); //head
if(numberOfStrikes >= 2) ctx.fillRect(-5,10,20,20); //body
if(numberOfStrikes >= 3) ctx.fillRect(-20,10,20,5); //left arm
if(numberOfStrikes >= 4) ctx.fillRect(0,10,30,5); // right arm
if(numberOfStrikes >= 5) ctx.fillRect(-5,30,5,10); // left leg
if(numberOfStrikes >= 6) ctx.fillRect(10,30,5,10); // right leg

ctx.fill();
ctx.restore();
}
}

var numberOfStrikes=0;
function showStrike() {
numberOfStrikes++;
drawHangMan(numberOfStrikes);
document.getElementById("strike").style.visibility='';
}


function guess(key) {
hideMessages();
if (guessedLetters[key]) {
showAlreadyGuessed();
return;
}
guessedLetters[key] = true;
var found = false;
for(i=0;i<word.length;++i) {
if (word[i] == key) {
foundLetters[i] = true;
found=true;
}
}
if(!found) showStrike();
return found;

}
function draw() {
var str='';
for(i=0;i<word.length;++i) {
if (foundLetters[i]) {
str += word[i];
} else {
str += '_';
}
str += ' ';
}
document.getElementById('word').innerHTML = str;
}
function handleKeyUp(evt) {
var e = evt ? evt : event;
if (e.keyCode >= 65 && e.keyCode < (65+26) ) {
guess(String.fromCharCode(e.keyCode));
}
else {
//alert("You entered " + e.keyCode);
}
draw();
}


</script>
</head>
<body onload="draw();" onkeyup="handleKeyUp(event);">
<table>
<tr>
<td colspan=2>
<span id='alreadyGuessed' style="visibility:hidden">Letter already guessed</span>
<span id='strike' style="visibility:hidden">Strike!</span>
</td>
</tr>
<tr>
<td>
<canvas id='hangman' width=150 height=150>
</td>
<td>
<span id='word'></span>
</td>
</tr>
</table>
</body>
</html>

Thursday, July 24, 2008

Javascript - Adding options to select box

Adding options to List Box in client side Javascript

Options to a drop down list box can be added dynamically using client side JavaScript.

function addOption(selectbox,text,value )
{
var optn = document.createElement("OPTION");
optn.text = text;
optn.value = value;
selectbox.options.add(optn);
}


Note that each time the function is called, it adds a new option to the list box. So we can add one option by calling the function once. Like this.

addOption(document.drop_list.Month_list,”January”, “January”);

So this way we can create a drop down list box of all the months by calling the function each time for a month. So with this now you can easily create the list box. But we will add another step to this by using one array of months. So from the array of months we will loop through and add each month to the list box. Here is how to create the array

var month = new Array("January","February","March","April","May","June",
"July","August","September","October","November","December");

So now once our array is ready with data, we will loop through the array by using for loop and then call the addOption function using the data of the array. Here is the code.

for (var i=0; i < month.length;++i){
addOption(document.drop_list.Month_list, month[i], month[i]);
}


And if you want to clear the options use:

document.drop_list.Month_list.options.length = 0;

Friday, July 4, 2008

JSON - JavaScript Object notation

JavaScript Object Notation is a data interchange format. The JSON format is often used for transmitting structured data over a network connection in a process called serialization. Its main application is in Ajax web application programming, where it serves as an alternative to the traditional use of the XML format.

A simple example is :


This script will popup an alert dialog box with the text 'John.'

The JSON block can support nested types as well as arrays. For example:


{
"firstName": "John",
"lastName": "Smith",
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": 10021
},
"phoneNumbers": [
"212 555-1234",
"646 555-4567"
]
}


Typically the JSON request will come from the server, or through a Ajax callback or some other technique. This approach is must easier to work with then returning XML that the JavaScript client then has to parse.

Thursday, June 19, 2008

Javascript setInterval, and setTimeout

Here is how you can set a timer in javascript.

setInterval(expression,interval)

or

setTimeout(expression,interval)

expression is a function that you want to call where interval is the time in milleseconds.

setInterval will repeatedly call the expression on the interval whereas setTimeout will call it only once.