Давайте посмотрим на ваш код, слегка упрощенный 1 :
def search_array(array)
array.each_with_index do |y, yi|
y.each_with_index do |x, xi|
return [yi-1, xi] if x != nil && x == array[yi+1][xi] && x == array[yi+2][xi]
end
end
end
Вы идете по одной строке за раз, затем для каждого элемента в этой строке проверьте, не является ли этот элемент nil
, и если так, определите, имеют ли два элемента ниже него одинаковое ненулевое значение. Если вы достигнете предпоследней (следующей за последней) строки, yi = array.size - 2
, вы сравните x
с array[yi+2][xi]
, что равно array[array.size][xi]
, что, в свою очередь, равно nil[xi]
. Однако nil
не имеет метода []
, поэтому возникает исключение undefined method . Обратите особое внимание на эти сообщения об ошибках; часто, как здесь, они приводят вас к ошибке.
Другая проблема заключается в том, что если вы найдете 1
в первых трех строках столбца j
, вы вернете индекс [-1, j]
, -1
, равный 0-1
. Вы тоже этого не хотите.
Я понимаю, что вы также хотите определить, приводит ли выпадение монеты в столбце к четырем рядам по горизонтали. Вы можете проверить как вертикально, так и горизонтально следующим образом.
def search_array(arr)
arr.first.each_index do |j|
r = arr.each_index.find { |i| arr[i][j] == 1 }
next if r == 0
r = r.nil? ? arr.size-1 : r-1
return [r,j] if below?(arr,r,j) || left?(arr,r,j) || right?(arr,r,j)
end
nil
end
def below?(arr,r,j)
r < arr.size-3 && (1..3).all? { |i| arr[r+i][j] == 1 }
end
def right?(arr,r,j)
j < arr.first.size-3 && (1..3).all? { |i| arr[r][j+i] == 1 }
end
def left?(arr,r,j)
j >= 3 && (1..3).all? { |i| arr[r][j-i] == 1 }
end
grid4 = [
[nil, nil, nil, nil, nil],
[nil, nil, nil, nil, nil],
[nil, nil, 1, nil, nil],
[nil, nil, 1, 1, 1],
[ 1, 1, 1, nil, 1]
]
grid5 = [
[nil, nil, nil, nil, nil],
[nil, nil, nil, nil, nil],
[nil, nil, 1, nil, nil],
[nil, 1, 1, nil, nil],
[nil, 1, 1, nil, 1]
]
search_array grid1 #=> [0, 0] (vertical)
search_array grid2 #=> [0, 2] (vertical)
search_array grid3 #=> nil
search_array grid4 #=> [3, 1] (horizontal)
search_array grid5 #=> [1, 2] (vertical)
Обратите внимание, что если вы также хотите проверить диагональ четыре в ряд, вы можете изменить:
return [r,j] if below?(arr,r,j) || left?(arr,r,j) || right?(arr,r,j)
до
return [r,j] if below?(arr,r,j) || left?(arr,r,j) || right?(arr,r,j) ||
top_left_to_bottom_right?(arr,r,j) || bottom_left_to_top_right?(arr,r,j)
и добавьте дополнительные методы top_left_to_bottom_right?
и bottom_left_to_top_right?
.
1. Я изменил имя вашего метода на search_array
, потому что в Ruby существует соглашение, согласно которому case-snake используется для именования переменных и методов. Вам не нужно принимать это соглашение, но 99% + Rubiests делают.