基于任务双属性构建层级列表及查找父任务的技术问询
嘿,我来给你捋清楚这个任务依赖链的实现方案,咱们从需求到代码一步步拆解,保证清晰易懂:
核心需求拆解
首先得明确咱们要解决的问题:手里的quests数据是无序存储的,规则是当A任务结束时,会授予B任务。我们需要:
- 找到起始任务:没有任何任务能解锁它,是链条的起点
- 找到最终任务:它结束后不会解锁任何任务,是链条的终点
- 梳理出完整的任务触发链
- 确定每个任务的父任务(也就是解锁它的那个任务)
技术实现步骤
1. 构建快速映射表
首先用两个字典(哈希表)把任务间的关联关系存起来,这样后续查找效率拉满:
endToGrantMap:键是结束的任务ID(questEndID),值是被授予的任务ID(questGrantID)——用来快速查“某个任务结束后会解锁谁”grantToEndMap:键是被授予的任务ID(questGrantID),值是触发它的结束任务ID(questEndID)——用来快速查“某个任务是被谁解锁的”
用C#实现的代码示例(对应你给出的任务类):
// 模拟示例数据 var questsList = new List<quests> { new quests { questGrantID = "quest234", questEndID = "quest567" }, new quests { questGrantID = "quest987", questEndID = "quest234" }, new quests { questGrantID = "quest654", questEndID = "quest987" } }; // 初始化映射字典 Dictionary<string, string> endToGrantMap = new Dictionary<string, string>(); Dictionary<string, string> grantToEndMap = new Dictionary<string, string>(); foreach (var quest in questsList) { endToGrantMap[quest.questEndID] = quest.questGrantID; grantToEndMap[quest.questGrantID] = quest.questEndID; }
2. 定位起始/最终任务
- 起始任务:找不到任何任务能解锁它(也就是它的ID不在
endToGrantMap的键里,因为没有任务结束会授予它) - 最终任务:它结束后不会解锁任何任务(也就是它的ID不在
grantToEndMap的键里,因为它不是任何任务的授予触发源)
代码示例:
// 找起始任务 string startQuest = questsList.Select(q => q.questGrantID) .First(id => !endToGrantMap.ContainsKey(id)); // 示例里结果是 quest654 // 找最终任务 string endQuest = questsList.Select(q => q.questEndID) .First(id => !grantToEndMap.ContainsKey(id)); // 示例里结果是 quest567
3. 构建完整任务链
从起始任务出发,顺着grantToEndMap就能遍历出完整的触发顺序:
List<string> fullQuestChain = new List<string>(); string currentQuest = startQuest; // 遍历所有有后续的任务 while (currentQuest != null) { fullQuestChain.Add(currentQuest); grantToEndMap.TryGetValue(currentQuest, out currentQuest); } // 加上最终任务 fullQuestChain.Add(endQuest); // 示例里的结果就是:["quest654", "quest987", "quest234", "quest567"]
4. 生成父任务映射
如果需要单独存储每个任务的父任务(解锁它的任务),可以直接用字典存储:
Dictionary<string, string> parentQuestMap = new Dictionary<string, string>(); foreach (var quest in questsList) { // 规则:questEndID结束 → 授予questGrantID,所以questGrantID的父任务是questEndID parentQuestMap[quest.questGrantID] = quest.questEndID; } // 示例里: // parentQuestMap["quest234"] = "quest567" // parentQuestMap["quest987"] = "quest234" // parentQuestMap["quest654"] = "quest987"
扩展:处理多分支场景
如果遇到一个任务结束后授予多个任务,或者存在多条独立任务链的情况,只需要把字典的 value 改成列表即可:
比如用Dictionary<string, List<string>> endToGrantsMap来存储一个任务对应的多个被授予任务,后续遍历逻辑稍作调整就能兼容。
总结
整个方案的核心就是用哈希表快速建立任务间的关联,避免低效的遍历查找,时间复杂度是O(n),不管任务数据量多大都能高效处理。
内容的提问来源于stack exchange,提问作者strykstaguy
相关产品推荐
相关产品推荐

