2009-07-15 4 views
3

Я медленно изучаю Ruby (на данный момент, возможно, первый язык, на который я вложил какое-то время на изучение на самом деле), поэтому это, вероятно, будет очень простым вопросом для многих из вас ,Селективная рубиновая решетка

Мой игрушечный проект для моих занятий - это, в основном, рогалик. В настоящее время у меня есть класс Map, который содержит массив объектов Tile, представляющих, конечно, каждую плиту на всей карте. Я пытаюсь создать метод, который будет возвращать меньший массив (наиболее вероятным примером будет отображение отображаемой в данный момент области карты).

Моя проблема сводится к этому. Поскольку массив, содержащий все эти фрагменты, является одномерным, я не могу представить себе чистый способ срезания фрагментов этого массива на основе двух координат x, y, которые метод принимает, чтобы определить, что нужно вернуть. Другими словами, я не могу найти простой способ перевести между двумя координатными парами без какого-либо довольно уродливого кода, и я понимаю, что есть очень простой способ сделать это, просто не «щелкая».

Идеи любой? Я открыт для некоторых довольно сумасшедших предложений!

ответ

4

Если массив одного Dimention можно сопоставить х и у COORDS в массив индекс так же, как вы делаете пиксели в буфере vga.

offset = y * buffer_width + x 

Если ваша карта ширина плитки 100 плитки и вы хотели бы получить плитку 5,5, то 5 * 100 + 5 = индекс массива 505 будет соответствующая плитка в вашем 1 одномерный массив.

Вы можете использовать это, чтобы объединить область просмотра на экране. Например, 10x10 видимых фрагментов: начните со своего смещения и возьмите следующие 10 элементов, добавьте buffer_width, чтобы сбросить строку, и добавьте следующие 10 и так далее, пока у вас не будет всех 10 строк для вашей видимой области 10x10.

Ниже приведен пример на меньшем наборе плитки с шириной плитки буфера 5 и выбора видимой области 3x3:

buffer = ['0,0', '1,0', '2,0', '3,0', '4,0', 
      '0,1', '1,1', '2,1', '3,1', '4,1', 
      '0,2', '1,2', '2,2', '3,2', '4,2', 
      '0,3', '1,3', '2,3', '3,3', '4,3', 
      '0,4', '1,4', '2,4', '3,4', '4,4'] 

buffer_width = 5 
buffer_height = 5 

# now lets say we want to grab a 3x3 slice from right 
# in the middle of the array from 1,1->3,3 

x1,y1 = 1,1 
x2,y2 = 3,3 

view_width = x2 - x1 
view_height = y2 - y1 

(0..view_height).each do |row| 
    offset = (y1 + row) * buffer_width + x1 
    puts buffer[offset..offset+view_width].inspect 
end 

Наш результат будет выход, как это:

["1,1", "2,1", "3,1"] 
["1,2", "2,2", "3,2"] 
["1,3", "2,3", "3,3"] 

Который вы можете объединить в новом одномерном или многомерном пространстве, которое вы считаете нужным.

Надеюсь, что это поможет.

+0

Отлично, это намного чище, чем то, что я придумывал. Благодаря! –

2

Вам нужно использовать карту использования на куске массива и сопоставить каждую строку с самим срезом.

a = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']] 
a[1..2].map { |row| row[0..1] } 

=> [[ "d", "е"], [ "г", "ч"]]

+0

Я собирался предложить что-то подобное, но вы избили меня. Для двумерного массива должен быть вложенный вызов карты Array #, вот и все, хотя это может показаться неинтуитивным для людей, незнакомых с тем, как Ruby может связывать и блокировать блоки. – tadman

+0

Не совсем то, что я искал (поскольку я работаю только с одномерными массивами). Тем не менее, спасибо за внимание к некоторым из возможностей класса Array! –