# A question about the logic of making a "Snake" game

1. May 31, 2014

### Jamin2112

I've started to make a "Snake" game (example: http://www.kongregate.com/games/uchiha/classic-snake-game) and reached a dead end. I'm not sure the programmatically best way of figuring out where the snake's "food" should next appear. It should of course appear anywhere on the screen that doesn't collide with the snake. I therefore think there are 2 procedures:

• (1) Pick a random location on the screen. If this location lies somewhere on the snake, then pick another random location. Do this until you find a proper location.
• (2) Use the positions of the links that compose the snake to figure out a proper next random location for the food.

The first one is inefficient, especially when the snake is long. The second one, I don't know how to write. Any ideas for how I can write the second one?

By the way, here's what I have so far:

The snakegame class is: jaminweb.com/Snakegame.html

Code (Text):

\$(document).keydown(function(e)
{
switch(e.which)
{
case 37: // left arrow key
s.redirect(3);
break;

case 38: // up arrow key
s.redirect(4);
break;

case 39: // right arrow key
s.redirect(1)
break;

case 40: // down arrow key
s.redirect(2);
break;

default: return; // exit this handler for other keys
}
e.preventDefault(); // prevent the default action (scroll / move caret)
});

function snakegame(C, C_h, C_w)
{
/* NOTE TO SELF: C is a Raphel object. Can't find a method to return the height
and width of a Raphael object in the documentation:
[PLAIN]http://raphaeljs.com/reference.html#Raphael.[/PLAIN] [Broken]
Using C_h and C_w for now, but should probably change it later.
*/

this.linkSize = 30; // size of a snake unit, in pixels

this.food.attr("fill","#39275b")
this.food.glow();

/* On instantiation, the snake direction is down and has 1 link */
this.dx = 0;

/* Event listener for changing the direction of the
snake with arroy keys on the keyboard
*/
this.redirect = function(dirnum)
{
switch (dirnum)
{
/*
dirnum corresponds to
1 ---> right
2 ---> down
3 ---> left
4 ---> up
*/
case 1:
this.dy = 0;
break;

case 2:
this.dx = 0;
break;

case 3:
this.dy = 0;
break;

case 4:
this.dx = 0;
break;

default: // never happens
break;
}

}
this.move = function()
{
/*
..........
*/
var temp = this.body[0];
var BBhead = temp.getBBox();
if (BBhead.x < 0 || BBhead.x2 > C_w || BBhead.y < 0 || BBhead.y2 > C_h)
{
clearInterval(mover);
return;
}
var BBfood = this.food.getBBox();
{
this.moveFood();
}
this.body[0].translate(this.dx, this.dy);
for (var i = 1, j = this.body.length; i < j; ++i)
{
this.body[i] = temp;
temp = this.body[i];
}
}

var mover = setInterval(this.move.bind(this), 300);

{
}

this.moveFood = function()
{

}
this.boxCollision = function(A, B)
{
return A.x > B.x && A.x < B.x2 && A.y > B.y && A.y < B.y2;
}

}

It's messy, but hopefully you can see my intent and give me some ideas for how to build off what I have now.

Last edited by a moderator: May 6, 2017
2. May 31, 2014

### interhacker

The first method should be fine, really. I've made a similar snake game in html5 with method 1. Works perfectly.

Modern PCs don't lag much when computing a single random number.

3. May 31, 2014

### DavidSnider

Instead of doing it purely random you should pick a random point in the array and forward-seek until you find a free space. This way the upper bound is N rather than unknown. That and you don't waste cycles generating random numbers.

4. May 31, 2014

### Jamin2112

Then the piece of food will always be right near the snake. He'll be stuck in one area of the screen because the piece of food will always appear next to one of his units.

5. May 31, 2014

### DavidSnider

The vast majority of the time the initial space chosen will be empty, when the screen is mostly filled it's always going to be near the snake anyway. You could add a random jitter factor that says "pick the nth open spot you find" where n is a random number. You can also pick a random seek direction for less predictability.

Last edited: May 31, 2014
6. May 31, 2014

### AlephZero

You could forward-seek in steps of p locations, where p is relatively prime to the size of the playing area.

That will step through all the board locations in sequence, but in pseudo-random order.

For "more randomness", look up the "quadratic probing" technique for dealing with collisions in hash tables.