Ruby:管理大型3d阵列的最佳方式

时间:2012-07-09 15:23:36

标签: ruby large-data-volumes

我想知道用以下方法管理大型3d数组的最佳方法是什么:

x = 1000 y = 1000 z = 100

=> 100000000个对象

每个单元格都是一个包含大量数据的对象。

即使所有数据都被折叠,简单的方法也非常有用(我首先尝试了一组对象数组的数组)

class Test

    def initialize
        @name = "Test"
    end

end

qtt = 1000*1000*100
Array.new(qtt).each { |e| e = Test.new }

我在某处读过DB对于这种情况可能是一件好事。

您如何看待这个?

我想做什么?

这个“矩阵”代表一个世界。每个元素都是一个1mx1mx2m的块,可能是另一种(水,泥,石......)。某些块也可能是空的。

但是用户应该能够在任何地方移除块并改变周围的一切(如果它们背后有水,它会流过这个洞例如。

事实上我想做的不是Minecraft是DwarfFortress的一个非常小的克隆(http://www.bay12games.com/dwarves/)

其他有趣的事情

在我的模型中,地面处于10级。这意味着在大多数情况下[0,10]是空的。 这些层上只能出现山丘和部分山脉。

地下基本未知且未挖掘。所以我们不应该为未使用的块添加实例。

我们应该从一开始就添加到模型中:宝石,黄金,水,谁可以存储而不必存储相邻的石头/情绪/地球块。

在游戏开始时,立方体的 80%不需要加载到内存中。

每次我们挖掘时,我们都会创建新的块:我们挖出的空块和周围的块。

我们应该索引的唯一内容是:

  • 地下河
  • 地下湖泊
  • 熔岩河

1 个答案:

答案 0 :(得分:1)

将许多物品放在记忆中永远不是一件好事。平面文件或以数据库为中心的方法将更有效,更易于维护。

我会做什么 - 面向对象的方法

将块的参数存储为简单数据并动态构造对象。

创建一个Block类来表示游戏中的一个块,并给它变量来保存该特定块的参数:

class Block
  # location of the Block
  attr_accessor :x, :y, :z

  # an individual id for the Block
  attr_accessor :id

  # to define the block type (rock, water etc.)
  attr_accessor :block_type

  # and add any other attributes of a Block...
end

然后,我会创建一些方法,使我能够将数据序列化/反序列化到文件或数据库。

正如你所说它适用于某个主板,你还需要一个Board类来代表它,以保持游戏状态并对Block个对象执行操作。使用每个x, y, z的{​​{1}}属性,您可以确定其在游戏中的位置。使用此信息,您可以在Block类中编写一个方法,该方法可以找到与当前块相邻的块。这将使您能够执行“级联”效果,您可以谈论一个Block受另一个Block操作影响的位置。

有效访问数据

这完全取决于您如何选择序列化Block对象。我可能会选择二进制格式来减少不必要的数据读取并通过Block参数存储对象,然后使用类似MMIO的内容快速对大型数据文件进行随机访问读/写操作类似于数组的方式。这将允许您快速有效地访问数据,而无需内存开销。如何读取数据将与上面的相邻块方法有关。

您当然也可以选择数据库存储路由,它允许您隔离块并以更高级别的方式对特定块进行查找,但这可能会给您带来额外的开销。

这听起来像一个有趣的项目,我希望这有点帮助! :)

P.S关于@Linuxious上面关于选择不同语言的评论。是的,在某些情况下这可能是真的,但熟练的程序员从不责备他的工具。程序只有程序员才能有效...除非你用Java编写它;)