0

I'm working on a simple GUI project to get the foundations of Java Swing. I created a Rock Paper Scissors game which you play against the computer which i implemented a GUI for

My text based GUI Form for Rock, Paper,Scissors

My problem is that once either my score or the computers score reach a value of 3, i want the text on the frame to change. I've tried to implement the code to check each time the variable increases in the button function but it still does not works, neither does implementing the function in the main, the game doesn't change any text or stop once the scores reach 3.

    chooseRock.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                String cc = getCompChoice();
                if (cc.equalsIgnoreCase("Paper")) {
                    compcount++;

                    if(compcount == 3){
                         winner.setText("Computer Wins");
                       }

                    compChoice.setText("Computers Choice: " + cc);

This code shows the GUI object and the listener for selecting "Rock", the code is the same for both paper and Scissors. Both compchoice and playchoice are declared with the other attributes at the top.

    gameScreen(String title){
     super(title);

    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setContentPane(gameBoard);
    this.pack();


        chooseRock.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                String cc = getCompChoice();
                if (cc.equalsIgnoreCase("Paper")) {
                    compcount++;

                    compChoice.setText("Computers Choice: " + cc);

                    compScore.setText("Computer Score: " + compcount);

                } else if (cc.equalsIgnoreCase("Scissors")) {
                    playcount++;

                    compChoice.setText("Computers Choice: " + cc);

                    playerScore.setText("Your Score: " + playcount);
                } else {

                    compChoice.setText("Computers Choice: " + cc + " Its a DRAW!");
                }


            }
        });

This is a function I've written to check the scores and display the winner, the 'winner' text is displayed at the top of the panel and has a placeholder.

    public void checkScore(){
    if(playcount == 3 ){ 
        winner.setText("GAME OVER - PLAYER WINS");
        chooseRock.setEnabled(false);
        chooseScissors.setEnabled(false);
        choosePaper.setEnabled(false);

    }else if(compcount == 3 ){
        winner.setText("GAME OVER - COMPUTER WINS! BETTER LUCK NEXT TIME");
        chooseRock.setEnabled(false);
        chooseScissors.setEnabled(false);
        choosePaper.setEnabled(false);
    }
}

Is there any way to take the variable written inside the listener and use it to change the text field or is there some way conditions like this should be implemented?

Megz0192
  • 1
  • 2
  • Where do you call the `checkScore()` method? Within the action listener, I hope – DontKnowMuchBut Getting Better May 16 '20 at 11:17
  • 2
    Also, when asking about code with an undiagnosed bug, it's often best to create and post a [mre] program in your question. This allows us to have running code that reproduces the bug for us, and often allows us to better understand your code and your problem. – DontKnowMuchBut Getting Better May 16 '20 at 11:19
  • @DontKnowMuchButGettingBetter I feel quite stupid, your solution did work, I had to copy the checkScore() method into each action listener. Thank You so much! – Megz0192 May 16 '20 at 11:40

1 Answers1

2

You should call checkScore() within the ActionListeners actionPerformed method so that the score is calculated and acted upon with each button press.


Interesting aside:

One way to simplify your listeners is to create an enum, one that checks for win, something like:

public enum RPS {
    ROCK("Rock"), PAPER("Paper"), SCISSORS("Scissors");
    private String text;

    private RPS(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }

    @Override
    public String toString() {
        return text;
    }

This way, your check for win can be as simple as adding a comparing method to the enum:

   // returns 1 for win, -1 for loss, 0 for tie
    public int compare(RPS other) {
        int length = values().length;
        int delta = (length + ordinal() - other.ordinal()) % length; 
        return delta != 2 ? delta : -1;
    }
}        

Each enum value has an ordinal() method that returns its order of declaration, 0 for ROCK, 1 for PAPER, and 2 for SCISSORS. The delta equation simply gets the difference between these ordinal values, adds 3 (the "size" of the enum) and checks the remainder of the calculation. If it is equal to 1, then that enum "wins" the battle, if 0, then its a tie and if 2, then this enum "loses". This can simplify your listeners.

