1

I created an array by doing the following:

@gameboard = Array.new(3, Array.new(3, " "))

I tried to assign a value like so, and I got this:

@gameboard[0][2] = "X"
@gameboard #=> [[" ", " ", "X"], [" ", " ", "X"], [" ", " ", "X"]]

When I declare the array differently,

@gameboard = [[" ", " ", " "], [" ", " ", " "], [" ", " ", " "]]

I get this result:

@gameboard[0][2] = "X"
@gameboard # => [[" ", " ", "X"], [" ", " ", " "], [" ", " ", " "]]

Why does using the Array.new method illicit different behavior when assigning values to the array?

sawa
  • 165,429
  • 45
  • 277
  • 381
Pam Nunez
  • 37
  • 3

2 Answers2

8

Follow the code:

@gameboard = Array.new(3, Array.new(3, " "))
@gameboard.map { |a| a.object_id }
# => [76584030, 76584030, 76584030]

means new(size=0, obj=nil) method creates an array of size, having the same ob.

But new(size) {|index| block } method works in a different way; it creates an array of size, having different obs.

See the code below:

@gameboard = Array.new(3) { Array.new(3, " ") }
@gameboard.map { |a| a.object_id }
# => [75510080, 75509920, 75509540]

The above is the same as your second code example:

@gameboard = [[" ", " ", " "], [" ", " ", " "], [" ", " ", " "]]
@gameboard.map { |a| a.object_id }
# => [80194090, 80193400, 80193080]

If you change or update the the value at index 1 of the first element array of @gameboard, it wouldn't affect all other inner array elements.

@gameboard = Array.new(3) { Array.new(3, " ") }
@gameboard[0][1] = 2
@gameboard
# => [[" ", 2, " "], [" ", " ", " "], [" ", " ", " "]]
sawa
  • 165,429
  • 45
  • 277
  • 381
Arup Rakshit
  • 116,827
  • 30
  • 260
  • 317
1

The Array constructor will not duplicate the object you passed; it will reuse the object to fill the array.

Use the block form in order to create a new object for each index:

@gameboard = Array.new(3) { |i| Array.new(3) { |j| " " } }
Matheus Moreira
  • 17,106
  • 3
  • 68
  • 107