Ruby 2D数组赋值

所以我有一个tic-tac-toe board类。 见下文:

 class Board attr_accessor :grid def initialize(grid = Array.new(3, Array.new(3, nil))) @grid = grid end def place_mark(position, symbol) @grid[position[0]][position[1]] = symbol end end 

每当我调用place_mark方法,并尝试将符号分配给2D数组中的元素时,整个列都会被分配。

 board = Board.new board.place_mark([0,0], :x) 

会导致

 [[:X, nil, nil], [:X, nil, nil], [:X, nil, nil]] 

期望的结果是什么

 [[:X , nil, nil], [nil, nil, nil], [nil, nil, nil]] 

我找到了解决我的问题的方法,在initialize方法中,我只需要像这样分配网格的默认值:

 def initialize(grid = [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]) @grid = grid end 

然后place_mark方法工作得很好。

所以我的问题是两个不同的数组声明是如何不同的,这会使它们以这种方式运行?

问题是Array.new(3, Array.new(3, nil))为你提供了一个包含相同数组的数组三次。

就像这样做:

 x = Array.new(3, nil) grid = Array.new(3, x) 

所以你有一个包含x三次的数组。 你真的想要三个独立的数组,每个数组都有自己的值。

根据http://ruby-doc.org/core-2.3.1/Array.html :

请注意,第二个参数使用对同一对象的引用填充数组。 因此,仅在需要使用本机不可变对象(例如符号,数字,true或false)实例化数组时才建议使用它。

要创建具有单独对象的数组,可以传递块。 此方法可以安全地与可变对象(如哈希,字符串或其他数组)一起使用:

 Array.new(4) { Hash.new } #=> [{}, {}, {}, {}] 

这也是构建多维数组的快速方法:

 empty_table = Array.new(3) { Array.new(3) } #=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]] 

最后一个例子正是您正在寻找的。