3

今天早些时候我在想一个小游戏的想法,偶然发现了如何实现它。这个想法是,玩家可以做出一系列动作,产生一点影响,但如果按照特定的顺序进行会产生更大的影响。到目前为止一切顺利,我知道该怎么做。显然,我必须让它变得更复杂(因为我们喜欢让它更复杂),所以我认为序列可能有不止一种可能的路径,它们都会产生更大的影响,尽管是不同的。此外,某些序列的一部分可能是其他序列的开始,甚至整​​个序列可能包含在其他更大的序列中。现在我不确定实现这一点的最佳方法。不过,我有一些想法。

1)我可以实现一个循环n链表。但是由于移动列表永远不会结束,我担心它可能会导致堆栈溢出™。这个想法是每个节点都会有 n 个子节点,并且在收到命令后,它可能会将您带到他的一个子节点,或者,如果没有子节点可用于该命令,则将您带回到起点。到达任何孩子时,都会执行几个功能,从而产生大小影响。但是,这可能会导致树上出现许多重复的节点,以应对所有可能以该特定动作结束并具有不同效果的序列,这可能很难维护,但我不确定。我从来没有在代码上尝试过这么复杂的东西,只是理论上。这个算法是否存在并且有名字?这是个好主意吗?

2)我可以实现一个状态机。然后,我不会在链表中徘徊,而是有一些巨大的嵌套开关来调用函数并相应地更新机器状态。似乎实现起来更简单,但是......好吧......看起来并不有趣......也不优雅。巨型开关在我看来总是丑陋,但这会更好吗?

3) 建议?我很好,但我很缺乏经验。编码领域的好处是,无论你的问题多么奇怪,过去有人解决了它,但你必须知道去哪里找。有人可能有比我更好的主意,我真的很想听听建议。

4

7 回答 7

3

我不能完全确定我完全理解你在说什么,但作为一个类似的情况,假设有人在键盘上输入了无穷无尽的数字流。'117' 是一个魔术序列,'468' 是另一个,'411799' 是另一个(包含第一个)。

因此,如果用户输入:

55468411799

您想在 *s 处触发“魔术事件”:

55468*4117*99*

或类似的东西,对吧?如果这与您正在谈论的问题相似,那么(类似Java的伪代码)之类的东西呢:

MagicSequence fireworks = new MagicSequence(new FireworksAction(), 1, 1, 7);
MagicSequence playMusic = new MagicSequence(new MusicAction(), 4, 6, 8);
MagicSequence fixUserADrink = new MagicSequence(new ManhattanAction(), 4, 1, 1, 7, 9, 9);

Collection<MagicSequence> sequences = ... all of the above ...;

while (true) {
  int num = readNumberFromUser();
  for (MagicSequence seq : sequences) {
    seq.handleNumber(num);
  }
}

而 MagicSequence 有类似的东西:

Action action = ... populated from constructor ...;
int[] sequence = ... populated from constructor ...;
int position = 0;

public void handleNumber(int num) {
  if (num == sequence[position]) {
    // They've entered the next number in the sequence
    position++;
    if (position == sequence.length) {
       // They've got it all!
       action.fire();
       position = 0; // Or disable this Sequence from accepting more numbers if it's a once-off
    }
  } else {
    position = 0; // missed a number, start again!
  }
}
于 2008-10-09T13:53:59.437 回答
2

无论如何,您可能都想实现一个状态机,但您不必对状态转换进行硬编码。
尝试制作状态图,其中状态 A 到状态 B 之间的链接意味着 A 可以通向 B。
然后您可以在运行时遍历图以查找玩家去向。

编辑:您可以将图形节点定义为:
-state-id
-指向其他状态的链接列表,其中每个链接定义:
-state-id
-precondition,状态列表在进入此状态之前必须访问的内容

于 2008-10-09T13:36:05.120 回答
1

您所描述的内容听起来与游戏实况文明中的技术树非常相似。

我不知道文明作者是如何构建他们的,但我倾向于使用多重图来表示可能的“动作”——有些你可以在没有“经验”的情况下开始,一旦你进入其中,会有多条路径通到最后。

画出在游戏的每个阶段你可以有哪些潜在的选择,然后画出从一些选项到其他选项的界限。

这应该让您开始实施,因为图表是 [相对] 易于实施和利用的概念。

于 2008-10-09T13:29:46.240 回答
1

听起来像一个神经网络。您可以创建一个并训练它来识别导致您正在寻找的各种效果的模式。

于 2008-10-09T13:39:08.750 回答
1

您所描述的内容听起来有点类似于依赖图或单词图。你可能会调查那些。

于 2008-10-09T13:50:19.710 回答
1

为您想要的每个效果创建一个小型状态机。在每个用户操作中,将其“广播”到所有状态机。大多数人不会在意,但有些人会前进,或者可能会倒退。当其中一个达到它的目标时,产生预期的效果。

为了保持代码整洁,不要对状态机进行硬编码,而是构建一个简单的数据结构来对状态图进行编码:每个状态都是一个带有一系列有趣事件的节点,每个节点都指向下一个状态的节点。每台机器的状态只是对相应状态节点的引用。

编辑:Cowan 的建议似乎与此等价,但他优化了他的状态机以仅表达简单的序列。似乎足以解决您的特定问题,但更复杂的条件可能需要更通用的解决方案。

于 2008-10-09T14:06:54.543 回答
1

@Cowan,@Javier:好主意,介意我添加吗?

让 MagicSequence 对象监听传入的用户输入流,即通知他们输入(广播),并让他们每个人将输入添加到内部输入流中。当输入不是模式中将让 MagicSequence 触发其操作的预期下一个输入时,此流将被清除。模式完成后,立即触发操作并清除内部输入流。

通过仅向等待它的 MagicSequence 提供输入来优化这一点。这可以通过两种方式完成:

  1. 您有一个对象可以让所有 MagicSequence 与与其模式中的数字对应的事件连接。MagicSequence(1,1,7) 会将自身添加到 got1 和 got7,例如:

    UserInput.got1 += MagicSequnece[i].SendMeInput;

  2. 您可以对此进行优化,以便在每次输入 MagicSequences 从无效事件中注销并注册有效事件之后。

于 2008-10-09T14:29:39.410 回答