Fifteen Puzzle

Code

Jon says:

I've been doing more programming, and wanted to share my latest project with TuxRadar readers (if only because everyone else is tired of listening!). It's a simple implementation of the 'Fifteen' puzzle in Javascript and HTML5 canvas. You can check it out here, so if you want to try it, go ahead. Feedback and comments are welcome, especially about the quality of my code (I expect it's low quality, so be constructive!).

My current plan is to re-implement as many of Simon Tatham's Portable Puzzle Collection in Javascript as I can (without reading the code, of course, just using the games as inspiration). It's a great collection, so do take a look at the originals too.

Happy hacking...

You should follow us on Identi.ca or Twitter


Your comments

Doesn't work in Links!

Am I going to have to upgrade to one of those new-fangled browsers like Mosaic?!?

Mike

Feedback

Nice work. I was very disappointed that I got no reward for solving it, though!

Less clicking would be required if clicking on a tile in the empty space's row or column would move that tile and all the tiles in between into the space, like they're being shoved along together in one go.

Also, I challenge you to implement the same thing using QtQuick. It's also Javascript-based, but I'd say you'll find it significantly easier to work with than HTML5, and you'll be able to add animations almost for free.

HTML5 is cool; but it's still fundamentally a content language, not a UI language. Intel has me all worked up because of this Tizen business. Bad, bad idea in my book. HTML5 is not a miracle technology.

Nice!

Out of curiosity, why canvas for this particular game? I'd've recommended using elements positioned absolutely (within a container with "position: relative", of course). That way, you could even use the new CSS3 transitions to actually "slide" the elements. :)

Regarding the code... All of your functions are global. You probably want to wrap all of it in something like this:

(function() {
this.Tile = {
initialize: function() { // constructor

},

public: function() {

}
};

var private = function() {

};

var privateVar = 123;
})(window);

That way, you can have private methods. It's also just good practice to keep the global object clean -- as few new members as possible. That's why I'd recommend using a single object, which contains the methods you're after.

Anyway, I didn't mean this comment to turn into a lecture on JS coding styles, but coding in JS is my day-job, so I guess it was inevitable. :P Nice work, though -- I look forward to more of your re-implementations!

Thanks :-)

Thanks for the feedback :-)

Re Paul: I'll try and add some kind of reward for solving - at least an alert('congratulations')!

The reason I'm interested in learning Javascript + HTML5 is that it seems more universal to me. The same website, with a bit of care, can work on mobile, tablet and desktop, no matter which OS. Plus, with Gnome, KDE + Windows 8 supporting Javascript, it's a good language to learn, no matter what I pair it with. Plus, and this is a bad reason, I guess it seems like it's 'cool', it's got a lot of momentum really.

Re barryvan: I guess I used canvas because it's the cool thing to do! I never even thought about css transitions, that would have been nice (although I don't think it would have been too difficult to add in JS anyway).

Also, if you could point me in the direction of some resources about JS style and private methods, that would be great. I've not come across it in my reading about JS, and only have a vague understanding of it in other languages like Java.

Thanks again for the feedback!

Crock's your man

Re Jon: Doug Crockford's your man. :) Check out the videos on [http://yuiblog.com/crockford/] and his main site [http://crockford.com/javascript/].

JavaScript doesn't actually have private members per se -- rather, it has closures. Closures function because an inner function has access to all of its containing function's variables. That is to say, in the following expression:

var f = (function() {
var private = 2;
return function(n) {
return private * n;
}
})();

we have two functions. The outer function, which is anonymous, is immediately invoked; this means that the inner function (which takes an argument) is assigned to "f". If I were to call f(4), the result would be 8; if I were to call f.private, the result would be undefined. In other words, it's not possible to get to the "private" variable except through the internal function.

Generally speaking, if you're not writing code that's going to be consumed in environments you don't control, it's enough to follow convention, and simply prefix methods that should be *assumed* private with an underscore. This doesn't actually change the method at all (you can still access it), but it clearly distinguishes the public methods from your "private", internal methods.

Regarding contaminating the global object: this can be dangerous for a number of reasons. The most commonly-cited is that you may run your code on another page; for example, you might create a single HTML page that contains all of your games. What happens when both of them declare a function called "start", for example? The last one takes precedence. You also have odd browser behaviours -- for example, elements with IDs can become globals. That's why it's recommended to have as few global members as possible, and use an object to namespace your code.

Incidentally, I've noticed that the code I posted earlier has some errors -- it should look more like this:

(function() {
// Establish namespace
this.jon = this.jon || {};

this.jon.fifteen = {
init: function() { },
foo: function() { },
bar: function() { }
}

})();

Sigh. This comment turned into a lecture again. :P

Liking Crock'

I just looked through some of those resources. They're definitely interesting.

I'll have to take a proper look over the next few weeks and play around to get a feel for how closures and the whole private/privaleged thing works in practice.

Thanks a lot though :-) Since I'd been doing some Scheme recently I was really pleased to hear Crockford say that JavaScript is very similar to Scheme!

Liked it...

Simple and effective. Good one. Wish I was that clever...

Bazza, G0LCU...

Post new comment

CAPTCHA
Fill in this captcha, or you shall be mocked mercilessly.
Username:   Password:
Create Account | About TuxRadar