SkelDave
SkelDave

Reputation: 1186

Cloning/Copying an Object

I am creating a connect 4 game in Java and i'm trying to make a deep copy of a custom object (The game Board), then modify that copy and add it to a list as part of the mini max algorithm.

This is the code i'm using for copying:

public void getPossibleBoards(Board board) {
    for(int i = 0; i < 7; i++) {
        if(!board.columns.get(i).isFull()) {    
            Board tmpBoard = board.copy(board);
            tmpBoard.columns.get(i).addCounter(turn);   
            boardList.add(tmpBoard);
        }
    }
}

public Board copy(Board other) {
    Board b = new Board(other);
    b.columns = other.columns;
    return b;
}

This takes the main board (passed as a parameter), loops through the columns on the board and if the column isn't full it creates a new board object and puts a counter in a empty column, then adds this new board object to a list for later use.

The problem is that when I copy the board, it keeps referencing the main board and modifying that, then each loop it adds a counter to a column without wiping the board clear first.

Expected output is: (Player 1 is human, player 2 is the computer)

0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
2 0 0 0 0 0 1

0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 2 0 0 0 0 1

0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 2 0 0 0 1

And so on until the 7 loops are over.

Actual output:

0 0 0 0 0 0 0 
0 0 0 0 0 0 0 
0 0 0 0 0 0 0 
0 0 0 0 0 0 0 
0 0 0 0 0 0 0 
0 0 0 0 0 0 2 
2 2 2 2 2 2 1 

0 0 0 0 0 0 0 
0 0 0 0 0 0 0 
0 0 0 0 0 0 0 
0 0 0 0 0 0 0 
0 0 0 0 0 0 0 
0 0 0 0 0 0 2 
2 2 2 2 2 2 1 

and so on until the 7 loops are over.

EDIT:

I had problems with the solution below so I decided to try another way, but got the same result and I don't understand why.

I'm basically creating a new Board object, within the constructor i'm assigning new blank columns to it, then looping through the main_board to get the colours of the counters at each slot (Stored as integers in the Slot class), and altering the new Board respectively.

if(!board.columns.get(i).isFull()) {    
    Board tmpBoard = new Board();

    for(int j = 0; j < 7; j++) {
        for(int k = 0; k < 7; k++) {
                    tmpBoard.columns.get(j).slots.get(k).setColour(board.columns.get(j).slots.get(k).getColour());
        }   
    }
}

Board constructor

public Board() {
    for(int i = 0; i < 7; i++) {
        columns.add(new Column());
    }
}

EDIT: Nevermind, above solution worked, just me forgetting to add a new counter after the copy.

Upvotes: 1

Views: 769

Answers (2)

Cemre Meng&#252;
Cemre Meng&#252;

Reputation: 18774

The line b.columns = other.columns; causes the problem since you are doing a reference assignment (i.e. its not doing a deep copy as you are expecting). You can copy that array by using System.arraycopy method.

I think in your case you are using an ArrayList to represent columns/rows if so, you can use:

Collections.copy(arrayList2,arrayList1);

or simply

new ArrayList<Integer>(oldList)

in order to create a copy.

Upvotes: 4

Franz Kafka
Franz Kafka

Reputation: 10851

Why does Board take another Board as a constructor parameter?

Your problem is that you don't copy the columns, you only do b.columns = other.columns in your copy method. If one of the two boards is changed both boards are affected. Create a new column instances when copying and also deep copy all elements in an column until you reach immutable objects or primitives.

Upvotes: 0

Related Questions