Селективный срез массива Ruby - PullRequest
3 голосов
/ 15 июля 2009

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

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

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

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

Ответы [ 2 ]

4 голосов
/ 15 июля 2009

Если ваш массив имеет одно измерение, вы можете отобразить координаты x и y на индекс массива так же, как вы делаете пиксели в буфере vga.

offset = y * buffer_width + x

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

Вы можете использовать это для объединения видимой области на экране. Например, видимые плитки размером 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"]

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

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

2 голосов
/ 15 июля 2009

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

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

=> [["d", "e"], ["g", "h"]]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...