javaarraylistparameter-passingthisinstance-variables

Java arraylist does not keep values that I am passing inside a method


I am making an AI game where the cpu stacks N numbered cubes in a table in 3 rows using the Uniform Cost Search algorithm. What I'm trying to do is the generateMoves() method, which will return an ArrayList with all the possible moves from a given state.

Cube is a class representing a cube with its own ID (the number of the cube), X axis position and Y axis position.

K is user input

getCubes() is a method that returns an ArrayList<Cube> which is the current state of the table.

setCubes() is a method that takes an ArrayList<Cube> and sets that list as the current state.

isValid() is a Cube method that checks the copyOfTable list if the given cube is in a valid position.

isFree() is a Cube method that checks the copyOfTable list if the given cube is free to be moved.

public class Table{
  private fields

  constructor{}

  public Arraylist<Table> generateMoves(){
    Arraylist<Table> moves = new ArrayList<Table>();
    ArrayList<Cube> currentTable = this.getCubes();
    ArrayList<Cube> copyOfTable = new ArrayList<Cube>(currentTable);

    int X = 1;
    int Y = 1;
    int K = this.getK();

    for(Cube cube : currentTable){
      int backupX = cube.getPosX();
      int backupY = cube.getPosY();

      for(Y = 1; Y <= 3; Y++){
        for(X = 1; X <= 4*K; X++){
          cube.setPosX(X);
          cube.setPosY(Y);
          if(cube.isValid(copyOfTable) && cube.isFree(copyOfTable)){
            this.setCubes(currentTable);

            moves.add(this);

            moves.get(0).printTable();

          }else{
            cube.setPosX(backupX);
            cube.setPosY(backupY);
            continue;
          }
        }
      }
    }

    moves.get(anyIndex).printTable();

    return moves;
  }
}
// main is in a different file
main(){
  ArrayList<Table> moves = new ArrayList<Table>();
  Table table = new Table();
  
  moves = table.generateMoves();
}

What I want is the moves.add(this) to add the current state of the board in the moves arraylist, so that I can return all the tables (states) that are possible to be generated by the given table.

The problem is that the first printTable() (inside the 3rd for loop), prints every state that can be generated. Not only the first one that I ask it for.

The second printTable() (above the return statement), no matter the index, only prints the first state of the table.

What am I missing here?

I tried the above code


Solution

  • I don't know why (please someone explain that to me), but after i spent a very long time trial-and-erroring, the solution is to make a method that creates a "deep" copy of the ArrayList in question like so:

    private ArrayList<Cube> createCopyOfTable(ArrayList<Cube> toCopy){
            ArrayList<Cube> copy = new ArrayList<>();
    
            for(Cube cube : toCopy){
                Cube _cube = new Cube(cube.getID(), cube.getPosX(), cube.getPosY());
                copy.add(_cube);
            }
    
            return copy;
        }
    

    and the updated part on my generateMoves() method:

    .
    .
    .
    for(X = 1; X <= 4*K; X++){
        cube.setPosX(X);
        cube.setPosY(Y);
    
        ArrayList<Cube> copyOfTable = createCopyOfTable(currentTable);
    
        if(cube.isValid(copyOfTable) && cube.isFree(copyOfTable)){
            Table table = new Table(K);
            table.setCubes(copyOfTable);
                            
            this.moves.add(table);
        }else{
            cube.setPosX(backupX);
            cube.setPosY(backupY);
            continue;
        }
    }
    .
    .
    .