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]]
最后一个例子正是您正在寻找的。