Pages

Tuesday, October 5, 2010

JQuery Test Ride - Fifteen Puzzle Game

I have heard a lot about jQuery. And, I always wanted to write something using it. I know it's been there for a while already, and you must be like, “What is this guy talking about?”. But, seriously, I just didn't get to it until now, when I decided I wanted to write my favorite childhood game – Number Sorting Game.
It is basically a hand-held game that has 15 squares tabs, but big enough to hold 16 squares. One tab is left empty so other tabs could be moved around. The tabs are numbered through 1 to 15, and are randomly sorted. The objective of the game is to arrange these numbered tabs in ascending by sliding the tabs that are around the blank one.
Here's a sample when the game starts:

The objective of the game is to sort these number in ascending using the blank spaces:
One thing very important to remember is that only tabs next to the blank can be moved.
So, here's how I did it using jQuery, css, and a html page.
Step 1 – jQuery JS, and HTML page
I downloaded jQuery js from the jQuery UI website(http://jqueryui.com/ ). I preferred to go to jQuery UI site and download, because I can grab both the jQuery js and UI for it. Because, I knew that I need to give some kind of congratulations message when the user wins, downloading from jQuery UI just gives me everything I need from js to UI. For the message, I wanted a modal window that greys out the background and pops out a message, like below:
After it is downloaded, there is basically two important folders, a javascript folder, that will have two js scripts, like jquery-1.4.2.min.js and jquery-ui-1.8.4.custom.min.js, and styles folder that has a css file and images folder inside.
I will be using Visual Studio website project, but trust me it is simple enough for other IDE as well. I created 2 folders, scripts and styles, and added the two js files in the scripts folder, and the css file, and the images folder in the styles folder.
Following is how it looked like now:
Now, I just added a Game.htm page, and in it added links to the css and js files:
1:  <link type="text/css" href= "styles/jquery-ui-1.8.4.custom.css" rel="stylesheet" />  
2: <script type="text/javascript" src="scripts/jquery-1.4.2.min.js">script>
3: <script type="text/javascript" src="scripts/jquery-ui-1.8.4.custom.min.js">script>
Just to test jQuery, I added following in the head of the html file.
1:  <script type="text/javascript">  
2: $(document).ready(function(){
3: alert('jQuery says hi');
4: });

Opened the html file in a browser, below is what I get:

Step 2: The tabs, and basic UI

The game has 4x4 grid where each squares land. So, I created a 4x4 table. Basically, four and four in each of them. I have to make each of them clickable, so I gave each of them a unique id, the first one 'td1', second 'td2' and soon.
1:  <table border="1" >  
2: <tr>
3: <td id="td1"></td>
4: <td id="td2"></td>
5: <td id="td3"></td>
6: <td id="td4"></td>
7: </tr>
8: <tr>
9: <td id="td5"></td>
10: <td id="td6"></td>
11: <td id="td7"></td>
12: <td id="td8"></td>
13: </tr>
14: <tr>
15: <td id="td9"></td>
16: <td id="td10"></td>
17: <td id="td11"></td>
18: <td id="td12"></td>
19: </tr>
20: <tr>
21: <td id="td13"></td>
22: <td id="td14"></td>
23: <td id="td15"></td>
24: <td id="td16"></td>
25: </tr>
26: </table>
I've got the placeholders, and now I have to add the numbers. So, I created an array of 16 numbers, and displayed each of them in their respective td's. Why an array? Because, users will be arranging tabs, and if I could link the tabs with an array, sorting, randomizing, and checking if the users actually sorted successfully will be much more easier.
1:  // array of 16 numbers  
2: var tabs = new Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
3: // display array
4: function displayArray() {
5: for (i = 1; i <= tabs.length; i++) {
6: Show(i);
7: }
8: }
9: function Show(tabLocation) {
10: $("#td" + tabLocation).text(tabs[tabLocation - 1]);
11: }
I used JQuery to find specific td from id where part of name comes from variable, and then change the text within it.
This is it.. Once I call the displayArray() in the ready function, it will loop through the tabs array and add first number in first tab, second number in second tab and so on.

Step 3: New Game button, and Random method

What we have till now is a sorted array. So, we need a method to randomize it. Also, a new game button that call the method isn't bad at all. A quick google search on randomizing an array led to sedition.com's Fisher Yates Randomize algorithm(http://sedition.com/perl/javascript-fy.html). And, I used the same logic in my app.
1:  // Ref: http://sedition.com/perl/javascript-fy.html  
2: function fisherYatesRandomize(myArray) {
3: var i = myArray.length;
4: if (i == 0) return false;
5: while (--i) {
6: var j = Math.floor(Math.random() * (i + 1));
7: var tempi = myArray[i];
8: var tempj = myArray[j];
9: myArray[i] = tempj;
10: myArray[j] = tempi;
11: }
12: }
So, now I call this method before I call the display method. It randomizes the array, and displays the array in the grid (/table).
The New Game button works the same way. The id of my button is “btnNewGame”. To call the random and display method when the button is clicked, jquery makes it easy. I added the following code is the ready function.
1:  $("#btnNewGame").click(function () { fisherYatesRandomize(tabs); displayArray(tabs); });  
I hooked up several methods to be called when a button is clicked.


Step 4: Hiding number 16, and a nicer look !!

Everything is good so far, except that 16 is not hidden, and the display is not that great. JQuery to the rescue again !! For the nice display, I used what jQuery UI gave me, a class called “ui-widget-header”. But, what about the number 16?? Well, we will simply don't add any css where to the where 16 exists. With that on mind, I changed my show method to:
1:  function Show(tabLocation) {  
2: if (tabs[tabLocation - 1] == 16) {
3: $("#td" + tabLocation).text("");
4: $("#td" + tabLocation).removeClass();
5: }
6: else {
7: $("#td" + tabLocation).text(tabs[tabLocation - 1]);
8: $("#td" + tabLocation).removeClass().addClass("ui-widget-header");
9: }
10: }
One more thing, to make the 16 as blank, a black background is suitable. I also want the tabs to be 50x50 px, change the mouse pointer to “pointer” when it hovers on the tabs. So, I added the table id as “canvas”, and added styles section in the head.
1:  <style type="text/css">  
2: #canvas
3: {
4: background-color: #000000;
5: border:0;
6: }
7: #canvas td
8: {
9: height:50px;
10: width:50px;
11: font-weight:bold;
12: font-size: 20px;
13: text-align: center;
14: cursor: pointer;
15: }
16: </style>
JQuery does make it easy. I am adding and removing css classes based on some conditions now.
Step 5: Making 'em clickable, and movable
To make those tabs clickable, I added onClick method calls to each of the td. I created a method called TabClicked(tabNumber), and each td calls this method with its tabnumber, such as the first td will now look like:
1:  <td id="td1" onclick="TabClicked(1);">td>  
The TabClicked method will get the tab number of the tab that was clicked, find what's on the left, right, top and bottom, and if one of them has 16, then swap the values and display the grid again.
1:  function TabClicked(tabNum) {  
2: var left = tabNum - 1;
3: var right = tabNum + 1;
4: var top = tabNum - 4;
5: var bottom = tabNum + 4;
6:
7: if (Has16(left)){
8: Swap(tabNum, left);
9: return;
10: }
11:
12: if (Has16(right)) {
13: Swap(tabNum, right);
14: return;
15: }
16:
17: if (Has16(top)) {
18: Swap(tabNum, top);
19: return;
20: }
21:
22: if (Has16(bottom)) {
23: Swap(tabNum, bottom);
24: return;
25: }
26: }
27:
28: function Swap(tabLocation, Location16){
29: temp = tabs[tabLocation - 1];
30: tabs[tabLocation - 1] = tabs[Location16 - 1];
31: tabs[Location16 - 1] = temp;
32:
33: Show(tabLocation);
34: Show(Location16);
35: }
Step 6: Win Check and Congratulations message
Last but not the least, I wanted to do a win check and display a congratulations message if the player wins. If you want to create a modal window, just create a div section in the html file, and set it up as a dialog using jQuery. So here's my message (div section)
1:  <div id="Congratulations" title="Horray....">  
2: <p>Congratulations...p>
3: <p>You've won the game!!p>
4: </div>
Here's how I set it up as dialog:
1:  $("#Congratulations").dialog({  
2: bgiframe: true, autoOpen: false, height: 150, width: 300, modal: true, resizable: false
3: });
To open it,
1:  $("#Congratulations").dialog('open');  
Now, I was able to display a dialog using jQuery using one line of code.
Putting it altogether, I got an easy Number Sorting Game. I called it easy because lot of the things that were required were easily accomplised using jQuery. I, now, have learned and used jQuery in my own little game, and I personally think using it has some major advantages than merely using javascript. The code becomes short, easily readable and understandable.
This is just my first attempt, and I have learned quite a bit of jQuery, however, there is a lot more to it. Hopefully, I will come back to it again, and learn more...

For complete source code and live view, goto:
https://dl.dropboxusercontent.com/u/83502693/FifteenPuzzle.html

No comments:

Post a Comment