0

I want to copy the 'clues' array to the 'board' array only once. Why does the clues array change along with board after copying once?

public class Ejewbo
{
    public static int[][] board = new int[9][9];
    public static int[][] clues = 
        {
            {0, 0, 0, 7, 0, 0, 0, 0, 0},
            {1, 0, 0, 0, 0, 0, 0, 0, 0},
            {0, 0, 0, 4, 3, 0, 2, 0, 0},
            {0, 0, 0, 0, 0, 0, 0, 0, 6},
            {0, 0, 0, 5, 0, 9, 0, 0, 0},
            {0, 0, 0, 0, 0, 0, 4, 1, 8},
            {0, 0, 0, 0, 8, 1, 0, 0, 0},
            {0, 0, 2, 0, 0, 0, 0, 5, 0},
            {0, 4, 0, 0, 0, 0, 3, 0, 0},
        };

    public static void main(String[] args)
    {
        Ejewbo.board = Ejewbo.clues.clone();
        test();
    }

    public static void printboth()
    {
        for (int j = 0; j < 9; j++)
        {
            for (int i = 0; i < 9; i++)
            {
                System.out.print(Ejewbo.board[j][i]);
                System.out.print(" ");
            }

            System.out.println();
        }

        System.out.println();

        for (int j = 0; j < 9; j++)
        {
            for (int i = 0; i < 9; i++)
            {
                System.out.print(Ejewbo.clues[j][i]);
                System.out.print(" ");
            }

            System.out.println();
        }

        System.out.println("-----");
    }

    public static void test()
    {
        for (int i = 0; i < 2; i++) //run twice to see issue
        {
            Ejewbo.board[0][0]++;
            printboth();
        }
    }
}

I would expect the clues array not to change, but it does. When a change is made to board, clues changes too. Why? Is there a better way to copy arrays like this (instead of using .clone())?

EDIT: The first answer here seems to be a good way for me to copy my arrays.

max
  • 35
  • 1
  • 6
  • You're only copying the outer array (a shallow copy). The two boards are still pointing to the same inner arrays though. You need to copy those too (a deep copy). – Carcigenicate Jul 26 '19 at 16:05
  • What is a simple way to make a deep copy using my example? I don't understand the solution in that post. – max Jul 26 '19 at 16:32
  • Iterate over the inner arrays and call `clone` or another copying method on each sub-array, then store the copies in a new outer array. – Carcigenicate Jul 26 '19 at 16:53
  • Thanks a bunch, got it. – max Jul 26 '19 at 16:55

3 Answers3

0

Also quick tip

for this below you can replace the 9 with board.length just in case you change the board size you would have to change everything else.

for (int j = 0; j < 9; j++)
        {
            for (int i = 0; i < 9; i++)

So the reason it only call it once is with this part of code you need to be able to call the clues array when you call the board array and update it with ++;

for (int i = 0; i < 2; i++) //run twice to see issue
            {
                Ejewbo.board[0][0]++;
                printboth();
            }
        }
Thomas
  • 65
  • 1
  • 10
0

Because clone() is doing a shallow copy.

Check out this answer: calling clone on an array

0

(code blocks below are untested)

When you call:

Ejewbo.board = Ejewbo.clues.clone();    

You are creating a shallow copy. The result is the behaviour that you have observed, board[i][j] = clues[i][j]. They are pointing to the same reference in memory and therefore any changes to one is also a change to the other.

What you could do instead is iterate over the 2D array itself with something like

for(int i=0; i<clues.length; i++) {
 for(int j=0; j<clues[i].length; j++) {
  board[i][j]=clues[i][j];
 }
}

Note, the Arrays class has a method for copying the contents of a one dimensional array over, known as copyOf. So the above code could be shortened to

for(int i=0; i<clues.length; i++) {
 board[i]=Arrays.copyOf(clues[i], board[i].length);
}

Note that the Arrays.copyOf method will truncate extra elements or pad elements (i.e will add 0s for your int array) if they do not match in length, however you likely will ensure that they do so.

  • I decided to use this: ``` for (int i = 0; i < 9; i++) Sudoku.board[i] = Sudoku.preClues[i].clone();``` – max Jul 27 '19 at 17:31