【问题标题】:Ruby undefined method `[]' for nil:NilClass (NoMethodError)用于 nil:NilClass (NoMethodError) 的 Ruby 未定义方法“[]”
【发布时间】:2014-03-16 07:29:26
【问题描述】:

我正在尝试使用 ruby​​ 制作康威人生游戏的一个版本。我创建了一个以@play_area 作为实例变量的 Grid 类。但是,当我运行我的代码时,@play_area 在它已经被评估了两次之后变成了 nil(当在行中评估时,如果 @play_area[x_mod][y_mod].alive )。为什么会这样?

编辑

这里是初始化函数:

def initialize(sizex, sizey)
    @x_length = sizex
    @y_length = sizey
    @play_area = []
    #initialize dead cells
    @x_length.times do |x|
        @play_area[x] ||= []
        @y_length.times do |y|
          @play_area[x][y] = Cell.new(x, y, false)
          puts @play_area[x][y].inspect
        end
    end
end

这是发生错误的函数:

def neighbor_num_of_cell(pos_x,pos_y)
    c = @play_area[pos_x][pos_y]
    count = 0
    ((pos_x-1)..(pos_x+1)).each do |x|
        ((pos_y-1)..(pos_y+1)).each do |y|
            unless @play_area[x][y].eql?(c)
                x_mod = x % (@x_length + 1)
                y_mod = y % (@y_length + 1)
                puts x_mod
                puts y_mod
                if @play_area[x_mod][y_mod].alive
                    count += 1
                end
            end
        end
    end
    count
end

对@play_area 中每个单元格的检查表明每个单元格都已正确初始化,这是检查的输出:

jon@jon-MacBook:~/programs/ruby$ ruby main.rb 
#<Cell:0x00000000f919d8 @alive=false, @alive_next=false, @x_pos=0, @y_pos=0>
#<Cell:0x00000000f91848 @alive=false, @alive_next=false, @x_pos=0, @y_pos=1>
#<Cell:0x00000000f916e0 @alive=false, @alive_next=false, @x_pos=0, @y_pos=2>
#<Cell:0x00000000f915a0 @alive=false, @alive_next=false, @x_pos=0, @y_pos=3>
#<Cell:0x00000000f91460 @alive=false, @alive_next=false, @x_pos=0, @y_pos=4>
#<Cell:0x00000000f91320 @alive=false, @alive_next=false, @x_pos=0, @y_pos=5>
#<Cell:0x00000000f911e0 @alive=false, @alive_next=false, @x_pos=0, @y_pos=6>
#<Cell:0x00000000f910a0 @alive=false, @alive_next=false, @x_pos=0, @y_pos=7>
#<Cell:0x00000000f90f38 @alive=false, @alive_next=false, @x_pos=0, @y_pos=8>

...

#<Cell:0x00000000f1abf8 @alive=false, @alive_next=false, @x_pos=19, @y_pos=7>
#<Cell:0x00000000f1aa90 @alive=false, @alive_next=false, @x_pos=19, @y_pos=8>
#<Cell:0x00000000f1a900 @alive=false, @alive_next=false, @x_pos=19, @y_pos=9>
#<Cell:0x00000000f1a798 @alive=false, @alive_next=false, @x_pos=19, @y_pos=10>
#<Cell:0x00000000f1a658 @alive=false, @alive_next=false, @x_pos=19, @y_pos=11>
#<Cell:0x00000000f1a518 @alive=false, @alive_next=false, @x_pos=19, @y_pos=12>
#<Cell:0x00000000f1a3b0 @alive=false, @alive_next=false, @x_pos=19, @y_pos=13>
#<Cell:0x00000000f1a270 @alive=false, @alive_next=false, @x_pos=19, @y_pos=14>
#<Cell:0x00000000f1a130 @alive=false, @alive_next=false, @x_pos=19, @y_pos=15>
#<Cell:0x00000000f19ff0 @alive=false, @alive_next=false, @x_pos=19, @y_pos=16>
#<Cell:0x00000000f19e88 @alive=false, @alive_next=false, @x_pos=19, @y_pos=17>
#<Cell:0x00000000f19d20 @alive=false, @alive_next=false, @x_pos=19, @y_pos=18>
#<Cell:0x00000000f19be0 @alive=false, @alive_next=false, @x_pos=19, @y_pos=19>

【问题讨论】:

  • 看起来@play_area[pos_x]nil,因此@play_area[pos_x][pos_y] 会引发NilClass 错误。

标签: ruby


【解决方案1】:

问题出在这一行:

@play_area[x][y] = Cell.new(x, y, false)

@play_area[x] 为零。您只初始化了多维数组的一维。在尝试向其中添加元素之前,您需要将 @play_area[x] 的每个元素初始化为一个数组。

@x_length.times do |x|
  @play_area[x] ||= []
  @y_length.times do |y|
    @play_area[x][y] = Cell.new(x, y, false)
  end
end

【讨论】:

  • 不幸的是,这并没有解决问题。您提供的代码中的@playArea[x] ||= [] 现在在我尝试运行它时会产生 NilClass 错误。
  • play_area,不是playArea
  • 感谢@meagar,我解决了这个问题,但它仍然无法正常运行。我编辑了我的 OP 以提供更多信息
  • Chef attributes/default.rb 没有初始化怎么可能有这个语法:node.default['bbcpd-bpds-api']['update_mode'] = false
  • @OndraŽižka 很容易,请参阅Hash.new 的块参数语法。
【解决方案2】:

我自己以前也遇到过这个问题。您的问题来自尝试检查不存在的单元格。想一想这个函数如何评估细胞 (0,0) 周围的细胞。首先,它会查看单元格 (-1, -1) 的内容......这是 Nil。我们很幸运甚至可以使用 Ruby 获得 Nil;在 Python 中,这会引发“列表索引超出范围”异常。

【讨论】:

  • 我几乎不赞成它对 Python 的温柔攻击。
  • 离题:实际上并非如此。 Python 中的 thing[-1] 是列表的最后一个元素,而不是索引超出范围异常(除非列表为空,在这种情况下,thing[0] 也会这样做)
猜你喜欢
  • 2016-06-15
  • 2013-02-17
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多