Java分支测验:路径统计方法实现及设计合理性咨询
问题描述
我正在开发一个带分支逻辑的测验项目,使用simple.json库处理JSON数据——后续问题由前序答案决定。相关问题与选项如下:
{"What is your marital status?": ["Single", "Married"]} {"Are you planning on getting married next year?": ["Yes", "No"]} {"How long have you been married?": ["Less than a year", "More than a year"]} {"Have you celebrated your one year anniversary?": ["Yes", "No"]}
我已经实现了测验的分支逻辑,设计了如下结构的JSON配置文件:
{ "What is your marital status?": { "Single": "Are you planning on getting married next year?", "Married": "How long have you been married?" }, "Are you planning on getting married next year?": { "Yes": "0 Thanks for your answers! We hope that you will build a cool family!", "No": "0 Thanks for your answers! Who knows, maybe you'll find someone significant in your life!" }, "How long have you been married?": { "Less than a year": "0 Thanks for your answers! We hope that you will celebrate your one year anniversary soon!", "More than a year": "Have you celebrated your one year anniversary?" }, "Have you celebrated your one year anniversary?": { "Yes": "0 Wow, cool! Keep it up! Thanks for your answers.", "No": "0 We think you should fix it next time! Thanks for your answers!" } }
同时编写了QuizHandler类来运行测验:
public class QuizHandler { private static final Logger LOGGER = Logger.getLogger("QuizHandler"); public void runQuiz(JSONObject configuration) { List<Object> keys = configuration.keySet().stream().toList(); LOGGER.info("keys: " + keys); String question = "What is your marital status?"; Scanner scanner = new Scanner(System.in); while (question.charAt(0) != '0') { System.out.println(question); System.out.println("Possible answers: " + ((JSONObject) configuration.get(question)).keySet().toString()); question = ((JSONObject) configuration.get(question)).get(scanner.nextLine()).toString(); } System.out.println(question.substring(2)); } }
配置中以0开头的内容表示测验结束,当前运行逻辑正常。
现在需要实现QuizService类中的方法,统计测验的所有可能路径数量,并生成如下格式的JSON结果:
{ "paths": { "number": 3, "list": [ [{"What is your marital status?": "Single"}, {"Are you planning on getting married next year?": "Yes/No"}], [{"What is your marital status?": "Married"}, {"How long have you been married?": "Less than a year"}], [{"What is your marital status?": "Married"}, {"How long have you been married?": "More than a year"}, {"Have you celebrated your one year anniversary?": "Yes/No"}] ] } }
待实现的类框架:
public class QuizService { // TODO: Implement a method that will count the number of possible ways to go through the quiz }
请问如何实现该方法?当前的测验逻辑设计是否合理?
解决方案
1. 实现路径统计方法
可以采用**深度优先搜索(DFS)**遍历所有可能的测验路径,收集路径信息后生成目标JSON结构。以下是具体实现:
import org.json.simple.JSONArray; import org.json.simple.JSONObject; import java.util.ArrayList; import java.util.List; import java.util.Map; public class QuizService { // 主方法:生成包含路径数量和列表的JSON结果 public JSONObject generateQuizPaths(JSONObject configuration) { List<List<JSONObject>> allPaths = new ArrayList<>(); // 从起始问题开始遍历 dfs(configuration, "What is your marital status?", new ArrayList<>(), allPaths); // 构建结果JSON JSONObject result = new JSONObject(); JSONObject pathsObj = new JSONObject(); pathsObj.put("number", allPaths.size()); JSONArray pathList = new JSONArray(); for (List<JSONObject> path : allPaths) { JSONArray jsonPath = new JSONArray(); jsonPath.addAll(path); pathList.add(jsonPath); } pathsObj.put("list", pathList); result.put("paths", pathsObj); return result; } // 深度优先搜索遍历路径 private void dfs(JSONObject configuration, String currentQuestion, List<JSONObject> currentPath, List<List<JSONObject>> allPaths) { JSONObject questionOptions = (JSONObject) configuration.get(currentQuestion); if (questionOptions == null) { return; } // 分类当前问题的选项:指向结束的答案 / 指向后续问题的答案 Map<String, String> optionsMap = (Map<String, String>) questionOptions; List<String> endAnswers = new ArrayList<>(); List<String> nextQuestionAnswers = new ArrayList<>(); for (Map.Entry<String, String> entry : optionsMap.entrySet()) { String answer = entry.getKey(); String next = entry.getValue(); if (next.startsWith("0")) { endAnswers.add(answer); } else { nextQuestionAnswers.add(answer); } } // 处理指向结束的答案:合并为一个路径条目 if (!endAnswers.isEmpty()) { JSONObject questionEntry = new JSONObject(); questionEntry.put(currentQuestion, String.join("/", endAnswers)); List<JSONObject> newPath = new ArrayList<>(currentPath); newPath.add(questionEntry); allPaths.add(newPath); } // 递归处理指向后续问题的答案 for (String answer : nextQuestionAnswers) { String nextQuestion = optionsMap.get(answer); JSONObject singleEntry = new JSONObject(); singleEntry.put(currentQuestion, answer); List<JSONObject> newPath = new ArrayList<>(currentPath); newPath.add(singleEntry); dfs(configuration, nextQuestion, newPath, allPaths); } } }
实现说明
- 使用DFS递归遍历每个问题的选项,区分选项是指向结束还是下一个问题
- 对于直接指向结束的多个选项(如Yes/No),合并成一个路径条目,避免生成重复路径
- 最终收集所有路径后,按照要求的JSON格式组装结果
2. 现有测验逻辑设计合理性分析
优点
- 结构直观:JSON配置直接映射问题与分支关系,易于理解和维护
- 逻辑简单:
QuizHandler的循环逻辑清晰,通过字符串前缀判断终止条件,实现成本低 - 扩展性较好:新增问题或分支只需修改JSON配置,无需大量改动Java代码
潜在问题与优化建议
- 硬编码起始问题:
QuizHandler中直接写死起始问题"What is your marital status?",后续修改起始点需改动代码,建议在JSON配置中新增"startQuestion"字段指定起始问题 - 终止标识脆弱:用
0作为结束标识,若后续结束文案出现以0开头的内容会导致逻辑错误,建议改用结构化标识,比如{"type": "end", "message": "xxx"} - 缺失输入校验:用户输入无效答案时会直接抛出异常,建议增加输入校验逻辑,提示用户重新输入有效选项
- 路径统计复杂度高:当前配置依赖字符串前缀判断结束,增加了路径统计的解析成本,改用结构化配置(区分问题节点和结束节点)会让统计逻辑更简洁
内容的提问来源于stack exchange,提问作者Serhii Chernikov
相关产品推荐
相关产品推荐

