【问题标题】:Points are not being added to the score when correct answer is selected选择正确答案时,分数不会被添加到分数中
【发布时间】:2019-06-12 02:42:43
【问题描述】:

我正在制作一个琐事游戏。当用户点击屏幕上的流派按钮来回答问题时,会弹出另一个窗口,其中包含问题和 4 个 jbuttons 作为可能的答案。我尝试对其进行编程,当点击正确的选项时,积分将被添加到用户的分数中,如果点击了不正确的选项,他们将失去生命,但它不起作用。

我制作了一个按钮处理程序,当他们点击一个流派时,它会打开一个带有 4 个选项的问题。在此之下,我放了一个 if else if 语句。如果点击正确的答案,给用户积分,否则,如果它不正确,带走一条生命。

private static class ButtonHandler implements ActionListener
    {
        public void actionPerformed (ActionEvent e)
        {

            if (e.getSource () == btnT1)
            {
                frame2.setVisible (true);
                btnT1.setEnabled (false);
                qTitle.setText ("Solar energy generates electricity from what source?");
                a1.setText ("The water");
                a2.setText ("The sun");
                a3.setText ("Fossil fuels");
                a4.setText ("The wind");

                if (e.getSource () == a2)
                {
                    score = score + 100;
                    frame2.setVisible (false);
                }
                else if (e.getSource () != a2)
                {
                    lives = lives - 1;
                    frame2.setVisible (false);
                }

            }

我想增加分数并夺走生命,但它不起作用。你能帮我让它工作吗?感谢所有帮助,谢谢。

此外,此代码也可能有助于解决问题。这些都是面板、按钮、动作监听器等等。

private static void guiApp ()
    {

        ButtonHandler onClick = new ButtonHandler (); // calls on ButtonHandler class

        // Creating JPanels
        JPanel gameBoard = new JPanel ();
        JPanel titlePanel = new JPanel ();
        JPanel bottomPanel = new JPanel ();

        gameBoard.setLayout (new GridLayout (4, 5, 4, 4));
        titlePanel.setLayout (new BoxLayout (titlePanel, BoxLayout.PAGE_AXIS));
        bottomPanel.setLayout (new BoxLayout (bottomPanel, BoxLayout.PAGE_AXIS));

        JFrame frame = new JFrame ("Trivia Game");
        frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

        // To monitor button clicks
        btnT1.addActionListener (onClick);
        btnT2.addActionListener (onClick);
        btnT3.addActionListener (onClick);
        btnS1.addActionListener (onClick);
        btnS2.addActionListener (onClick);
        btnS3.addActionListener (onClick);
        btnF1.addActionListener (onClick);
        btnF2.addActionListener (onClick);
        btnF3.addActionListener (onClick);
        btnM1.addActionListener (onClick);
        btnM2.addActionListener (onClick);
        btnM3.addActionListener (onClick);
        btnG1.addActionListener (onClick);
        btnG2.addActionListener (onClick);
        btnG3.addActionListener (onClick); 

        // Formatting widgets
        Font titleFont = new Font ("Forte", Font.BOLD, 36);

        title.setFont (titleFont);
        title.setHorizontalAlignment (title.CENTER);
        tech.setHorizontalAlignment (tech.CENTER);
        sports.setHorizontalAlignment (sports.CENTER);
        food.setHorizontalAlignment (food.CENTER);
        movies.setHorizontalAlignment (movies.CENTER);
        geo.setHorizontalAlignment (geo.CENTER);

        titlePanel.add (title);

        // Adds buttons to panel
        gameBoard.add (tech);
        gameBoard.add (sports);
        gameBoard.add (food);
        gameBoard.add (movies);
        gameBoard.add (geo);
        gameBoard.add (btnT1);
        gameBoard.add (btnS1);
        gameBoard.add (btnF1);
        gameBoard.add (btnM1);
        gameBoard.add (btnG1);
        gameBoard.add (btnT2);
        gameBoard.add (btnS2);
        gameBoard.add (btnF2);
        gameBoard.add (btnM2);
        gameBoard.add (btnG2);
        gameBoard.add (btnT3);
        gameBoard.add (btnS3);
        gameBoard.add (btnF3);
        gameBoard.add (btnM3);
        gameBoard.add (btnG3);
        bottomPanel.add (scoreText);
        bottomPanel.add (livesText);

        //Get the frame's content pane
        Container contentPane = frame.getContentPane ();

        // add panel to frame
        contentPane.add (gameBoard, BorderLayout.CENTER);
        contentPane.add (titlePanel, BorderLayout.NORTH);
        contentPane.add (bottomPanel, BorderLayout.SOUTH);

        //size the window.
        frame.setSize (550, 500);
        frame.setVisible (true);

        // Questions window
        JPanel qPanel = new JPanel ();

        qPanel.setLayout(new BoxLayout(qPanel,BoxLayout.PAGE_AXIS));

        JFrame frame2 = new JFrame ("Question");
        frame2.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

        a1.addActionListener (onClick);
        a2.addActionListener (onClick);
        a3.addActionListener (onClick);
        a4.addActionListener (onClick);

        qPanel.add (qTitle);
        qPanel.add (a1);
        qPanel.add (a2);
        qPanel.add (a3);
        qPanel.add (a4);        

        Container contentPane2 = frame2.getContentPane ();

        contentPane2.add (qPanel);

        //size the window.
        frame2.setSize (500, 200);
        frame2.setVisible (false);

        //Results Window
        JPanel resultsPanel = new JPanel ();
        JPanel rBottomPanel = new JPanel ();

        resultsPanel.setLayout(new BorderLayout());
        rBottomPanel.setLayout (new BoxLayout (rBottomPanel, BoxLayout.LINE_AXIS));

        JFrame frame3 = new JFrame ("Results");
        frame3.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

        resultsPanel.add (resultsMessage, BorderLayout.NORTH);
        rBottomPanel.add (reset, BorderLayout.SOUTH);
        rBottomPanel.add (exit, BorderLayout.SOUTH);

        Container contentPane3 = frame3.getContentPane ();

        contentPane3.add (resultsPanel);
        contentPane3.add (rBottomPanel, BorderLayout.SOUTH);

        //size the window.
        frame3.setSize (400, 300);
        frame3.setVisible (false);
    }

【问题讨论】:

  • 1.通过巧妙地使用数组、集合和循环,可以减少很多重复代码。 2. 这样做可以使你的代码更容易调试。 3. 如果您需要我们帮助找出代码无法正常工作的原因,最好在您的问题中创建并发布一个有效的minimal reproducible example / minimal reproducible example 程序。否则我们真的无法测试这段代码。
  • 当你的监听器被激活时,源是btnT1。在用户有时间与新问题进行交互之前,它不会神奇地更改为 a1、a2 或 a3,因此按钮侦听器实际上没有多大意义。
  • 这就像您在问用户是否在用户有机会做出选择之前做出了正确的选择。

标签: java swing variables jbutton actionlistener


【解决方案1】:

这里的逻辑是错误的:

private static class ButtonHandler implements ActionListener
{
    public void actionPerformed (ActionEvent e)
    {

        if (e.getSource () == btnT1)
        {
            frame2.setVisible (true);
            btnT1.setEnabled (false);
            qTitle.setText ("Solar energy generates electricity from what source?");
            a1.setText ("The water");
            a2.setText ("The sun");
            a3.setText ("Fossil fuels");
            a4.setText ("The wind");

            if (e.getSource () == a2)
            {
                score = score + 100;
                frame2.setVisible (false);
            }
            else if (e.getSource () != a2)
            {
                lives = lives - 1;
                frame2.setVisible (false);
            }

        }

此处理程序将在按下 btnT1 时被激活您的逻辑测试用户有机会做出选择之前。

为此,a1、a2、a3 和 a4 上的侦听器需要具有此侦听器所具有的逻辑。

如果这是我的程序,我会将我的 GUI(“视图”)与程序的逻辑部分(“模型”)分开,我会创建一个非 GUI 问题类,其中包含包含正确答案的问题文本,可以检查正确性,以及一个 GUI QuestionView,它显示问题并可以检查用户对它所持有的模型(问题)的响应——我将整个事情分开,并且不要尝试像您一样对其进行硬编码。

顺便说一句,请阅读The Use of Multiple JFrames, Good/Bad Practice?


例如,我将为 Question 创建一个单独的类,一个非 GUI 类,其中包含一个问题字符串、一个答案字符串和一个可能的答案ArrayList<String>,其中包含用户可以选择的所有答案,像这样可以工作:

public class Question {
    private String question;
    private List<String> possibleAnswers;
    private String answer;

    public Question(String question, List<String> possibleAnswers, String answer) {
        this.question = question;
        this.answer = answer;

        // randomize things:
        this.possibleAnswers = new ArrayList<>(possibleAnswers);
        Collections.shuffle(this.possibleAnswers);
    }

    public String getQuestion() {
        return question;
    }

    public List<String> getPossibleAnswers() {
        return possibleAnswers;
    }

    public String getAnswer() {
        return answer;
    }

    // test if String matches answer
    public boolean test(String possibleAnswer) {
        return answer.equals(possibleAnswer);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Q: ");
        sb.append(question);
        sb.append("; ");
        sb.append("A: ");
        sb.append(answer);
        sb.append("; ");
        sb.append(possibleAnswers);
        return sb.toString();
    }
}

我会将数据与代码分开,并创建一个简单的文本文件来保存问题。再次保持简单。在为我制作的示例程序创建的文件中,问题数据保存在几行中,用空行分隔问题。每个问题的第一行包含问题文本,下一行是正确答案,接下来的几行是错误答案。同样,空行分隔问题。请注意,在上面的 Question 类构造函数中,我随机化了答案,因此在实际的 Question 对象中,不再保证第一个可能的答案是正确的。文本文件可能如下所示:

问题文件.txt

Who is buried in Grant's tomb?
Ulysses Grant
George Washington
Abraham Lincoln
Donald Trump

What color was Washington's white horse?
White
Blue
Green
Brown

How many days are there in a week?
7
4
2
3

What is 2 + 2?
4
2
11
I have no idea?

What is the largest celestial body in the solar system?
The sun
Jupiter 
Mars
What is the solar system?

我将创建代码以逐行读取此文件,在读取时创建 Question 对象,并将它们放入ArrayList&lt;Question&gt;

然后,我将创建一个 JPanel,将单个问题显示为 GUI,使用 JLabel 显示问题字符串,一组 JRadioButtons 保存在嵌套 JPanel 中,该 JPanel 使用 GridLayout 保存可能的答案字符串,以及JButton 提交用户的选择进行评分。

例如:

@SuppressWarnings("serial")
public class QuestionViewPanel extends JPanel {
    private Question question; // model for this view
    private JLabel questionLabel;
    private ButtonGroup answersGroup = new ButtonGroup();
    private JButton submitButton = new JButton("Submit");
    private JButton clearAnswerButton = new JButton("Clear Answer");

    public QuestionViewPanel(Question question) {
        this.question = question;

        questionLabel = new JLabel(question.getQuestion());
        questionLabel.setBorder(BorderFactory.createTitledBorder("Question:"));

        JPanel possAnswersPanel = new JPanel(new GridLayout(0, 1));
        possAnswersPanel.setBorder(BorderFactory.createTitledBorder("Possible Answers:"));
        for (String possAnswer : question.getPossibleAnswers()) {
            JRadioButton rBtn = new JRadioButton(possAnswer);
            rBtn.setActionCommand(possAnswer);
            answersGroup.add(rBtn);
            possAnswersPanel.add(rBtn);
        }

        clearAnswerButton.setMnemonic(KeyEvent.VK_C);
        clearAnswerButton.addActionListener(e -> answersGroup.clearSelection());
        submitButton.setMnemonic(KeyEvent.VK_S);
        JPanel bottomPanel = new JPanel();
        bottomPanel.add(submitButton);
        bottomPanel.add(clearAnswerButton);

        setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        setLayout(new BorderLayout(5, 5));
        add(questionLabel, BorderLayout.PAGE_START);
        add(possAnswersPanel, BorderLayout.CENTER);
        add(bottomPanel, BorderLayout.PAGE_END);
    }

    public void addSubmitListener(ActionListener listener) {
        submitButton.addActionListener(listener);
    }

    public Question getQuestion() {
        return question;
    }

    public boolean testAnswer() {
        boolean result = false;
        ButtonModel model = answersGroup.getSelection();
        if (model != null) {
            String possibleAnswer = model.getActionCommand();
            result = question.test(possibleAnswer);
        }
        return result;
    }

}

然后创建一个快速而肮脏的驱动程序类,一个创建 GUI,一个使用 CardLayout 来交换 QuestionViewPanel,并将所有东西放在一起:

@SuppressWarnings("serial")
public class QuestionTest extends JPanel {
    // This String likely needs to be changed
    private static final String RESOURCE_PATH = "QuestionsFile.txt";
    private List<Question> questionsList = new ArrayList<>();
    private List<QuestionViewPanel> questionViewList = new ArrayList<>();
    private CardLayout cardLayout = new CardLayout();
    private JPanel questionViewShowPanel = new JPanel(cardLayout);

    public QuestionTest(List<Question> questionsList) {
        this.questionsList = questionsList;
        for (Question question : questionsList) {
            QuestionViewPanel qView = new QuestionViewPanel(question);
            qView.addSubmitListener(new SubmitListener(qView));
            questionViewShowPanel.add(qView, question.getQuestion());
        }
        setLayout(new BorderLayout());
        add(questionViewShowPanel);
    }

    private class SubmitListener implements ActionListener {
        private QuestionViewPanel qView;

        public SubmitListener(QuestionViewPanel qView) {
            this.qView = qView;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            boolean result = qView.testAnswer();
            String text = result ? "Correct!" : "Wrong!  The correct answer is: " 
                        + qView.getQuestion().getAnswer();
            JOptionPane.showMessageDialog(qView, text, "Result", JOptionPane.PLAIN_MESSAGE);
            cardLayout.next(questionViewShowPanel);
        }
    }

    private static void createAndShowGui(List<Question> questionsList) {
        QuestionTest mainPanel = new QuestionTest(questionsList);

        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);  
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        final List<Question> questionsList = new ArrayList<>();

        InputStream questionsStream = QuestionTest.class.getResourceAsStream(RESOURCE_PATH);
        Scanner scanner = new Scanner(questionsStream);
        String question = "";
        String answer = "";
        List<String> possibleAnswers = new ArrayList<>();
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();           
            if (line.trim().isEmpty()) {
                if (!question.trim().isEmpty()) {
                    questionsList.add(new Question(question, possibleAnswers, answer));
                    question = "";
                    answer = "";
                    possibleAnswers = new ArrayList<>();
                }
            } else if (question.trim().isEmpty()) {
                question = line;
            } else {
                possibleAnswers.add(line);
                if (answer.trim().isBlank()) {
                    answer = line;
                }
            }
        }
        if (!question.trim().isEmpty()) {
            questionsList.add(new Question(question, possibleAnswers, answer));
            question = "";
            answer = "";
            possibleAnswers = new ArrayList<>();
        }
        if (scanner != null) {
            scanner.close();
        }

        SwingUtilities.invokeLater(() -> createAndShowGui(questionsList));
    }
}

此代码中的 GUI 如下所示:

【讨论】:

  • 感谢您向我解释这一点,这是有道理的,为什么它不起作用。您有任何可能的解决方案或建议吗?
  • @BlueElectro:见编辑。听众需要在 a1、a2、a3... 按钮上。而且您还需要停止对这些东西进行硬编码——将问题与 GUI 分开。这将使您的代码更加灵活。
猜你喜欢
  • 2022-01-20
  • 1970-01-01
  • 2018-06-23
  • 2017-07-23
  • 2022-11-13
  • 1970-01-01
  • 2018-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多