Ruby 2D数组赋值

时间:2016-08-22 03:21:30

标签: arrays ruby

所以我有一个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方法运行正常。

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

1 个答案:

答案 0 :(得分:2)

问题在于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]]

最后一个例子正是你要找的。