Ruby未定义方法`[]'为零:NilClass(NoMethodError)

问题描述:

我试图用红宝石制作康威的生活游戏版本。我用@play_area创建了一个Grid类作为实例变量。但是,当我运行我的代码时,@play_area在它已经被两次评估后变为零(当在@play_area [x_mod] [y_mod] .alive中对行进行评估时)。这是为什么发生?Ruby未定义方法`[]'为零:NilClass(NoMethodError)

EDIT

这里的初始化功能:

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表明每个单元格都被正确初始化,这里是检查的输出:

[email protected]:~/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> 
+0

看起来'@play_area [pos_x]'是'nil',因此'@play_area [pos_x] [pos_y]'抛出了一个'NilClass'错误。 – zeantsoi

问题是这一行:

@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 
+0

不幸的是,这并没有解决问题。现在提供的代码中的@playArea [x] || = []'会在我尝试运行它时产生NilClass错误。 – steamingramen

+0

'play_area',而不是'playArea'。 – meagar

+0

谢谢@meagar,我解决了这个问题,但仍然无法正常运行。我编辑了我的OP来提供更多信息 – steamingramen

我以前就遇到过这个问题。你的问题来自于试图检查不存在的单元。想一想这个函数如何评估细胞周围的细胞(0,0)。首先它将查看单元格的内容(-1,-1)......这是Nil。我们很幸运能够通过Ruby获得Nil;在Python中,这会引发'列表索引超出范围'异常。

+1

我几乎不满意Python的投标。 – toszter

+0

题外话:其实并非如此。 Python中的thing [-1]是列表的最后一个元素,而不是索引超出范围的异常(除非列表为空,在这种情况下,thing [0]将执行相同操作) – scav