【问题标题】:How can I correctly copy a set of objects without referring to the originals or duplicating those referred to multiple times?如何正确复制一组对象而不引用原件或复制多次引用的对象?
【发布时间】:2014-07-19 03:32:23
【问题描述】:

我有一个GameState 对象。它包含诸如玩家、玩家的手和其中的牌、玩家资源的状态和位置等内容。几乎所有东西都至少与另一件事相关联——卡牌知道他们在哪一手牌,资源知道他们属于哪个玩家,等等。

我想创建一个系统来告诉玩家两个GameStates 之间的区别。它会比较状态并返回“如果你做了这个动作,这些事情就会改变”。执行此操作的最简单方法似乎是复制 GameState 并将操作应用于副本,然后将副本与原始副本进行比较。

我已经查看了一些浅拷贝和深拷贝的实现,但我可以很快预见到一个对象属于两个不同对象的问题。一个例子是一些玩家代币;玩家有一个属于他们的所有令牌的列表(例如,玩家可以了解他们都在哪里),并且令牌所在的空间有一个所有令牌的列表(例如,如果空间受到可以影响其上所有标记的事物的影响)。如果我做一个深拷贝,那么播放器和空间将引用同一个令牌的两个不同副本;如果我进行浅拷贝,那么所有内容都将引用原始GameState 中存在的对象。我不能选择一侧总是浅而另一侧总是深,因为也许令牌会从棋盘上移除并且没有空间,或者令牌会与玩家分离并稍后被另一个人捡起.甚至可能有一些牌在使用时会针对玩家,所以如果它针对的是用户,那就是循环引用。

基本上,我想做这三个图表中的第一个,但是我不知道如何避免第二种和第三种情况。

我怀疑一般来说没有简单的方法可以做到这一点,但我想我不妨问问。

我在 Unity3D 中使用 C#,以防万一。

【问题讨论】:

  • 似乎您必须自己定义克隆逻辑。另一种想法是创建两个方法,将 GameState 对象读取和写入 Stream。然后你可以编写如下代码: MemoryStream ms = ...;写(门状态,毫秒); GameState 克隆 = 读取(毫秒);如果您打算将 GameState 保存到磁盘,这些也会很有用。

标签: c# unity3d deep-copy shallow-copy


【解决方案1】:

作为克隆的捷径,您可能会从序列化中获得一些好处。我经常使用 JSON.NET (NewtonSoft) 来执行类似的操作,只要您的对象不太复杂,您通常可以通过基本的“序列化然后反序列化”过程来解决问题。顺便说一句,JSON.NET 可以很好地处理循环引用等。

我认为你更大的挑战是向用户展示“将会发生什么”信息。

【讨论】:

    【解决方案2】:

    几个月前,我为奥赛罗棋类游戏编写了一个简单的 AI。我需要将每次移动的不同游戏状态传递给我的评估函数。我所做的只是“克隆”计算所需的基本数据,并将“克隆的数据”传递给其他函数。在函数内部,我所做的事情或多或少与您的建议相同,即模拟每个状态下每个动作的结果。

    我认为自己定义“克隆”策略是不可避免的。但是,您只能从原始 GameState 实例中提取有用的数据。玩家的名字肯定不重要吧?

    【讨论】:

      猜你喜欢
      • 2013-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-17
      • 2011-02-07
      • 2011-09-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多