所以我有一个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
方法运行正常。
所以我的问题是两个不同的数组声明是如何不同的,这会使它们以这种方式运行?
答案 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]]
最后一个例子正是你要找的。 p>