Search code examples
javafor-looparraylistcoordinatesspawn

Create arraylist of availableCoordinates


I am currently making a snake game and I don't want the apple to spawn inside my snake. I tried to fix this by doing this:


    ArrayList<Coordinate> availableCoordinates = new ArrayList<>();

    public void Coordinates() {


        for (int i = 0; i < numberOfSquaresY; i++) {
            for (int j = 0; j < numberOfSquaresX; j++) {
                availableCoordinates.add(new Coordinate(j*squareSize, i*squareSize, snake.get(0).color));
            }
        }

        for(int i = 0; i < availableCoordinates.size()-1; i++) {
            for (int j = 0; j < snake.size() - 1; j++) {
                if (availableCoordinates.get(i).xPos == snake.get(j).xPos && availableCoordinates.get(i).yPos == snake.get(j).yPos){
                    availableCoordinates.remove(i);
                }
            }
        }

    }

However only 1 value is getting removed even though it should be 3 that are getting removed, and I don't know why.


Solution

  • You iterate over availableCoordinates and inside this loop you remove items from it. So after you removed an element the following elements get a new index. The loop index is incremented anyways so you jump over an element after removing.

    I would not add all coordinates to the list and then remove the used ones. While filling your availableCoordinates check if this field is free:

    for (int i = 0; i < numberOfSquaresY; i++) {
        for (int j = 0; j < numberOfSquaresX; j++) {
            Coordinate c = new Coordinate(j*squareSize, i*squareSize, snake.get(0).color);
            if (!snake.contains(c)) {
                availableCoordinates.add(c);
            }
        }
    }
    

    assuming that Coordinate#equals only checks xPos and yPos.

    EDIT: If you cannot use contains you have to create a 3rd for level to iterate through your snake's elements:

    boolean doIt;
    for (int i = 0; i < numberOfSquaresY; i++) {
        for (int j = 0; j < numberOfSquaresX; j++) {
            Coordinate c = new Coordinate(j*squareSize, i*squareSize, snake.get(0).color);
            // reset flag for each coordinate
            doIt = true;
            for (Coordinate bodyElement : snake) {
                if (c.xPos == bodyElement.xPos && c.yPos == bodyElement.yPos) {
                    // coordinate is used by snake
                    doIt = false;
                    // no need to check other body elements
                    break;
                }
            }
            if (doIt) {
                availableCoordinates.add(c);
            }
        }
    }