如何向用户询问一组问题并存储答案

时间:2017-04-07 11:59:23

标签: java

我正在制作基于文本的冒险游戏。我试图让游戏根据他们对某些问题的回答为玩家选择一个“类”。 (例如,如果玩家选择偷偷摸摸或隐秘的倾斜答案,那么游戏将为他们分配适合此类人的“流氓”类。

到目前为止,我已经创建了这个我想稍后在主程序中调用的方法,然后基于返回值,我将使用另一个条件语句通过调用set方法来设置player类

到目前为止,这是我的方法。我正在前进的方式,我将有一个非常长的chooseSpec方法,因为我想要至少10个问题。我的问题具体是什么是最有效的方法来解决这个问题,并且正在以一种方法完成所有这一切的正确方法?

public static int chooseSpec(Scanner in) {
    int war = 0; //counter for warrior class
    int rog = 0; //counter for rogue class
    int mag = 0; //counter for magic class
    int choice; //users choice, a number between 1 and 3.

    System.out.println("While out hunting, you come across a deer which has been badly mauled by a wolf. What do you do?" + "\n" +
                       "1. Draw your dagger and end it's suffering" + "\n" +
                       "2. Attempt to heal it with a herbal concoction, knowing it may not work." + "\n" +
                       "3. Leave it, and allow nature to take it's course.");
    choice = in.nextInt(); 

    switch (choice) {
        case 1: 
            war += 1;
            break;

        case 2:
            mag += 1;
            break;
        case 3:
            rog +=1;
    } 
    return choice;
}

3 个答案:

答案 0 :(得分:2)

您应该将所有问题和答案存储在对象中。这样,你可以混合每个问题的答案,目前选择总是1将保证相同的答案。

其次,它允许您为每个问题添加任意数量的答案,甚至可以在每次开始游戏时混合订单。

在这里使用更多的java抽象也很好:

public ClassType chooseSpec(List<Question> questions, Scanner in) {

     List<ClassType> selectedAnswers = new ArrayList<>(questions.size());
      // iterate over all your questions
    for(Question question: questions) {
        // print question and all answers
        System.out.println(question.getQuestion() + "\n"
                + question.getAnswers().stream().map(Answer::getQuestion)
                .collect(Collectors.joining("\n")));

        int choice = in.nextInt();
        if(choice >= question.getAnswers().size()){
          // check if answer is within the scope
          throw IllegalArgumentException("There are only "+question.getAnswers() +" answers");
        }
        // add selected answer type to global result list 
        selectedAnswers.add(question.getAnswers().get(choice-1).getClassType());
    }

    return findMostPolularClass(selectedAnswers);
}

private ClassType findMostPolularClass(List<ClassType> selectedAnswers){
    // might be too fancy, but it will find most frequent answer
    Map<ClassType, Long> occurences = selectedAnswers.stream().collect(Collectors.groupingBy(e -> e, Collectors.counting()));
    return occurences.entrySet().stream()
            .max(Comparator.comparing(Map.Entry::getValue)).get().getKey();
 }

持有问题及所有答案:

static class Question {

    private final String question;
    private final List<Answer> answers;

    public Question(String question, List<Answer> answers) {
        this.question = question;
        this.answers = answers;
    }

    public String getQuestion() {
        return question;
    }

    public List<Answer> getAnswers() {
        return answers;
    }
}

每个答案都定义了答案文本,以及它最适合哪个班级

class Answer {

    private final String question;
    private final ClassType classType;
    // static constructors, help to work with this model
    public static Answer mageAnswer(String question) {
        return new Answer(question, ClassType.MAGE);
    }

    public static Answer wariorAnswer(String question) {
        return new Answer(question, ClassType.WARIOR);
    }

    private Answer(String question, ClassType classType) {
        this.question = question;
        this.classType = classType;
    }

    public ClassType getClassType() {
        return classType;
    }

    public String getQuestion() {
        return question;
    }
}

//将所有课程存储在此处,比记住数字更具可读性:)

enum ClassType {
    MAGE, WARIOR, ARCHER
}

答案 1 :(得分:0)

您应该将所有问题存储在一个集合中。像arraylist。假设你有10个问题,这个方法应该在foreach循环中调用迭代问题arraylist。这样,您的方法将被重用。

答案 2 :(得分:0)

根据您的要求,您希望处理三种不同的Professions

  • 战士
  • 盗贼
  • 法师

这些职业没有任何状态,新的实例不是动态构建的。因此,Enumeration可以代表他们:

public enum Profession {
    WARRIOR,
    ROGUE,
    MAGE;
}

接下来,您要求玩家选择与{a Answer和2. Profession相关联的Token,即您从键盘上读取的输入:

public class Answer {

    public static Answer of(Profession profession, String token, String description) {
        return new Answer(description, profession, token);
    }

    private final String description;
    private final Profession profession;
    private final String token;

    public Answer(String description, Profession profession, String token) {
        this.description = requireNonNull(description);
        this.profession = requireNonNull(profession);
        this.token = requireNonNull(token);
    }

    public String getDescription() {
        return description;
    }

    public Profession getProfession() {
        return this.profession;
    }

    public String getToken() {
        return token;
    }

    public boolean isMatch(String token) {
        return this.token.equals(token);
    }
}

您想要对Answer做些什么:

  • 将其呈现给玩家。
  • 检查从玩家获得的令牌是否与Answer相关联的令牌匹配。
  • 并以可读的形式构建Answer

AnswersQuestions的一部分,它不保持状态或动态创建。 Enumeration再一次代表他们:

public enum Question {

    MAULED_DEER("While out hunting, you come across a deer which has been badly mauled by a wolf. What do you do?",
        Answer.of(WARRIOR, "1", "Draw your dagger and end it's suffering."),
        Answer.of(ROGUE, "2", "Attempt to heal it with a herbal concoction, knowing it may not work."),
        Answer.of(MAGE, "3", "Leave it, and allow nature to take it's course.")),

    GAME_DEVELOPMENT("While playing games you decided to develop your very own. Which language do you choose?",
            Answer.of(MAGE, "a", "OOD with Java."),
            Answer.of(WARRIOR, "b", "OOD and FP using Scala."),
            Answer.of(ROGUE, "c", "Pure FP with Haskel."));

    private final String description;
    private final List<Answer> answers;

    Question(String description, Answer... answers) {
        this.description = description;
        this.answers = Arrays.asList(answers);
    }

    public String getDescription() {
        return description;
    }

    public List<Answer> getAnswers() {
        return answers;
    }

    public Set<Answer> getMatches(String token) {
        return answers.stream()
                .filter(answer -> answer.isMatch(token))
                .collect(Collectors.toSet());
    }
}

Questions必须是:

  • 与他们的Answers一起呈现。
  • 应确定哪个Answers匹配给定的令牌(从播放器获得)。

但是你要向玩家询问很多Questions并想跟踪他给出的Answers。更确切地说,您与Profession相关联的Answer。并且您希望跟踪每个Profession的当前得分:

public class Scores {

    private Map<Profession, AtomicInteger> scores = new HashMap<Profession, AtomicInteger>() {{
        for (Profession profession : Profession.values()) {
            put(profession, new AtomicInteger());
        }
    }};

    private int max = 0;

    public void incrementIf(boolean isTrue, Profession profession) {
        if (isTrue) {
            int score = scores.get(profession).incrementAndGet();
            max = Math.max(max, score);
        }
    }

    public Set<Profession> getWinners() {
        return Arrays.stream(Profession.values())
                .filter(profession -> scores.get(profession).get() == max)
                .collect(Collectors.toSet());
    }
}

类型Scores的责任在于确定是否以及Profession增加分数。最后它应该计算查询的Winners

public class Inquiry {

    public Set<Profession> obtainChoice(Scanner scanner) {
        Scores scores = new Scores();
        for (Question question : Question.values()) {
            String token = ask(question, scanner);
            question.getAnswers().forEach(answer ->
                    scores.incrementIf(answer.isMatch(token), answer.getProfession()));
        }
        return scores.getWinners();
    }

    private String ask(Question question, Scanner scanner) {
        System.out.println(question.getDescription());
        question.getAnswers().forEach(answer ->
                System.out.println(answer.getToken() + ") " + answer.getDescription()));
        do {
            String token = scanner.nextLine();
            for (Answer answer : question.getAnswers()) {
                if (token.equals(answer.getToken())) {
                    return token;
                }
            }
            System.out.println("Try again and select a valid answer please!");
        } while (true);
    }
}

缺少的最后一块拼图是应用程序本身,它会触发查询:

public class Game {

    public static void main(String[] args) {
        try (Scanner scanner = new Scanner(System.in)) {
            Set<Profession> choices = new Inquiry().obtainChoice(scanner);
            if (choices.size() == 1) {
                System.out.println("You are a true " + choices.iterator().next());
            } else {
                System.out.println("You havn't found your path yet and hence must choose between:");
                choices.forEach(profession -> System.out.println(" - " + profession));
            }
        }
    }
}

此设计力求readableextendable,因此您可以轻松更改内容。

玩得开心!