For example, here I create a single listener class for all buttons:

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;

@SuppressWarnings("serial")
public class RockPaperScissors extends JPanel {
    public static final int MAX_SCORE = 3;
    private static final int PANEL_WIDTH = 600;
    private int myScore;
    private int compScore;
    private JLabel statusLabel = new JLabel(" ");
    private JLabel myChoiceLabel = new JLabel();
    private JLabel compChoiceLabel = new JLabel();
    private JLabel myScoreLabel = new JLabel();
    private JLabel compScoreLabel = new JLabel();
    private List<Action> actionList = new ArrayList<>();

    public RockPaperScissors() {
        JPanel statusPanel = new JPanel();
        statusPanel.setBorder(BorderFactory.createTitledBorder("Status"));
        statusPanel.add(statusLabel);

        JPanel scorePanel = new JPanel();
        scorePanel.setBorder(BorderFactory.createTitledBorder("Score"));
        scorePanel.add(new JLabel("My Score:"));
        scorePanel.add(myScoreLabel);
        scorePanel.add(Box.createHorizontalStrut(15));
        scorePanel.add(new JLabel("Comp Score:"));
        scorePanel.add(compScoreLabel);

        JPanel selectionPanel = new JPanel();
        selectionPanel.setBorder(BorderFactory.createTitledBorder("Selections"));
        selectionPanel.add(new JLabel("My Choice:"));
        selectionPanel.add(myChoiceLabel);
        selectionPanel.add(Box.createHorizontalStrut(15));
        selectionPanel.add(new JLabel("Comp Choice:"));
        selectionPanel.add(compChoiceLabel);

        JPanel btnPanel = new JPanel(new GridLayout(1, 0, 3, 0));
        for (RPS rps : RPS.values()) {
            Action action = new ButtonAction(rps);
            actionList.add(action);
            JButton button = new JButton(action);
            btnPanel.add(button);
        }

        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
        add(statusPanel);
        add(scorePanel);
        add(selectionPanel);
        add(btnPanel);
    }

    @Override
    public Dimension getPreferredSize() {
        Dimension superSize = super.getPreferredSize();
        int height = superSize.height;
        int width = Math.max(superSize.width, PANEL_WIDTH);
        return new Dimension(width, height);
    }

    private class ButtonAction extends AbstractAction {
        private RPS rps;

        public ButtonAction(RPS rps) {
            super(rps.getText());
            this.rps = rps;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            int randomValue = (int) (RPS.values().length * Math.random());
            RPS compChoice = RPS.values()[randomValue];

            myChoiceLabel.setText(rps.getText());
            compChoiceLabel.setText(compChoice.getText());

            if (rps.compare(compChoice) > 0) {
                statusLabel.setText("I Win");
                myScore++;
            } else if (rps.compare(compChoice) < 0) {
                statusLabel.setText("Computer Wins");
                compScore++;
            } else {
                statusLabel.setText("Draw");
            }

            myScoreLabel.setText(String.valueOf(myScore));
            compScoreLabel.setText(String.valueOf(compScore));

            if (myScore >= MAX_SCORE) {
                statusLabel.setText("I Win the Game");
            } else if (compScore >= MAX_SCORE) {
                statusLabel.setText("Computer Wins the Game");
            }

            if (myScore >= MAX_SCORE || compScore >= MAX_SCORE) {
                for (Action action : actionList) {
                    action.setEnabled(false);
                }
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui() {
        RockPaperScissors mainPanel = new RockPaperScissors();
        JFrame frame = new JFrame("RockPaperScissors");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

}
enum RPS {
    ROCK("Rock"), PAPER("Paper"), SCISSORS("Scissors");
    private String text;

    private RPS(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }

    @Override
    public String toString() {
        return text;
    }

    public int compare(RPS other) {
        int length = values().length;
        int delta = (length + ordinal() - other.ordinal()) % length;
        return delta != 2 ? delta : -1;
    }
}