Подтвердить что ты не робот

Ruby undefined метод `[] 'для nil: NilClass (NoMethodError)

Я пытаюсь сделать версию игры Conway жизни, используя рубин. Я создал класс Grid с переменной @play_area как переменную экземпляра. Тем не менее, когда я запускаю свой код, @play_area поворачивается на нуль после того, как он уже дважды был оценен (когда оценивается в строке, если @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 показывает, что каждая из ячеек инициализирована правильно, вот вывод проверки:

[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>
4b9b3361

Ответ 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

Ответ 2

Я уже сталкивался с этой проблемой. Ваша проблема связана с попыткой проверить ячейки, которые не существуют. Подумайте еще раз, как эта функция оценивает ячейки, окружающие ячейку (0,0). Сначала он рассмотрит содержимое ячейки (-1, -1)... Что такое Nil. Нам повезло, что он даже запустил Nil с помощью Ruby; в Python это привело бы к исключению "индекс индекса вне диапазона".