3

I'm working on generating a game tree.

My problem I enter is that when I copy an object to a new object, and then makes changes in the new object, the old object also changes it's values.

So it seems to be a reference problem.

But how do I make the new object an independent instance.

after creating this child object copied from parent, and then changing values in the child object, the parent object is also changed and in the end of the method it will print that the objects is equal.

private void generateSubTree(State parent, int depth) {
    if (depth == 0) {
        System.out.println("End of leaf..!");
        return;
    }
    ArrayList<State> listOfStates = GameEngine.legalMoves(parent);
    for (State s: listOfStates) {
        Board tempBoard = new Board(parent.getBoard().getBoard());
        BoardPiece pieceRef = new BoardPiece();
        State child = new State(parent);
        if(parent.getTurn() == 0) {
            pieceRef = GameEngine.checkForPiece(child.getPlayer1(), s.getMove().getFromX(), s.getMove().getFromY());
            pieceRef.updatePosition(s.getMove().getToX(), s.getMove().getToY());
            tempBoard.updateBoard(child.getPlayer1(), s.getMove(), false);
        } else {
            pieceRef = GameEngine.checkForPiece(child.getPlayer2(),  s.getMove().getFromX(),  s.getMove().getFromY());
            pieceRef.updatePosition(s.getMove().getToX(), s.getMove().getToY());
            tempBoard.updateBoard(child.getPlayer2(), s.getMove(), false);  
            }
        child.setBoard(tempBoard);
        parent.addChild(child);
        System.out.println("Is parent equal to child: " + child.equals(parent));
        i++;
        System.out.println("States generated: " + i);
        generateSubTree(child,depth-1);
    }

}

public class State{

private Board board;
private int turn;
private Move move;
private ArrayList<Move> legalMoves;
private int depth;
private int utilityVal;
private Player player1;
private Player player2;

private State parent;
private ArrayList<State> children;

public State() {
    children = new ArrayList<>();
}

// Copy constructor
public State(State state) {
    this.parent = state.parent;
    this.depth = state.depth;
    this.board = state.board;
    this.children = state.children;
    this.turn = 1 - state.turn;
    this.player1 = state.player1;
    this.player2 = state.player2;
    // shallow copy
    // this.subjects = student.subjects;

    // deep copy - create new instance of HashSet
//  this.subjects = new HashSet<>(state.subjects);
}

The expected result is that I can change the object Child without changing Parent

MaskinMichael
  • 33
  • 1
  • 4
  • 4
    Welcome to Stack Overflow. Please could you post a [mcve]? At the moment we don't know which parts of the objects are shared, or which state you're having problems with. – Jon Skeet Apr 01 '19 at 14:06
  • 1
    I wonder why the child class has the same field values as the parent... like the children of the parent are also the children of the child??? or the parent of the child is the same as the parent of the parent. Anyway you should explain which object is being changed , how it is being changed and what is expected/happening. (as indicated in your code, deep copy may be of help) – user85421 Apr 01 '19 at 14:20

2 Answers2

2

But how do I make the new object an independent instance.

Remove the static keyword to make the fields inside the object independent from other objects.

If a field/variable is static it shares its value with all instances of the class. If you change one of them you change the value for all of the instances.

I think the main problem is your copying of State objects. You do not really copy anything you only pass the references to another instance.

You need a deepCopy method which also copies the instances of all the fields which itself have to copy themselfs.

Deep copying has to be made in all fields which are part of the new object. Here you have to copy the Board, the Player, the Move and so on. For the primitive data types your copy does work as it is.

Markus Steppberger
  • 618
  • 1
  • 8
  • 18
  • 1
    The question doesn't mention static fields anywhere. While it's *possible* there are static fields, we don't know that's the problem yet. – Jon Skeet Apr 01 '19 at 14:05
  • I have implemented the class State, to show you that it is not static. If you need more please tell me. – MaskinMichael Apr 01 '19 at 14:13
0
    // Copy constructor
public State(State state) {
    this.parent = state.parent;
    this.depth = state.depth;
    this.board = state.board;
    this.children = state.children;
    this.turn = 1 - state.turn;
    this.player1 = state.player1;
    this.player2 = state.player2;
    // shallow copy
    // this.subjects = student.subjects;

    // deep copy - create new instance of HashSet
//  this.subjects = new HashSet<>(state.subjects);
}

Your copy constructor doesn't make a copy. You provide references to another object, and they pointing to the same parent, depth, board, children, etc. You should create for every object another copy constructor upto primitive types. For example, if board contains two ints:

class Board {
int a;
int b;

public Board(Board board){
   this.a = board.a;
   this.b = board.b;
}

And just use this constructor:

this.board = new Board(state.board);

instead of:

this.board = state.board;
pethryth
  • 56
  • 5
  • Okay, so for example the contructor should look like this: public State(State state){ this.player = new Player(state.player); etc....; } – MaskinMichael Apr 01 '19 at 14:22
  • yes, but that constructors must to copy on the end primitive types. If Player contains for example object: Position, you should also have copy constructor for Position inside copy constructor for Player, like i said upto primivites int,double,etc Or you can use some deep copy methods from: http://javatechniques.com/blog/faster-deep-copies-of-java-objects/ but it's slower. – pethryth Apr 01 '19 at 14:33
  • If you paste Player.class and every that Player contains, i will write for you this part and you could do the same for another classes – pethryth Apr 01 '19 at 16:20