1

I am a new to java programming and I am developing a simple a one player TICTACTOE game using swing. Thee are two classes. One main TICTACTOE class which uses an XOButtton class to set up buttons which can listen to click events. I begin by creating an object of this tictactoe class then use this object to call a method called initialCheckButton to find out if the buttons have been clicked 3 timess. If yes it calls another method to find out if the Xs or Os are consecutively displayed.If yes you win. I plan to develop this further but this is just a template. When the GUI dsiplays,clicking on buttons and display of successive Xs or Os does not display the message of the JoptionPane. Any help?

public class TicTacToe extends JFrame {
    JPanel p = new JPanel();
    boolean done = false;
    XOButton buttons[] = new XOButton[9];

    public static void main(String args[]) {
        TicTacToe t = new TicTacToe();

        t.initialCheckButton();
    }

    public TicTacToe() {

        super("TicTacToe");

        setSize(400, 400);
        setResizable(false);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        p.setLayout(new GridLayout(3, 3));
        for (int i = 0; i < 9; i++) {
            buttons[i] = new XOButton();
            p.add(buttons[i]);
        }
        add(p);

        setVisible(true);

    }

    public void initialCheckButton() {
        int sum = 0;

        while (sum <= 3) {

            for (int i = 0; i < 9; i++) {

                if (buttons[i].checkButtonO() == 1) {
                    sum++;
                }

                if (buttons[i].checkButtonX() == 1) {
                    sum++;
                }

            }

        }

        checkButtonFinal();

    }

    public void checkButtonFinal() {
        for (int i = 0; i < 9; i++)
            for (int j = i + 3; j < 9; j++) {
                for (int k = j + 3; k < 9; k++) {

                    if (buttons[i].checkButtonO() == buttons[j].checkButtonO() && buttons[k].checkButtonO() == 1)
                        JOptionPane.showMessageDialog(null, "Great, you won");

                    if (buttons[i].checkButtonX() == buttons[j].checkButtonX() && buttons[k].checkButtonX() == 1)
                        JOptionPane.showMessageDialog(null, "Great, you won");

                }

            }

        for (int i = 0; i < 9; i += 3) {
            if (buttons[i].checkButtonO() == buttons[i + 1].checkButtonO() && buttons[i + 2].checkButtonO() == 1)
                JOptionPane.showMessageDialog(null, "Great, you won");
            if (buttons[i].checkButtonX() == buttons[i + 1].checkButtonX() && buttons[i + 2].checkButtonX() == 1)
                JOptionPane.showMessageDialog(null, "Great, you won");

        }

        for (int i = 0; i < 9; i += 2) {
            for (int j = i + 2; j < 9; j += 2)
                for (int k = j + 2; k < 9; k += 2) {
                    if (buttons[i].checkButtonO() == buttons[j].checkButtonO() && buttons[k].checkButtonO() == 1)
                        JOptionPane.showMessageDialog(null, "Great, you won");

                    if (buttons[i].checkButtonX() == buttons[j].checkButtonX() && buttons[k].checkButtonX() == 1)
                        JOptionPane.showMessageDialog(null, "Great, you won");
                }

        }

        for (int i = 0; i < 9; i += 4) {
            for (int j = i + 4; j < 9; j += 4)
                for (int k = j + 4; k < 9; k += 4) {
                    if (buttons[i].checkButtonO() == buttons[j].checkButtonO() && buttons[k].checkButtonO() == 1)
                        JOptionPane.showMessageDialog(null, "Great, you won");
                    if (buttons[i].checkButtonX() == buttons[j].checkButtonX() && buttons[k].checkButtonX() == 1)
                        JOptionPane.showMessageDialog(null, "Great, you won");
                }

        }

    }

    public static class XOButton extends JButton implements ActionListener {
        public int buttonClicked = 0;
        public int buttonClickedX = 0;
        public int buttonClickedO = 0;

        ImageIcon X, O;
        byte value = 0;
        /*
         * 0:nothing 1:X 2:O
         */

        public XOButton() {
            X = new ImageIcon(this.getClass().getResource("X.png"));
            O = new ImageIcon(this.getClass().getResource("O.png"));
            this.addActionListener(this);
        }

        public void actionPerformed(ActionEvent e) {

            value++;
            value %= 3;
            switch (value) {
            case 0:
                setIcon(null);
                buttonClicked = 0;
                break;
            case 1:
                setIcon(X);
                buttonClickedX = 1;
                break;
            case 2:
                setIcon(O);
                buttonClickedO = 1;
                break;
            }
        }

        public int checkButtonO() {
            return buttonClickedO;

        }

