如何设计依赖关系列表并存储它

时间:2015-05-06 01:35:59

标签: c# sqlite design-patterns

我正在开发一个游戏,作为一系列任务。用户可以随时使用许多任务,但某些任务依赖于其他任务在可用之前先完成。你可以看看WoW可能是最好的实现。当您完成各种任务时,游戏状态会更新以反映用户可用的新选项。

我很好奇如何有效地构建它。例如:

Quest A: no dependency
Quest B: no dependency
Quest C: dependent on B complete
Quest D: dependent on C and A both complete

基本上,这变成了节点C,其中B作为父节点,节点D节点C和节点D作为父节点。当我们完成任务时,该应用程序将查看具有所有已完成父项的孩子作为用户可用的孩子。

我确信这是一个常见问题。我理论上可以理解它,但是我正在努力实现它。

我在C#/ sqlite工作。我想将Quest数据存储在我的数据库中。我正在考虑一个名为Quest(不是部落)的表来获取任务细节,但我正在努力寻找依赖信息的最佳实现。特别是,以易于维护的方式构建它。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

我认为您可以在代码中设置依赖项,因为它们通常不会更改(如果有的话)。要实现您想要的目标,您需要使用一组依赖任务创建Quest类。

public class Quest
{
    private List<Quest> quests = new List<Quest>();

    // you need a validation in setter.
    public bool Complete { get; set; }

    public bool CanStart()
    {
        return quests.All(o => o.Complete);
    }

    public void Add(Quest quest)
    {
        this.quests.Add(quest);
    }

    public void Remove(Quest quest)
    {
        this.quests.Remove(quest);
    }
}

您可以通过向集合中添加依赖Quest来配置Quest依赖项。例如,要设置4个具有依赖关系的任务,就像你想要的问题一样,如下所示。

[TestMethod]
public void SetupABCDQuestTest()
{
    var questA = new Quest();
    Assert.IsTrue(questA.CanStart());

    var questB = new Quest();
    Assert.IsTrue(questB.CanStart());

    var questC = new Quest();
    questC.Add(questB);
    Assert.IsFalse(questC.CanStart());

    questB.Complete = true;
    Assert.IsTrue(questC.CanStart());

    var questD = new Quest();
    questD.Add(questA);
    questD.Add(questC);
    Assert.IsFalse(questD.CanStart());

    questA.Complete = true;
    questC.Complete = true;

    Assert.IsTrue(questD.CanStart());
}

使用Decorator Pattern,您可以按照自己的方式设置依赖关系,无论是复杂还是简单!

答案 1 :(得分:0)

这是一种多对多的关系,所以显而易见的解决方案是junction table

CREATE TABLE Quest (
    ID,
    [...]
);
CREATE TABLE QuestDependency (
    Child  REFERENCES Quest(ID),
    Parent REFERENCES Quest(ID)
);