I'm befuddled. In my Ruby code, I've got a two-dimensional array of dots, which is assigned to an instance variable in a Battleship game:
@dotty_board =
[[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."]]
Now if that's all it was, I could easily type
@dotty_board[5][5] = 'C'
print @dotty_board
and I'd see something like this, right?
[[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "C", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", ".", ".", ".", ".", "."]]
In fact, I typed exactly that in a small Ruby test file. Of course it works that way.
But in the context of my game code, I have a @dotty_board
variable with precisely the above contents and I've confirmed its class is Array. (If it matters, I create it by a method call on an instance object. But it's not an instance object; it's an array.) I can type precisely the above two lines, and then, instead, I see this:
[[".", ".", ".", ".", ".", "C", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "C", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "C", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "C", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "C", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "C", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "C", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "C", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "C", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "C", ".", ".", ".", "."]]
The sixth element of every row is now a 'C', not just of the sixth row. In other words, after I change the value of 5,5 to 'C', the value of 0,5 through 9,5 also changes to 'C'. I tried a lot of testing and research, and I can't figure it out. I just know I'm going to slap my forehead very audibly when someone reveals the secret. What the holy $#!+ could be going on? Any ideas?
I've confirmed that the problem has something to do with my @dotty_board
variable. I exactly copied my test code within the document itself, code that has the weird effect with @dotty_board
. I then @dotty_board
to @ditty_board
and assigned this new variable to the two-dimensional array of dots you see above. Well, ditty_board[5][5] = 'C'
works exactly as expected in that context, it changes only that one coordinate.
But what on earth could there be about @dotty_board
(an Array class object) that could make it have this different behavior?
The answer is given below. It seems that the way my array was initialized was not right for an array whose values might need to be updated.
A friend of mine heard my summary of the problem and solution, and nodded sagely, saying, "Ah. Deep vs. shallow copy."