2 votes

La modification des valeurs d'un objet entraîne la modification d'un autre objet

Je travaille sur la génération d'un arbre de jeu.

Mon problème est que lorsque je copie un objet dans un nouvel objet, et que j'effectue ensuite des modifications dans le nouvel objet, les valeurs de l'ancien objet sont également modifiées.

Il semble donc qu'il s'agisse d'un problème de référence.

Mais comment faire pour que le nouvel objet soit une instance indépendante.

après avoir créé cet objet enfant copié du parent, puis modifié les valeurs de l'objet enfant, l'objet parent est également modifié et, à la fin de la méthode, il est indiqué que les objets sont égaux.

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);
}

Le résultat attendu est que je peux modifier l'objet Enfant sans modifier le Parent.

1voto

Mais comment faire pour que le nouvel objet soit une instance indépendante.

Retirer le static pour rendre les champs à l'intérieur de l'objet indépendants des autres objets.

Si un champ/variable est static il partage sa valeur avec toutes les instances de la classe. Si vous modifiez l'un d'entre eux, vous modifiez la valeur de toutes les instances.

Je pense que le problème principal est la copie de State objets. Il ne s'agit pas d'une véritable copie, mais seulement d'une transmission des références à une autre instance.

Vous avez besoin d'un deepCopy qui copie également les instances de tous les champs qui doivent eux-mêmes se copier.

Une copie en profondeur doit être effectuée dans tous les domaines qui font partie du nouvel objet. Ici, vous devez copier le champ Board , le Player , le Move et ainsi de suite. Pour les types de données primitifs, votre copie fonctionne telle quelle.

0voto

pethryth Points 56
    // 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);
}

Votre constructeur de copie ne fait pas de copie. Vous fournissez des références à un autre objet, et elles pointent vers le même parent, la même profondeur, le même tableau, les mêmes enfants, etc. Vous devez créer pour chaque objet un autre constructeur de copie jusqu'aux types primitifs. Par exemple, si le tableau contient deux ints :

class Board {
int a;
int b;

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

Il suffit d'utiliser ce constructeur :

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

au lieu de :

this.board = state.board;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X