我正在生成游戏树。
我输入的问题是,当我将一个对象复制到一个新对象,然后在新对象中进行更改时,旧对象也会更改其值。
所以这似乎是一个参考问题。
但是如何使新对象成为独立的实例。
在创建从父对象复制的子对象之后,然后更改子对象中的值,父对象也将更改,并且在方法结束时,它将打印出对象相等。
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);
}
预期结果是我可以更改对象Child而无需更改Parent
答案 0 :(得分:1)
但是如何使新对象成为独立的实例。
删除static
关键字以使对象内的字段与其他对象无关。
如果字段/变量为static
,它将与该类的所有实例共享其值。如果您更改其中之一,则会更改所有实例的值。
我认为主要问题是您复制了State
个对象。您实际上并没有复制任何内容,只将引用传递给另一个实例即可。
您需要一个deepCopy
方法,该方法还复制所有必须复制自身的字段的实例。
必须在属于新对象的所有字段中进行深度复制。在这里,您必须复制Board
,Player
,Move
等。对于原始数据类型,您的副本照原样工作。
答案 1 :(得分: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);
}
您的副本构造函数未创建副本。您提供对另一个对象的引用,它们指向相同的父对象,深度,木板,子对象等。 您应该为每个对象创建另一个复制构造器,直到原始类型。 例如,如果board包含两个整数:
class Board {
int a;
int b;
public Board(Board board){
this.a = board.a;
this.b = board.b;
}
并使用此构造函数:
this.board = new Board(state.board);
代替:
this.board = state.board;