【问题标题】:How do I make a class stored in a 2d-array "aware" of their position in it?如何使存储在二维数组中的类“知道”它们在其中的位置?
【发布时间】:2015-08-26 21:15:01
【问题描述】:

我认为标题说明了一切......但为了完整起见,这里是完整的问题。

问题

所以,我在 Visual Basic/C#/Anything.net 中有一个 2 列数组(矩阵或“网格”),由声明为 Public Matrix(,) As CellCell 实例组成。

Cell 大致是这样的:

Class Cell

    Public Value as integer
    Public Height as integer
    Public Tags as Dictionary

    Sub New(Optional v As CellType = CellType.Void)
        value = v
        type = v
    End Sub

    Function GetPos() as Point
        *need arcane necromancy here*
    End Sub

End Class

问题很简单,但我知道答案可能不是:我可以不通过构造函数就得到Cell的位置吗?

这是我想要实现的示例(总是给出Public Matrix(,) As Cell):

Dim x,y as integer
Dim apple as Cell = GetARandomAppleFrom(Matrix)
x=apple.GetArrayPos.x
y=apple.GetArrayPos.y
Console.WriteLine(String.Format("An Apple is in {0}, {1}",x,y)

关于这个问题的必要性的附带问题

目前我正在使用以下 sn-p 代码将所有单元格初始化为零值,因为使用 Matrix.Initialize() 失败了,将每个元素设置为空。

如果方法描述说它调用了默认构造函数,那么为什么会失败?

尽管从编码/效率的角度来看,我怀疑我的初始化是否正确,因为我认为双循环并不是那么好......

 For x = 0 To Me.zWidth
     For y = 0 To Me.zHeight
         Matrix.SetValue(New Cell(CellTypes.Void), x, y)
     Next
 Next

我现在坚持。因此这里有一个

可能的解决方案

这意味着我可以在初始化时将索引传递给 Position 字段 - 通过构造函数 - 像这样......

 For x = 0 To Me.zWidth
     For y = 0 To Me.zHeight
         Matrix.SetValue(New Cell(CellTypes.Void,x,y), x, y)
     Next
 Next

但是,由于 Cell 可能会改变位置或被覆盖,我希望它的位置是动态确定的。

但是,如果雷达没有更好的结果,我肯定会使用这种方法,然后根据位置变化更新值,

附录

一些可能有用或没用的信息:

  • 矩阵大小小于或等于 (512,512)
  • 这将成为等距(所以没有 3d,但我已经在单元格中有一个高度变量)游戏的地形数据地图生成器,具有相当小的地图,支持山脉、河流等表面特征,

【问题讨论】:

  • 您只有两个选择:(1)将位置传递给 Cell 构造函数(正如您已经提到并被拒绝)或(2)通过搜索容器中的单元格来按需计算位置( O(N) 操作)
  • 我的问题是,为什么GetPosCell 的方法?你有充分的理由,还是只是因为它对你来说是自然而然的?因为根据我的经验,这些问题实际上相当棘手,并且让它们“正确”有时涉及做出违反直觉的选择。在这种情况下,我认为细胞根本不应该知道自己的位置。你最初是如何获得对单元格的引用的?不管你怎么做,这可能不是一个好主意——而不是存储对单元格的直接引用,你应该遍历矩阵。
  • 我正在为一款具有相当小地图的游戏制作地形数据地图生成器原型,并支持山脉、河流等表面特征

标签: c# arrays vb.net matrix


【解决方案1】:

您为什么不能直接减少随机选择器以返回找到的 x,y 值并使用它来检索您的单元格?像这样的:

Dim pt as Point
pt = GetRandomPosition()
Dim apple as Cell = Matrix(pt.X,pt.Y)
Console.WriteLine(String.Format("An Apple is in {0}, {1}",pt.X,pt.Y)

【讨论】:

  • 我想让Cell 自己提供它,因为这是一个模拟,在该模拟中我还将在不知道之前查询Cell 的位置。随机拾取是对位置检索系统的测试。 :P
【解决方案2】:

这确实是一个建模问题。我个人更喜欢细胞知道他们的位置,因为这对他们来说似乎很重要,但是对于一个你似乎不喜欢这种方法,对于两个,当更新位置时,这必须在两个领域中完成(通过辅助方法)一次 - 在受影响的单元格和网格中,这可能是有问题的。因此,还有其他事情:

如何从简单的二维数组转向构建自己的类型,比如更智能的数组,它不仅将单元格网格保持为简单的二维数组,而且还记录每个 Cell 及其坐标 --一个字典,将每个包含的Cell 映射到一对表示xy 的整数。我们称该智能阵列为SmartArray。它需要移动单元格的方法,这些方法以原子方式更新地图和网格(这没关系,因为所有更改都在SmartArray“领域”内)。然后你可以问SmartArray 实例“网格上的哪个单元格c?”您将在O(1) 中得到答案。这将是对内存占用速度的权衡。但是,每个Cell 都必须知道它们包含SmartArray,这样它就知道该问谁了。

您也可以省略地图并保留查询方法,但每次提出问题时让它们遍历网格。答案将是相同的,查找将采用O(n^2),但移动单元格会更容易,因为您只需更新一个结构。这将使权衡转向一个有利于内存占用而不是速度的权衡,它本质上是您在 q 中提到的双循环。

【讨论】:

    【解决方案3】:

    首先要初始化 N 个元素,你必须调用你的初始化器 N 次,没有效率问题。

    回答您的问题:您的项目不应该关心它的位置。集合中项目的位置不是项目本身的问题,如果您移动项目或更改集合,可能会很快导致头痛。 如果您的收藏从 2d 矩阵变为 3d 矩阵怎么办?你必须重写代码并添加一个 Z 变量(这只是一个简单的例子)。

    我会尝试以另一种方式完全构建我的代码/解决方案。

    顺便说一句,一个项目可以通过查找对自身的引用来定位自己在集合中的位置。 (根据需要使代码适应您的矩阵)

    GetPosition( Array source)
    {
        foreach(var element in source)
           Object.ReferenceEquals(this,element)
    }
    

    性能很差,因为您循环了集合,但它可能满足您的需求

    【讨论】:

    • 我不知道我们可以在多索引数组上做一个for each...酷! “另一种方式”是什么意思?
    • 如果您深入研究您想要实现的目标,我们可能会建议您遵循正确的模式。看来您正在试图找到解决结构性问题的技巧。
    猜你喜欢
    • 1970-01-01
    • 2020-08-26
    • 1970-01-01
    • 2020-04-13
    • 1970-01-01
    • 2016-10-28
    • 2016-11-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多