Ruby和指针
我正在为一个小游戏编写一个地下城生成器 地下城是由房间组成的。Ruby和指针,ruby,pointers,Ruby,Pointers,我正在为一个小游戏编写一个地下城生成器 地下城是由房间组成的。房间与其他房间有连接 room.connections=[房间a,房间b] 和 room.number=1#唯一id 现在我需要根据房间号码来选择房间 我首先使用了一个递归\u scan方法,该方法不起作用,因为房间可能会导致圆圈,从而引发堆栈溢出错误。因此,我放置了一个名为的数组,其中包含房间号,该房间号已被选入该方法的参数中。然后它没有扫描所有的房间-顺便说一句,我不知道为什么,根据我的逻辑不理解,它应该工作 然后我试着把所有的房
房间
与其他房间有连接
room.connections=[房间a,房间b]
和
room.number=1#唯一id
现在我需要根据房间号码来选择房间
我首先使用了一个递归\u scan
方法,该方法不起作用,因为房间可能会导致圆圈,从而引发堆栈溢出错误。因此,我放置了一个名为的数组,其中包含房间号,该房间号已被选入该方法的参数中。然后它没有扫描所有的房间-顺便说一句,我不知道为什么,根据我的逻辑不理解,它应该工作
然后我试着把所有的房间也放在一个数组中,然后迭代这个数组来寻找想要的房间——但我遇到了一个问题,每个房间基本上都与其他房间相连,至少在它之间有一些其他房间;因此,数组的大小与地下城大小*房间的数组大小一样大。长度
我现在需要的是一个显式指针——我知道ruby中几乎每个变量都是指针,除了Fixnums和Float(可能还有其他变量)。尽管如此,数组变大了,所以我需要一个真正的指针
(我还试图设置一个对象id数组,并通过ObectSpace加载它们,但遗憾的是——因为我经常要加载房间——正如一条错误消息所解释的那样,具有所需对象id的房间已经被回收了。)
这是我的递归扫描方法:
def room(number)
recursive_scan(@map, number, []) # @map is the entrance room
end
private
def recursive_scan(room, number, scanned)
scanned << room.room_number
if room.room_number == number
room
else
r = nil
room.connections.each do |next_room|
if !scanned.include?(next_room.room_number)
r = recursive_scan(next_room, number, scanned)
end
end
r
end
end
def室(编号)
递归#u扫描(@map,number,[])#@map是入口房间
结束
私有的
def递归扫描(房间、号码、扫描)
扫描您可能需要查看,这将使用数字数组加快速度。使用这种方法,您可能试图将一个方形的销钉塞进一个圆孔。Ruby中的所有内容都已经是参考资料
为什么不维护一个房间索引呢
rooms[room.number] = room
然后你可以通过房间[i]
得到任何东西。我只需修改Room的initialize方法,就可以使索引不断更新
def initialize
rooms[self.number] = self
. . .
end
这不会占用太多空间,因为数组只是一个索引,实际上没有房间的副本。从数组中获得的每个引用本质上与通过程序中的任何其他机制获得的引用相同,引用与经典指针之间唯一的真正区别是垃圾收集的开销
如果曾经删除过房间(退出前除外),则在删除时,您需要设置房间[x]=nil
我不明白为什么需要先创建数据结构,然后对房间进行索引,但是FWIW您应该能够进行递归枚举,并使用房间索引数组中的房间作为been-here标志。我不知道为什么它以前不起作用,但如果写得仔细的话,它确实必须起作用。这是一个经典的图形问题。使用图形库将处理大多数这些问题。尝试使用rgl
gem
将每个房间定义为图形中的顶点。连接将是边缘
require "rgl/adjacency"
map = RGL::AdjacencyGraph.new
rooms.each {|room| map.add_vertex room}
rooms.connections.each {|room1, room2| map.add_edge room1, room2}
现在您可以测试两个房间是否在O(1)中直接连接:
或者获取所有房间的列表:
map.vertices
您还可以获得所有相邻房间的列表:
map.adjacent_vertices(room)
将所有房间存储在内存中的真正方法是:
all_rooms = ObjectSpace.each_object(Room).to_a
如果需要加速线性搜索,只需将其转换为O(1)操作即可;)根据您描述的recursive\u scan
和已经扫描的应该可以工作,不久前我对边缘查找算法使用了完全相同的方法。可能会发布您的代码,我们会看看是否可以修复。我应该补充一点,您可能希望将Room
索引设置为Room
的类变量。所以:@@rooms[self.number]=self
我已经有了这个解决方案,但是因为我需要将rooms转换为\u yaml
,所以我得到了一个数组,它的大小不只是引用,而是all\u rooms*array.length
。
all_rooms = ObjectSpace.each_object(Room).to_a