Question

I have a class like this:

class Tiles
  attr_accessor :board
  def initialize
    @board = Array.new(4) { Array.new(4) { 0 } }
  end
  ...

Later, I call this method:

def display_board
  padded_board = @board.clone
  padded_board.each_with_index do |row, x|
    row.each_with_index do |item, y|
      padded_board[x][y] = pad_number(item)
    end
    puts row.join ' '
  end
end  

Anytime I change padded_board, @board gets changed as well. I can't figure out why this is happening. Any ideas?

Was it helpful?

Solution

That is because when you clone, you are creating a new instance of an array @board, but its elements, which are also arrays, are not being replaced with new instances. You are not going deeply enough to clone the end elements. You need to do deep clone. You might want to look at some answers and gems suggested here or here.

OTHER TIPS

The reason is that array is in fact a set of pointers to other objects, in your case those objects are another arrays. When you are cloning array, you are creating new pointers, which points to the same objects. By calling padded_board[x][y]= you are modifying the padded_board[x] array, which is referenced by both @board and padded_board.

To fix it, you need to duplicate not only the array, but also each element of this array. Int his case this should be sufficient:

   padded_board = @board.map(&:clone)

In more general case it is useful to extend Array with deep_dup method. Rails have this method defined within ActiveSupport module, whcih can also be used in any non-rails project by adding `require 'active_support/core_ext/object/deep_dup'.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top