Ruby 和指针
我正在为一个小游戏编写一个地下城生成器。
地下城由房间组成。 房间
与其他房间有连接
。
room.connections = [room_a, room_b]
和room.number = 1 # unique id
现在我需要根据房间号来选择房间。
我首先使用 recursive_scan 方法执行此操作,但该方法不起作用,因为房间可能会导致循环,从而引发 StackOverflowError。因此,我将一个名为 already_scanned
的数组与房间号一起放入该方法的参数中。然后它没有扫描所有房间 - 顺便说一句,我不知道为什么,根据我的逻辑理解它应该有效。
然后我尝试将所有房间也放入一个数组中,然后迭代所需房间的数组 - 但在这里我遇到了问题,每个房间基本上都与其他房间相连,至少在它之间有一些其他房间;因此数组的大小为 dungeon_size * array_of_rooms.length
。
我现在需要的是一个显式指针 - 我知道 ruby 中几乎每个 var 都是一个指针,除了 Fixnums 和 Float (也许还有其他一些)。尽管如此,数组变得很大,所以我需要一个真正的指针。
(我还尝试设置一个 object_id 数组并通过 ObectSpace 加载它们,但遗憾的是 - 因为我经常必须加载房间 - 然后具有所需 object_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
I'm programming a Dungeon Generator for a litte game.
Dungeons are made of rooms. A room
has connections
to other rooms.
room.connections = [room_a, room_b]
androom.number = 1 # unique id
Now I need to pick a room by it's number.
I did this first with a recursive_scan
method, which did not work because rooms can lead into circles, which throws a StackOverflowError. So I put an array called already_scanned
with the room numbers, which were already picked into the args of the method. Then it didn't scan all rooms - btw, I have no idea why, by my logical undstandness it should have worked.
Then I tried to put all rooms also in an array and then iterate the array for the wanted room - but here I get the problem, every room is basically connected to every other room, at least with some other rooms betwenn it; so the array gets as big as dungeon_size * array_of_rooms.length
.
What I need now is an explicit pointer - I know almost every var in ruby is a pointer, except Fixnums and Float (and maybe some other). Even though, the array gets to big, so I need a real pointer.
(I also tried to setup an array of object_ids and load them via ObectSpace, but sadly - because I often have to load the rooms - the rooms with the wanted object_id are already recycled then, as an error message explains.)
This is my recursive scan method:
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Ruby 中的所有内容都已经是参考。
为什么不只维护一个房间索引呢?
然后你就可以用
rooms[i]
得到任何东西。我将通过简单地修改 Room 的 initialize 方法来使索引保持最新状态。这不会占用太多空间,因为数组只是一个索引,它实际上没有房间的副本。从数组中获取的每个引用本质上与通过程序中任何其他机制获取的引用相同,并且引用和经典指针之间的唯一真正区别是垃圾收集的一点开销。
如果房间曾经被删除(除了在退出之前),您将需要在删除时设置
rooms[x] = nil
。我不明白为什么您需要先创建数据结构,然后对房间进行索引,但 FWIW 您应该能够执行递归枚举,并使用房间索引数组中的房间作为“beve-here”标志。我不知道为什么它以前不起作用,但如果仔细写的话它确实必须起作用。
Everything in Ruby is already a reference.
Why not just maintain a room index?
Then you can get anything with
rooms[i]
. I would keep the index up to date incrementally by simply modifying the initialize method of Room.This won't take up much space because the array is just an index, it doesn't actually have copies of the rooms. Each reference obtained from the array is essentially the same thing as a reference obtained via any other mechanism in your program, and the only real difference between the reference and a classic pointer is a bit of overhead for garbage collection.
If rooms are ever deleted (other than just before exit) you will want to set the
rooms[x] = nil
when on deletion.I don't see why you need to create the data structure first and then index the rooms, but FWIW you should be able to do that recursive enumeration and use the rooms presence in the room index array as the been-here flag. I'm not sure why it didn't work before but it really has to if written carefully.
这是一个经典的图问题。使用图形库可以解决大部分问题。尝试使用 rgl gem。
将每个房间定义为图中的一个顶点。连接将是边缘。
现在您可以在 O(1) 内测试两个房间是否直接相连:
或者获取所有房间的列表:
您还可以获取所有相邻房间的列表:
It is a classical graph problem. Using graph library will handle most of these issues. Try using the
rgl
gem.Define each room as a vertex in the graph. The connections will be the edges.
Now you can test whether two rooms are directly connected in O(1):
Or get the list of all rooms:
You can also get the list of all adjacent rooms:
将所有房间存储在内存中的真正hackish方法是:
A really hackish way to get all Rooms in memory would be:
您可能需要查看 NArray gem,它将加快数字数组的使用速度。您可能试图用这种方法将方钉强行插入圆孔中。
You may want to look at the NArray gem, which will speed up using arrays of numbers. You may be trying to force a square peg into a round hole here with this approach.