jQuery Memory Game

jQuery Memory Game

So, there I was, trying to remember the idea I had gotten for a blog post. Some snippet or other of jQuery or PHP had been floating through my head recently and I was sure it was going to win me the Pulitzer Prize For Technical Blogging. Except, as with most great ideas, I assumed that I would remember it and didn’t write it down. It was, after all, the Greatest Idea EVAR!

Seeing as how I was boneheaded and had forgotten it completely, I started casting around for another idea, and that was when it hit me. What better thing to code when my memory is failing me, than the classic ‘Memory Game’?! So, armed with Yet Another Great Idea, I dove into vim to make the magic happen.

It must be noted that I did hit a huge roadblock right in the middle of the development of this, and I have to thank Ryan Neufeld for looking at the problem with fresh eyes and handing me an elegant solution for something I was doing with the DOM.

Brief explanation of the plugin, after the jump…

I’ll give you a general overview of the logic behind the game and some of its features, rather than doing a very detailed explanation/tutorial of how the game was built. However, vox populi and all of that, if it’s requested I will be happy to write out the tutorial in full to explain every step of the game.

Basically, the premise of the game is simple. You have a layout of tiles, all identical, and you turn the tiles over to reveal symbols. When you find a pair of symbols, you can remove those tiles from the board. When you remove all the tiles, you win the game. Unlike many single-player card games like Solitaire, you quite literally cannot lose this game. It would be like failing an IQ test. This makes the memory game an attractive candidate for playing, and coding.

Looking at the strategy for how to put this game together, I realized that there were five main conditions I had to fulfill:

  1. I needed to build the layout of the tiles, all face-down. The tiles needed to be shuffled in a random order, so that pairs have to be hunted for. It’s a simple enough game as it is, we don’t want to make it insulting by putting all the pairs together, do we?
  2. You need to be able to reveal one tile at a time, in sets of two.
  3. If the pair of tiles revealed matches, it needs to be removed from the board.
  4. If the pair of tiles does not match, they need to be turned back over.
  5. If all pairs have been removed, recognize that the game is over

Now, it would be very simple to build this wretchedly, injecting a lot of HTML into the jQuery code, wickedly traversing the DOM from end to end at every opportunity, and complicated iterations. It would also be very tempting to over-spec this game, including things like the (incredibly brilliant) Isotope plugin to animate the movement of the cards, even adding CSS3 tranforms to rotate the cards in some manner.

I chose, instead, a middle ground. I was striving to not over-complicate this mini-project, but also to write some solid code at the same time. Also, there is a quote somewhere about everytime you interpolate HTML into your jQuery, John Resig cries. (You don’t believe me? See here.) I wanted to avoid the tears of Mr. Resig as much as possible, as well as not hashing about with unnecessary crap when I didn’t need to.

I decided on some ground rules for myself. I would use CSS classes as flags on my tiles. I needed to flag tiles that were being turned over, tiles that had been removed from the board. Sure, I could get all fancy and use data attributes or get really kludgy and use global arrays or something like that. I wanted a more…straightforward approach.

Where possible, I wanted to keep the code as DRY as possible. So, that meant modules to perform certain tasks like revealing and clearing the tiles. The other big consideration that I had in doing this plugin was that ultimately, it was for the USER, not the KODER. It didn’t mean much if the code on the back-end was the most semantically and syntactically perfect thing that had ever been written, if the game wasn’t pleasant to play.

Okay, let’s be fair. It wouldn’t mean much to everyone ELSE. To me, having semantically and syntactically perfect code would be everything.

I decided to use a

    to hold the tiles. Each
  • would have its image stored as a background image, and there would be an tag in the
  • which would fade in and out to do the reveal of the tile. Some setTimeout foo was needed in order to not have the tiles flash too fast. And just for decoration’s sake, I built this demo with the really cool ‘Devine Icons Part 2‘ set by ipapun at DeviantArt.

    Please check out the demo, the jquery source, the minified, or the whole enchilada.

    Another note: In typical plugin fashion, you can change a few settings on the game. Pass in an object with any of the following parameters:

    tileCount – Number of tiles total in the game. Pairs will be determined by dividing this in half. Values that aren’t evenly divisible by two are not advised.

    delay – Number of milliseconds between when tiles are flipped and when they flip back over or are cleared (assuming match)

    timeout – Number of milliseconds between when the first tile is clicked and when the game decides it is tired of waiting for you to click the second one, and flips the first back over.