0

I am attempting to make the classic snake game in p5.js. I have a snake object and I'm storing the locations of its body in a 2d array, this.data, where each element stores an x value and a y value (at index 0 and 1 respectively). As the snake moves, I push new positions into the array.

I ran into a problem when I tried to detect whether or not the snake had run into itself. What I tried to do was test whether its current position was already in the array using indexOf, reasoning that if the new location was open, it would only occur once in the array, at index one less than the array's length. Otherwise, if the location already existed elsewhere in the array (indicating the snake had run into itself), it would return a value less than the length minus one.

However, this doesn't seem to be happening.

function Snake()
{
    this.x; //x-coordinate of head
    this.y; //y-coordinate of head
    this.dx; //velocity in x-direction
    this.dy; //velocity in y-direction
    this.length; //length of snake
    this.data; //stores all locations snake occupies
    this.alive = 1; //is the snake alive?

    this.update = function(board)
    {
        if (this.alive)//update head position
        {
            this.x += this.dx;
            this.y += this.dy;

            let tempCoords = [this.x,this.y];
            this.data.push(tempCoords);

            while (this.data.length > this.length) //janky
            {
                this.data = this.data.slice(1);
            }

            if (this.data.indexOf(tempCoords) + 1 != this.data.length) //make sure snake hasn't hit itself
            {
                this.alive = 0;
            }
        }

    }
}

The final if statement always evaluates false even when the snake intersects itself. From the testing I've done, this seems to be an issue with using indexOf on multidimensional arrays. What solutions are there to this problem?

  • `indexOf()` compares `searchElement` to elements of the Array using strict equality (the same method used by the `===` or triple-equals operator). And that won't work for comparing arrays. Note the `this.data` holds arrays with a pair of values. – Shidersz Jun 12 '19 at 21:19
  • 2
    Possible duplicate of [Javascript 2d array indexOf](https://stackoverflow.com/questions/24943200/javascript-2d-array-indexof) – Heretic Monkey Jun 12 '19 at 21:21

2 Answers2

0

indexOf uses an equality check to find the index, and

  [0, 0] === [0, 0]

is false, as objects (and arrays are objects), are compared by reference (and you do have two different arrays). To compare them by their inner values you have to manually check the x and ys against each other:

  const collides = this.data.some(coords => coords[0] === this.x && coords[1] === this.y);
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
0

Essentially, you have the following data and you want to see if the data in head is equal to any of the elements in points

var points = [[1,1],[1,2],[1,3]]
var head = [1,2]

You can check for any matches in an array using Array.some() like this:

var overlap = points.some(p => p[0] === head[0] && p[1] === head[1])

var points = [[1,1],[1,2],[1,3]]
var head = [1,2]

var overlap = points.some(p => p[0] === head[0] && p[1] === head[1])

console.log(overlap)
KyleMit
  • 30,350
  • 66
  • 462
  • 664