        public int checkButtonX() {
            return buttonClickedX;

        }
    }
}
MarionaGlenni
  • 63
  • 1
  • 7
  • Check the first 2 lines of `initialCheckButton` method. – George Z. Apr 13 '19 at 10:55
  • George Z. It was a mistake I made. I initially put 3 but while copying, I put 0 – MarionaGlenni Apr 13 '19 at 11:02
  • changing the while loop to sum<=3 does not help – MarionaGlenni Apr 13 '19 at 14:19
  • @MarionaGlenni Why do you have the buttons in a 1-dim array of size 9 and not in a 2-dim array of the size 3x3? Wouldn't that make more sense? – Progman Apr 13 '19 at 16:04
  • @MarionaGlenni What exactly is the problem/question? Please see: [Why is “Can someone help me?” not an actual question?](http://meta.stackoverflow.com/q/284236) and check [ask]. – Progman Apr 13 '19 at 16:06
  • Please explain what is not working as expected. Is it `checkButtonFinal()` ? – c0der Apr 13 '19 at 16:36
  • Thanks c0der and Progman. My problem is that the while loop is supposed to check if 3 successive buttons have been clicked, then exexute the checkButtonFinal() method that checks if you havethe clicked buttons lined up properly and finally lets you know you have won. It does not work this way and I think the problem starts from the while loop – MarionaGlenni Apr 13 '19 at 16:48
  • You need to use @ before the user name. For example: @Progman – c0der Apr 14 '19 at 04:05

1 Answers1

2

The following is a refactored version of your code that includes some documented changes :

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class TicTacToe extends JFrame {

    private static int ROW = 3, COLS = 3;
    private final JPanel p;
    private final XOButton buttons[];
    //static counter, so it has the same value for all button instances
    //used as a toggle between X and O
    private static int counter = 0;

    public static void main(String args[]) {
       new TicTacToe();
    }

    public TicTacToe() {

        super("TicTacToe");

        setResizable(false);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        buttons = new XOButton[ROW*COLS];
        p = new JPanel();
        p.setLayout(new GridLayout(3, 3));
        initialize();
        add(p);
        pack();
        setVisible(true);
    }

    private void initialize(){
          for (int i = 0; i < 9; i++) {
              buttons[i] = new XOButton();
              p.add(buttons[i]);
          }
    }

    //restart game
    private void restart(){
        p.removeAll();
        initialize();
        revalidate();
    }

    private void checkButtons() {

        //many similar for loops are not easy to follow
        //refactor into methods
        XOButton[] winningButtons = checkRows();
        if( winningButtons != null) {
            won(winningButtons);
        }

        winningButtons = checkCols();
        if( winningButtons != null) {
            won(winningButtons);
        }

        winningButtons =  checkDIagonals();
        if( winningButtons != null) {
            won(winningButtons);
        }
    }

    //returns winning buttons, or null
    private XOButton[] checkRows() {

        for(int row = 0; row < buttons.length ; row +=3 ){
            int totalX = buttons[row].buttonClickedX + buttons[row+1].buttonClickedX+ buttons[row+2].buttonClickedX ;
            int totalO = buttons[row].buttonClickedO + buttons[row+1].buttonClickedO+ buttons[row+2].buttonClickedO ;
            if(totalX >=3 || totalO >=3) return new XOButton[]{buttons[row], buttons[row+1], buttons[row+2]};
        }
        return null;
    }

    //returns winning buttons, or null
    private XOButton[] checkCols() {

        for(int col = 0; col < COLS ; col++ ){
            System.out.println(col+"-"+(col+3)+"-"+(col+6));
            int totalX = buttons[col].buttonClickedX + buttons[col+3].buttonClickedX+ buttons[col+6].buttonClickedX ;
            int totalO = buttons[col].buttonClickedO + buttons[col+3].buttonClickedO+ buttons[col+6].buttonClickedO ;
            if(totalX >=3 || totalO >=3) return new XOButton[]{buttons[col], buttons[col+3], buttons[col+6]};
        }
        return null;
    }

    //returns winning buttons, or null
    private XOButton[] checkDIagonals() {

        int totalX = buttons[0].buttonClickedX + buttons[4].buttonClickedX+ buttons[8].buttonClickedX ;
        int totalO = buttons[0].buttonClickedO + buttons[4].buttonClickedO+ buttons[8].buttonClickedO ;
        if(totalX >=3 || totalO >=3) return new XOButton[]{buttons[0], buttons[4], buttons[8]};

        totalX = buttons[2].buttonClickedX + buttons[4].buttonClickedX+ buttons[6].buttonClickedX ;
        totalO = buttons[2].buttonClickedO + buttons[4].buttonClickedO+ buttons[6].buttonClickedO ;
        if(totalX >=3 || totalO >=3) return new XOButton[]{buttons[2], buttons[4], buttons[6]};

        return null;
    }

    //invoked when there is a winner
    private void won(XOButton[] winningButtons) {

        for(XOButton button : winningButtons){
            button.setBackground(Color.PINK);
        }

        JOptionPane.showMessageDialog(null, "Great, you won");
        restart(); //start new game
    }

    class XOButton extends JButton implements ActionListener {

        private int  buttonClicked = 0, buttonClickedX = 0,  buttonClickedO = 0;
        String X, O; //avoid using unavailable images when posting

        public XOButton() {
            X = "X";
            O = "O";
            this.addActionListener(this);
            setPreferredSize(new Dimension(40,40));
        }

        @Override
        public void actionPerformed(ActionEvent e) {

            if(buttonClicked  > 0 ) return; //invoke only on first click
            buttonClicked ++;
            counter = (counter+1)%2;  //changes from 1 to 0 and back to 1

            switch (counter) {

                case 0:
                    setText(X);
                    buttonClickedX = 1;
                    break;
                case 1:
                    setText(O);
                    buttonClickedO = 1;
                    break;
            }

            checkButtons();//check buttons after every click
        }

        public int checkButtonO() {
            return buttonClickedO;
        }

        public int checkButtonX() {
            return buttonClickedX;
        }
    }
}

enter image description here

c0der
  • 18,467
  • 6
  • 33
  • 65
  • I have gone through the changes you have done to the code and this is quite ingenious. I think my main problem was the use of while loops and many for loops. This is a lesson for me. I understand how the the code you have revised works but I still dont understand why mine does not work. I will take yours as the solution. Thanks a million – MarionaGlenni Apr 14 '19 at 16:27
  • To understand what is wrong with the original code, I recommend using a debugger. It is not complicated to use and it is an essential tool for any programmer. You may want to read: [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) – c0der Apr 14 '19 at 17:52