1

I am creating a simple TicTacToe game. I created 9 JButtons by using [3][3] matrix. The thing is that I need to check the state of those buttons so I can determine the winner.

I do not know how can I check / access those button through the if statement without some kind of identifier or index. I could create 9 JButton objects and check them using if statements but it does not seem efficient. I know that this is not the best solution for this game and that I should have created a whole class for the logic of the game, but this way seems very efficient and I really would like to know how to do it this way.

Here is the code:

import javax.swing.JFrame;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Font;
import javax.swing.JButton;
import java.awt.GridLayout;

public class AdinTicTacToe extends JFrame implements ActionListener {
    private static final long serialVersionUID = 1L;
    public static final int WIDTH = 500; //Width of the JFrame
    public static final int HEIGHT = 400; //Height of the JFrame

    public static void main(String[] args) {
        AdinTicTacToe gui = new AdinTicTacToe(3, 3);
        gui.setVisible(true);
    }

    //Creating a matrix of buttons to make flexible layout
    JButton[][] buttons = new JButton[3][3];

    {
        for (int row = 0; row < buttons.length; row++) {
            for (int col = 0; col < buttons[0].length; col++) {
                JButton cells = new JButton();
                buttons[row][col] = cells;
                add(cells);
                cells.addActionListener(this);
            }
        }
    }

    //A constructor to set initial values
    public AdinTicTacToe(int rows, int columns) {
        super();
        setSize(WIDTH, HEIGHT);
        setTitle("Tic Tac Toe");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Setting a layout
        setLayout(new GridLayout(rows, columns));
    }

    //Handling button clicks
    boolean check; //Variable to determine the current state of a button

    @Override
    public void actionPerformed(ActionEvent e) {
        //Using getSource method to avoid multiple if statements and make it efficient
        JButton myButton = (JButton) e.getSource();
        if (!check)
            myButton.setText("X");
        ; //Set X to the clicked cell
        if (check)
            myButton.setText("O"); //Set O to the clicked cell
        check = !check; //Reverting the button state 
        myButton.setFont(new Font("Arial", Font.BOLD, 60)); //Set font of X and O
        myButton.setEnabled(false); //Disable button after it gets clicked

    }
}
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
Adin Cebic
  • 39
  • 1
  • 7

1 Answers1

3

Firstly: You don't need the brackets before the initialization.

An OOP-ish approach would be to create a class that contains a reference to a button and the button's index:

public class ButtonIndexPair{
    private JButton button;
    private int indexRow;
    private int indexColumn;
    public ButtonIndexPair(JButton button,int indexRow, int indexColumn){
        this.button = button;
        this.indexRow = indexRow;
        this.indexColumn = indexColumn;
    }
    public int getRow(){
        return indexRow;
    }
    public int getColumn(){
        return indexColumn;
    }
    public JButton getButton(){
        return button;
    }
}

and then when you initialize the button array, do this instead:

JButton cells = new JButton();
buttons[row][col] = new ButtonIndexPair(cells,row,col);
add(cells);
cells.addActionListener(this);

and change the type of the matrix to ButtonIndexPair:

ButtonIndexPair[][] buttons = new ButtonIndexPair[3][3];


@Override
public void actionPerformed(ActionEvent e) {
    //Using getSource method to avoid multiple if statements and make it efficient
    JButton myButton = (JButton) e.getSource();
    ButtonIndexPair theRightPair = buttons[0][0];
    for (int row = 0; row < buttons.length; row++) {
        for (int col = 0; col < buttons[row].length; col++) {
            if(buttons[row][col].getButton().equals(myButton)){
                theRightPair = buttons[row][col];
                break;
            }
        }
    }

    //then you can use 'theRightPair' 

    if (!check)
        myButton.setText("X");
    ; //Set X to the clicked cell
    if (check)
        myButton.setText("O"); //Set O to the clicked cell
    check = !check; //Reverting the button state 
    myButton.setFont(new Font("Arial", Font.BOLD, 60)); //Set font of X and O
    myButton.setEnabled(false); //Disable button after it gets clicked

 }
ItamarG3
  • 4,092
  • 6
  • 31
  • 44
  • But how can I change the matrix type? – Adin Cebic Dec 08 '16 at 20:32
  • Yeah, this seamed good, but I am not able to create object of that class due to the constructor. I need an object to invoke getRow and getColumn methods in order to get those indexes. How do I do it? – Adin Cebic Dec 08 '16 at 21:22
  • @AdinCebic you can loop through the 2D array until you find a button that is like the button clicked (`buttons[i][j].getButton().equals(myButton)`) – ItamarG3 Dec 08 '16 at 21:32
  • I am not that experienced, could you please explain how? – Adin Cebic Dec 08 '16 at 21:36
  • Thanks again! But I have another problem, now when I print out theRightPair, Iget some veird numbers. How to use this data inside a conditional statement. I feel bad and stupid since I asked too much. – Adin Cebic Dec 08 '16 at 21:56
  • @AdinCebic what do you want it to print? – ItamarG3 Dec 08 '16 at 21:57
  • I tried to print that index to the console so I can use it in the conditional statement. I need to know which button is clicked to be able to check whether someone won (X or O player) – Adin Cebic Dec 08 '16 at 22:04
  • @AdinCebic then try to print the row and the column instead – ItamarG3 Dec 08 '16 at 22:21