0

I'm working with students to make a snake game, and we are just about finished but the last thing we added does not work: if the snake collides with itself, it doesn't end the game! The logic behind the check is correct, and it seems to be more reliable at a lower framerate, though it still does not work correctly at all times.

The code to detect the collision is in draw(), and is written as:

    System.out.println("headX: " + x.get(x.size()-1) + "\theadY: " +y.get(y.size()-1));
    for (int i=0; i < x.size()-1; i++) {
      System.out.println("i: " + i + "\tx: " + x.get(i) + "\ty: " + y.get(i));
      if ((x.get(x.size()-1) == x.get(i)) && (y.get(y.size()-1) == y.get(i))) {
        println("=======================================");
        alive = false;
        textSize(90);
        text("YOU LOSE", 300, 400);
      }
    }

This includes some print statements I've added to check, and it does in fact have the condition in the if statement be satisfied without executing the code inside the if statement.

The snake is saved in an arraylist as a series of x and y coordinates, and a rectangle is drawn from each of them. This for loop is supposed to check the coordinates of each of the snake pieces except for the head and compare it to the head. Even when it is true, the code does not always execute.

Here is the entire code, written in the Processing IDE

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
boolean moveRight = true;
boolean moveLeft = false;
boolean moveUp = false;
boolean moveDown = false;
boolean alive = true;

Random food = new Random();
int foodX = food.nextInt(100)*10;
int foodY = food.nextInt(100)*10;

ArrayList<Integer> x = new ArrayList<Integer>(Arrays.asList(0, 10, 20, 30, 40, 50, 60, 70, 80, 80, 70, 60, 50, 40, 30, 20, 20));
ArrayList<Integer> y = new ArrayList<Integer>(Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 20));
void setup() {
  size(1000, 1000);
  frameRate(60);
}
  void draw() {
    if (alive) {
      background(242, 195, 53);
      if (moveRight) {
        int headX = x.get(x.size()-1)+10;
        int headY = y.get(y.size()-1);
        x.add(headX);
        y.add(headY);
        //if you eat food, stuff below is false
        if (headX != foodX || headY != foodY) {
          x.remove(0);
          y.remove(0);
        } else {
          updateFood();
        }
      }
      if (moveLeft) {
        int headX = x.get(x.size()-1)-10;
        int headY = y.get(y.size()-1);
        x.add(headX);
        y.add(headY);
        if (headX != foodX || headY != foodY) {
          x.remove(0);
          y.remove(0);
        } else {
          updateFood();
        }
      }
      if (moveUp) {
        int headX = x.get(x.size()-1);
        int headY = y.get(y.size()-1)-10;
        x.add(headX);
        y.add(headY);
        if (headX != foodX || headY != foodY) {
          x.remove(0);
          y.remove(0);
        } else {
          updateFood();
        }
      }
      if (moveDown) {
        int headX = x.get(x.size()-1);
        int headY = y.get(y.size()-1)+10;
        x.add(headX);
        y.add(headY);
        if (headX != foodX || headY != foodY) {
          x.remove(0);
          y.remove(0);
        } else {
          updateFood();
        }
      }

      drawFood();
      fill(25, 62, 125);

      for (int i=0; i < x.size(); i++) {
        rect(x.get(i), y.get(i), 10, 10);
      }
      if (x.get(x.size() -1) >1000 || y.get(y.size()  -1) > 1000 || x.get(x.size() -1) < 0 || y.get(y.size() -1) < 0) {
        textSize(90);
        text("YOU LOSE", 300, 400);
        fill(255, 255, 255);

        alive = false;
      }
      System.out.println("headX: " + x.get(x.size()-1) + "\theadY: " +y.get(y.size()-1));
      for (int i=0; i < x.size()-1; i++) {
        System.out.println("i: " + i + "\tx: " + x.get(i) + "\ty: " + y.get(i));
        if ((x.get(x.size()-1) == x.get(i)) && (y.get(y.size()-1) == y.get(i))) {
          println("=======================================");
          alive = false;
          textSize(90);
          text("YOU LOSE", 300, 400);
        }
      }
    }
  } 



  void keyPressed()
  {
    if (key == 'd') {
      if (!moveLeft) {

        moveRight = true;
        moveLeft = false;
        moveUp = false;
        moveDown = false;
      }
    }
    if (key == 'a') {
      if (!moveRight) {
        moveLeft = true;
        moveUp = false;
        moveRight = false;
        moveDown = false;
      }
    }

    if (key == 'w') {
      if (!moveDown) {
        moveUp = true;
        moveLeft = false;
        moveDown = false;
        moveRight = false;
      }
    }
    if (key == 's') {
      if (!moveUp)
        moveUp = false;
      moveLeft = false;
      moveDown = true;
      moveRight = false;
    }
  }
  void drawFood() {
    fill(255, 12, 12);
    rect(foodX, foodY, 10, 10);
  }
  void updateFood() {
    foodX = food.nextInt(100)*10;
    foodY = food.nextInt(100)*10;
  }

EDIT: Integers do not reliably work with ==, they must use .equals. Check out this question: Java: Integer equals vs. ==

a0935
  • 81
  • 6
  • You really shouldn't teach writing that long methods to students. Use private methods and name them properly. – A1m Jul 13 '17 at 21:09
  • Agreed. Your `if (moveRight) {` sections are each almost identical, so they should be moved into a separate method and combined into a single function depending on a parameter. No sense having similar code all over the place when it can be in one place. Even so, they should be `else if`s afterwards unless they could move diagonally or something. – mbomb007 Jul 13 '17 at 21:12
  • I agree, this is my first time teaching and juggling 8 students is an art. They do some work on their own and then I come along to help them, I will have to be more firm in the future about proper structure. Thank you for the advice! – a0935 Jul 13 '17 at 21:13
  • You shouldn't use `==` to compare objects (Integers). Use `equals` (that's not probably the problem, but anyway) – leonbloy Jul 13 '17 at 21:18

1 Answers1

1

Integers do not always work with ==, but rather must use .equals. Changing

if(x.get(x.size()-1) == x.get(i)) && (y.get(y.size()-1) == y.get(i))

to

if(x.get(x.size()-1).equals(x.get(i))) && (y.get(y.size()-1.equals(y.get(i)))

solved the problem

a0935
  • 81
  • 6
  • Note that you should probably be using a single `ArrayList` of `PVector` instances, which would eliminate this problem altogether. – Kevin Workman Jul 13 '17 at 21:22