如何简化多参数else if判断并解决问答游戏空值问题
优化“21问”游戏代码:简化逻辑+解决空值与归类歧义问题
我正在开发一款类似“21问”的游戏,让用户想一个食物、动物或物品词汇,电脑通过提问猜测词汇。目前的核心代码存在两个关键问题:
- 硬编码大量判断条件,新增或修改词汇时维护成本极高
- 条件触发式提问导致空值问题,且部分词汇存在归类歧义(比如用户可能把企鹅归为水生或陆生,干扰识别)
以下是针对性的优化方案:
1. 用数据驱动替代硬编码判断
把每个动物的属性抽象为实体类,将所有动物数据存储在集合中,匹配时遍历集合检查属性是否符合,彻底消除冗长的if-else链。
定义动物属性实体类
import java.util.List; class Animal { private String name; private List<String> sizes; // 支持多尺寸,比如猫可以是Small/Medium private List<String> domains; // 支持多领域,比如企鹅同时属于Land/Water private List<String> bodyOfWaters; private boolean hasWings; private int legs; private List<String> skinTypes; private boolean isCommonPet; private boolean isDomesticated; private String dangerLevel; private String category; // Feline/Canine等 // 构造器 public Animal(String name, List<String> sizes, List<String> domains, List<String> bodyOfWaters, boolean hasWings, int legs, List<String> skinTypes, boolean isCommonPet, boolean isDomesticated, String dangerLevel, String category) { this.name = name; this.sizes = sizes; this.domains = domains; this.bodyOfWaters = bodyOfWaters; this.hasWings = hasWings; this.legs = legs; this.skinTypes = skinTypes; this.isCommonPet = isCommonPet; this.isDomesticated = isDomesticated; this.dangerLevel = dangerLevel; this.category = category; } // getter方法 public String getName() { return name; } public List<String> getSizes() { return sizes; } public List<String> getDomains() { return domains; } public List<String> getBodyOfWaters() { return bodyOfWaters; } public boolean isHasWings() { return hasWings; } public int getLegs() { return legs; } public List<String> getSkinTypes() { return skinTypes; } public boolean isCommonPet() { return isCommonPet; } public boolean isDomesticated() { return isDomesticated; } public String getDangerLevel() { return dangerLevel; } public String getCategory() { return category; } }
初始化动物数据
import java.util.List; import java.util.ArrayList; List<Animal> animals = new ArrayList<>(); // 添加老鼠 animals.add(new Animal("Mouse", List.of("Small"), List.of("Land"), null, false, 4, List.of("Fur", "Hair"), true, false, null, null)); // 添加鱼 animals.add(new Animal("Fish", List.of("Small"), List.of("Water"), List.of("Most"), false, 0, List.of("Scales"), true, false, null, null)); // 添加鲨鱼 animals.add(new Animal("Shark", List.of("Large"), List.of("Water"), List.of("Oceans", "Seas"), false, 0, List.of("Skin"), false, false, "Dangerous", null)); // 添加猫 animals.add(new Animal("Cat", List.of("Small", "Medium"), List.of("Land"), null, false, 4, List.of("Fur"), true, true, null, "Feline")); // 添加企鹅(解决归类歧义) animals.add(new Animal("Penguin", List.of("Small", "Medium"), List.of("Land", "Water"), List.of("Oceans", "Antarctic"), false, 2, List.of("Feathers"), false, false, null, null));
2. 解决空值与条件触发提问问题
对于未触发提问的属性(值为null),匹配时直接跳过检查;对于用户输入的答案,用Optional包装避免空指针异常。
编写匹配逻辑
import java.util.Optional; import java.util.ArrayList; import java.util.List; // 用户输入的答案,用Optional包装避免空值 Optional<String> userSize = Optional.ofNullable(aA1); Optional<String> userDomain = Optional.ofNullable(aA2); Optional<String> userBodyOfWater = Optional.ofNullable(aAw1); Optional<String> userWings = Optional.ofNullable(aA3); Optional<Integer> userLegs = Optional.ofNullable(aA4); Optional<String> userSkinType = Optional.ofNullable(aA5); Optional<String> userCommonPet = Optional.ofNullable(aA6); Optional<String> userDomesticated = Optional.ofNullable(aAld2); Optional<String> userDangerLevel = Optional.ofNullable(aAl1); Optional<String> userCategory = Optional.ofNullable(aAfc); // 遍历动物列表匹配 List<Animal> matches = new ArrayList<>(); for (Animal animal : animals) { boolean match = true; // 检查尺寸:用户输入不为空时,动物尺寸列表包含用户输入 if (userSize.isPresent() && !animal.getSizes().contains(userSize.get())) { match = false; } // 检查领域:用户输入不为空时,动物领域列表包含用户输入(解决企鹅归类问题) if (match && userDomain.isPresent() && !animal.getDomains().contains(userDomain.get())) { match = false; } // 检查水域类型:用户输入不为空时,动物水域列表包含用户输入 if (match && userBodyOfWater.isPresent() && animal.getBodyOfWaters() != null && !animal.getBodyOfWaters().contains(userBodyOfWater.get())) { match = false; } // 检查翅膀:用户输入不为空时,转换为boolean匹配 if (match && userWings.isPresent()) { boolean hasWings = "Yes".equals(userWings.get()); if (animal.isHasWings() != hasWings) { match = false; } } // 检查腿数:用户输入不为空时匹配 if (match && userLegs.isPresent() && animal.getLegs() != userLegs.get()) { match = false; } // 检查皮肤类型:用户输入不为空时,动物皮肤列表包含用户输入 if (match && userSkinType.isPresent() && !animal.getSkinTypes().contains(userSkinType.get())) { match = false; } // 检查是否常见宠物:用户输入不为空时转换为boolean匹配 if (match && userCommonPet.isPresent()) { boolean isPet = "Yes".equals(userCommonPet.get()); if (animal.isCommonPet() != isPet) { match = false; } } // 检查是否驯化:用户输入不为空时转换为boolean匹配 if (match && userDomesticated.isPresent()) { boolean isDomesticated = "Yes".equals(userDomesticated.get()); if (animal.isDomesticated() != isDomesticated) { match = false; } } // 检查危险等级:用户输入不为空时匹配 if (match && userDangerLevel.isPresent() && !userDangerLevel.get().equals(animal.getDangerLevel())) { match = false; } // 检查类别:用户输入不为空时匹配 if (match && userCategory.isPresent() && !userCategory.get().equals(animal.getCategory())) { match = false; } if (match) { matches.add(animal); } } // 输出结果 if (matches.size() == 1) { System.out.println(matches.get(0).getName() + "!"); } else if (matches.size() > 1) { System.out.println("我猜可能是:"); matches.forEach(animal -> System.out.println("- " + animal.getName())); } else { System.out.println("Sorry! That's not an animal we recognize yet. Better luck next time!"); System.exit(1); }
3. 核心优化点总结
- 数据驱动:新增动物只需添加实体对象,无需修改判断逻辑,大幅降低维护成本
- 空值安全:用
Optional包装用户输入,未提问的属性直接跳过检查,避免空指针异常 - 歧义兼容:每个属性支持多值(比如企鹅同时属于陆生和水生),只要用户选择的属性在动物的属性列表中即视为匹配
- 扩展性强:后续新增食物、物品类别时,只需复用相同的实体类设计和匹配逻辑
内容的提问来源于stack exchange,提问作者JustNeedHelp
相关产品推荐
相关产品推荐

