Javascript Snake
I made a Javascript version of that ubiquitous snake game. Why? Well certainly not because the world is lacking of Javascript based Snake games. I came across a copious amount of free time at work today and feeling that I had to code something while at work I figure a snake game would be straight forward(ish).
Displaying The Snake:
The basic premise is the following grid (where yellow represents the snake and green represents the snake head):
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
| 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
To appear to move the snake you manipulate the head (27) and tail (22) cells by changing its colour. For example to move up colour cells 17, 22, and 27 green, white, and yellow respectively. I’m more than sure there’s a name for this kind of ‘illusion’.
Changing the colour is as simple as changing the cell’s background-color property.
Surprisingly the biggest hurdle that I had to overcome was coming up with the HTML to make the grid. I tried using a bunch of <div>s and aligning them with float:right but of course I couldn’t get that to work across browsers. The Designer helpfully suggested that I just use a good old fashioned <table> and lo and behold that worked beautifully!
Moving The Snake:
The snake’s cell numbers are stored internally in a deque. When the snake moves push the new head and pop the old tail.
get new head position
if new head position is the wall or the snake itself
end the game
else
if new head position is food
place food in a new position
grow the snake
update the score
else
remove the tail from the snake deque
add the new head position to the snake deque
Determining The New Head Position:
The new head position is determined by the current direction of the snake. For example in the grid above the new head positions would be 17, 28, and 37 for up, right, and down respectively. Note that left is an invalid direction. The current direction is controlled by whatever arrow the user presses during the game. Of course you want to check if whatever the user presses is a valid direction.
Anyways… play the game. Let me know what you think…
Sometimes You Can Please All Of Them
Attention all future potential users of The Project who for some reason or another choose to browse with scripting off: The Project, as it stands now, will still be fully functional. Sure it won’t be as pretty or slick but it’ll still work.
And for all future potential users with scripting on: All of you will have the pleasure of The Project running some of the most consise Javascript I’ve ever written. And it’s all because of JQuery. I haven’t fallen this much in love with a framework since I met Hibernate a few months ago…
Three Hours For A Pair Of Square Brackets
The Project has this one particular form with a set of ‘Yes’/'No’ radio buttons and a <textarea> element.
The Client wanted the ‘Yes’ radio button automatically checked whenever a user enters some text in the <textarea> and the ‘No’ radio button to do the same thing when a user erases said text.
Solution: Attach an onChange()* onBlur() event handler on the <textarea>. Everytime the event is fired set the radio buttons based on the <textarea>’s value.
I knew how to do this in plain vanilla Javascript but I’m drinking the JQuery kool aid nowadays so off to figure out how to jquery-select a radio button.
Three hours later I finally figured it out. Here’s a quick summary of those three hours:
- 2 hours 59 mins wondering why
$('input[name=YesNoRadioButton]‘).val(radioValue)wasn’t working - 30 seconds to read in The Official JQuery Docs that the correct way is
$('input[name=YesNoReadioButton]‘).val([radioValue]) - 30 seconds to implement the ‘correct way’
And that’s what bugs me about JQuery. It possesses great power but with great power comes great… reading of sh*tloads of blogs tagged with ‘jquery’ in order to try to figure out your JQuery problem.
* Pointless because there’s no onChange() event handler for a <textarea> element
Two Questions
Question #1: How do I close a Javascript popup window using an anchor tag without putting the closing event inline?
The Project has a set of pages that open as pop up windows via Javascript. Each of these pop up windows have a link that enables it to close itself (again via Javascript). Something like this:
<a href = "javascript:window.close()">link</a>
I want to remove that Javascript function and use that JQuery ready function to bind the click event. If scripting is disabled then the link would direct to another page. Something like this:
<a href = "<url to load when scripting is disabled>"
name = "PopUpClose">link</a>
$(document).ready(function()
{
$('a[name=PopUpClose]').click(closePopUpWindow);
});
function closePopUpWindow()
{
window.close('<window name>');
return false;
}
However that doesn’t work for me. I have to resort to this:
<a href = "<url to load when scripting is disabled>"
onClick = "javascript:window.close('<window name>');
return false;"
name = "PopUpClose">
Yeah it works (with and without scripting enabled). But still how do I remove that onClick event from the HTML?
Question #2: How do I determine if a page was referred from a HTTPS page?
This question is related to the first one. When scripting is disabled, my ‘pop up’ windows above are just regular pages. On the closing link I want to link back to the page that opened the pop up window (ie. $_SERVER['HTTP_REFERER]‘).
However whenever I open the ‘pop-up-but-not-really-when-scripting-is-disabled’ page from a https page, $_SERVER['HTTP_REFERER'] is null. And as far as I know there’s no such thing as $_SERVER['HTTPS_REFERER'].
So how do I emulate $_SERVER['HTTP_REFERER'] for https pages?
Avoiding The Flicker
A major part of gracefully degrading The Project is hiding blocks on a page load by Javascript. For example suppose I have a set of radio buttons. Each radio button has a block associated with it. A block’s visibility depends on whether its radio button is checked. The idea is that if Javascript is enabled then those blocks could toggle its visibility via script. If Javascript is disabled then although those blocks would not be able to toggle, they also would not be hidden in the first place thus still being visible to the user.
Like all things initially the this seem fairly straightforward. Just add an onLoad() event to the block I want to hide and when the event is fired (ie. when the page is loaded) hide the block:
$('#block-you-want-to-hide').load(function()
{
$(this).hide();
});
And of course something is wrong. When the page loads the blocks I want to hide appear for a split second then gets hidden. In other words the blocks ‘flicker’:
… between the point of your HTML that is to be hidden, and the point where your JavaScript library has been completely included and then found the element(s) to hide, there is a possible discrepancy which will result in “jumping” pages; i.e. you will get a flicker temporarily showing the content, and then hiding it.
Naively I thought that JQuery’s ready() function would take of this but surprisingly that’s not the case.
Anyways here’s the hack / fix that I found:
- Create a Javascript anonymous function which appends a css file to the document’s
<head>element(function () { var headElement = document.getElementsByTagName('head')[0]; var headExists = (headElement != null); if (headExists) { var cssLink = document.createElement('link'); cssLink.rel = 'stylesheet'; cssLink.type = 'text/css'; cssLink.href = 'your-flicker-hack.css'; headElement.appendChild(cssLink); } }()); - The external css file sets the blocks you want to hide
div#block-you-want-to-hide-on-load { display: none; }
OK I won’t even pretend that I understand how the above works or even why it works. All I know is that it works. Period. Full Stop.