Snake Game – eat the food but dont spawn another (javascript)

Tags: , ,



I have a snake game made using JavaScript using Node.js and sockets.

When a food spawns, I want there to be a 21/25 chance it being green, a 3/25 chance of it being red, and a 1/25 chance of it being yellow.

If there is more than 1 food in the array and the player eats a green one, I want it to disappear.

And:

  1. If a player eats a green food, they gain 10 points and another food spawns.

  2. If a player eats a red food, the player gains 50 points and 3 green food spawn.

  3. If the player eats a yellow food, they gain 200 points and 5 green food spawn.

It’s working fine, except for when there’s more than 1 green food on the screen and the player eats one, sometimes several food disappear or sometimes they all disappear.

Why is this happening?

var FoodList = [];
SpawnFood(10, 1); //Spawn a default peice of food


function SpawnFood(Value, Amount) //Add a Food to the board
{
    for (var i = 0; i < Amount; i++) {
        var j = i;

        if (FoodList.length == 0) {
            FoodList[j] = new Food(); //If there is no food in the array, spawn one
            FoodList[j].init();
            FoodList[j].FoodValue = Value;
            j++
        } else { //if there is food in the array
            while (FoodList[j] !== undefined) { //choose the lowest empty place
                j++
            }
            FoodList[j] = new Food(); //And then spawn in
            FoodList[j].init();
            FoodList[j].FoodValue = Value;
        }
    }
}

//Collision detection below :

for (var i in SnakeList) //For each instance of snake
{
    var snake = SnakeList[i]; //Declare snake as the current snake

    for (var j in FoodList) //For each instance of Food
    {
        if (snake.hasColision(FoodList[j])) //If they have collided
        {
            snake.addLength(); //Removes the Food and adds length to the current snake
            snake.eatFood(FoodList[j]); //Rewards the player with score)

            var Value = FoodList[j].FoodValue; //Asking it what score value the food has
            delete FoodList[j]; //Deletes that food

            var count = 0;
            for (var s in FoodList) //For each instance of Food
            {
                count++;
            } //Counts how many peices of food are in the array (.length doesnt work)

            if (Value == 10) { //If the player ate a green food

                if (count < 1) { //And theres more than 1 food in the array

                    var RandomNumber = Math.round(Math.random() * (25 - 1) + 1); //Generate a random num

                    if ((RandomNumber >= 1) && (RandomNumber <= 21)) //common drop, green food
                    {
                        SpawnFood(10, 1); //Soawn green food
                    } else if ((RandomNumber >= 22) && (RandomNumber <= 24)) //rare red
                    {
                        SpawnFood(50, 1); //spawn red
                    } else {
                        SpawnFood(200, 1); //spawn very rare yellow
                    }
                }

            } else if (Value == 50) { //If the player ate a red, spawn 3 green
                SpawnFood(10, 3);
            } else if (Value == 200) { //If the player ate a yellow, spawn 5 green
                SpawnFood(10, 5);
            }
        }
    }
}

Answer

Here is how you should do it: (I don’t know about SnakeList but it should be an array as well, if it’s not then follow the same approach as for FoodList)

var FoodList = [];
SpawnFood(10, 1);


// remove food from index
function removeFood(index){
    // cut that element out of the array (Read more about splice)
    FoodList.splice(index, 1);
}

// spawn an amount of food by calling spawnOneFood an amount of times
function SpawnFood(Value, Amount) {
    for (var i = 0; i < Amount; i++) {
        // create a new food
        var f = new Food();
        f.init();
        f.FoodValue = Value;

        // add it to FoodList
        FoodList.push(f);
    }
}

// get random value (it good practice to split diferent logics into diferent function)
function getRandomValue(){
    var RandomNumber = Math.round(Math.random() * (25 - 1) + 1);

    // no need to check if it's greater than 1 (it is)
    if (RandomNumber <= 21)
        return 10;
    // no need to check if it's greater than 22 (it is)
    else if (RandomNumber <= 24)
        return 50;
    // no need for else (if we are here then the above tests failed) (if you get a yellow food go straight to a casino because you're lucky as hell)
    return 200;
}

// SnakeList should be an array too. (for(var i = 0; i < SnakeList.length; i++))
for (var i in SnakeList)
{
    var snake = SnakeList[i];

    for (var j = 0; j < FoodList.length; j++) //For each instance of Food
    {
        if (snake.hasColision(FoodList[j]))
        {
            snake.addLength();
            snake.eatFood(FoodList[j]);

            var Value = FoodList[j].FoodValue;
            removeFood(j);
            j--; // removeFood actually shrinks the array so we need to go backwards one step to handle all elements

            // This should work now
            var count = FoodList.length;

            if (Value == 10) {

                if (count < 1) {
                    var randomValue = getRandomValue();
                    SpawnFood(randomValue, 1);
                }

            } else if (Value == 50) {
                SpawnFood(10, 3);
            } else if (Value == 200) { // as I said: LUCKY AS HELL
                SpawnFood(10, 5);
            }
        }
    }
}


Source: stackoverflow