I used one action listener for an array of buttons that do different things.
Exploring methods.
I am fairly new to java. I just made a tic tac toe program. I am hoping for people to look it over and tell me what they think, ways to make it better, new areas to explore. ect.
I know the Check method is more complicated then it has to be, but I freakin love it.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class tictactoe extends JFrame{

    public static JMenuBar MenuBar = new JMenuBar();
    JMenu File = new JMenu("File");
    JMenu Help = new JMenu("Help");
    JMenu Options = new JMenu("Options");
    JMenuItem NewGame = new JMenuItem("New Game");
    JMenuItem Exit = new JMenuItem("Exit");
    JMenuItem About = new JMenuItem("About");
    JMenuItem Sound = new JMenuItem("Sound");
    JButton[] button = new JButton[9];
    JPanel p1 = new JPanel();
    int[] winCheck = new int[9];//holds value for each button
    int check = 0;//used to hold sum of 3 winCheck value, to determine if anyone has won;
    int player =1;// sets user count for X and Circle
    int load =1;// tells difference between load and reload
    int buttonIndex;//used to index button array
    int TieCheck=0;

    public tictactoe(){
        add(p1);
        MenuBar.add(File);
        MenuBar.add(Help);
        MenuBar.add(Options);
        File.add(NewGame);
        File.add(Exit);
        Help.add(About);
        Options.add(Sound);
        Exit.addActionListener(new ExitListener());
        NewGame.addActionListener(new NewGameListener());}

    
        public class ExitListener implements ActionListener{
        public void actionPerformed(ActionEvent e){
           System.exit(1);
        }
    }


        //Buttons from load must be erased before reload.
        //If not it will just add 9 more buttons to the existing buttons.
        //So I seperated load and reload
        public void firstLoad(){ //first time the user presses New Game
        p1.setLayout(new GridLayout(3,3,0,0));
        for(int i = 0; i<9; i++){
        button[i]= new JButton("");
        p1.add(button[i]);
        button[i].addActionListener(new Play());
        p1.setVisible(true);
        }
    }
    public void reLoad(){
        for(int i=0;i<9;i++){
        winCheck[i] = 0; //sets all the values to check for win back to Zero
        button[i].setEnabled(true);
        p1.remove(button[i]);
        button[i].removeActionListener(new Play());
        }
        player=1;//makes sure X starts first on new game no matter who went last before
        firstLoad();
    }

    public class NewGameListener implements ActionListener{
        public void actionPerformed(ActionEvent e){
        p1.setVisible(false);
        if(load==1){//if its the fist game
        firstLoad();
        load=2;//sets for all reloads
            }
        else{
            reLoad();
        }
        }
    }
    
     public void Xwin(){//just sets what to do when someone wins
         JOptionPane.showMessageDialog(null,"X wins!");
         for(int i=0;i<9;i++){button[i].setEnabled(false);}}
    public void Ywin(){//dido
         JOptionPane.showMessageDialog(null,"Circle wins!");
         for(int i=0;i<9;i++){button[i].setEnabled(false);}}
       
    //IDK but I am pretty sure that this added more demand for computer usage, Creates alot of variables
    //Maybe someone can give me some feed back on that
    //Considering what little time I have been programming and lack of proper training on this,
    //I am proud of it.

    // First for loop loops twice
    //inside  for loop loops 3 times each
    //unless someone wins and then it is kicked out
    //if sum is -3 then Circle wins, If its is Postitve the X wins
    //Inside loop takes the sum of each colum and compares them to 3 or -3
    //If no win on either, inside loop kicks back out.
    //Second time it enters the Inside loop it checks rows

    public void WinCheck(){
            int a=0;//tells inside for loop were to start
            int ai =3;//increments loop start by 3 after ending of loop
            int b=2;//tells inside for loop were to end
            int bi=3;//increments end by 3 after ending of loop
            int c=1;//increment by 3 between start and end of inside loop
            int d=6;//throws while loop if inside loop try to start past 5

            for(int z=1;z<=4;z++){//loops twice unless thrown before
            while(a<=d){// stops for loop at 5 and 2
            for(int i=a;i<=b;i=i+c){
                check=check+winCheck[i];              
            }
                if(check == 3)
                {
                    Xwin();
                    a=9;//kicks inside loop
                    z=9;//kicks outside loop
                    }
                else if(check ==-3){
                    Ywin();
                    a=9;//kicks inside loop
                    z=9;//kicks outside loop
                }
                else{
                check=0;
                a=a+ai;//changes increments after ending of inside loop
                b=b+bi;
                }
                }
            a=0;ai=1;b=6;bi=1;c=3;d=2;// chanes increments for inside loop for the second time through the outside loop
            check = 0;
                }


                
                //check for diagonals
            
            if(winCheck[0]+winCheck[4]+winCheck[8]==3){
                Xwin();
            }
            if(winCheck[0]+winCheck[4]+winCheck[8]==-3){
                Ywin();
            }
            if(winCheck[2]+winCheck[4]+winCheck[6]==3){
                Xwin();
            }
            if(winCheck[2]+winCheck[4]+winCheck[6]==-3){
                Ywin();
            }          
    }
    
    public void click(){
        if(player == 1){
        Font X = new Font("X",Font.PLAIN, 150);
        button[buttonIndex].setFont(X);
        button[buttonIndex].setText("X");
        player = 2;
        winCheck[buttonIndex]= 1;
        }
        else{
        Font O = new Font("O",Font.PLAIN, 150);
        button[buttonIndex].setFont(O);
        button[buttonIndex].setText("O");
        player = 1;
        winCheck[buttonIndex]= -1;
        }

    }
    
    public class Play implements ActionListener{
        public void actionPerformed(ActionEvent e){
                  TieCheck=TieCheck+1;

                  if(TieCheck==9){
                 JOptionPane.showMessageDialog(null,"Tie!");
                }
           for(int i=0; i<button.length; i++){
          if(e.getSource() == button[i]){
               buttonIndex = i;
               button[i].setEnabled(false);
               }
            }
           click();
           WinCheck();
        }
    }

 public static void main(String[] args) {
 JFrame Frame = new tictactoe();
 Frame.setSize(500, 500);
 Frame.setVisible(true);
 Frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
 Frame.setJMenuBar(MenuBar);
    }

}

Recommended Answers

All 11 Replies

Minor points:
Class name should start with Uppercase
Indenting of code in methods and loops not consistent
A method and variable with the same name: Wincheck with different case
Creating a new object on every method call vs once outside the method
Font X = new Font("X",Font.PLAIN, 150);
Undocumented usage of a literal:
winCheck[buttonIndex]= 1; // what does the 1 here mean?

The "tie" logic is buggy. Play several games in a row; you'll see.

(I know what's causing this bug, but I'll let you debug it as an exercise for the student. ;-)

commented: Took time to understand logic +1

Another thought on the logic:
Have a 2 dim array that contains indexes to the winning moves: eg {0,1,2}, {3,4,5} etc for all 8 possible wins and then loop through that array to test for wins vs all the complicated logic in the WinCheck method.

Another thought on the logic:
Have a 2 dim array that contains indexes to the winning moves: eg {0,1,2}, {3,4,5} etc for all 8 possible wins and then loop through that array to test for wins vs all the complicated logic in the WinCheck method.

Norm winCheck[buttonIndex]=1; changes the winCheck value to 1. E.x. the user clicks button[5] and turns to X then winCheck[5]=1; If it turned to circle then winCheck[5]=-1; I am interested in using a 2 dim arrays, but I need to learn more about it. Is it possible to get the sum of a whole row? How would that be different from what I done?

The "tie" logic is buggy. Play several games in a row; you'll see.

(I know what's causing this bug, but I'll let you debug it as an exercise for the student. ;-)

JeffGrigg, Either you plugged my code in or you took time to follow my logic. THANK YOU!
I forgot to change TieCheck back to 0 when the game is restarted.

If you have any ideas on how i can better work with methods and class, that would be helpfull

Those comments should be in the code. Posting them here doesn't help anyone that is reading the code.
Your variable names don't have a useful meaning. winCheck ??? vs theBoard or theSqrs
The literal 1 vs a variable: XmovedHere Defined: final int XmovedHere = 1;
theBoard[5] = XmovedHere;

Is it possible to get the sum of a whole row?

Do that in a loop. If the indexes for the row were in an array (rowIdx) they could be used to sum a "row": theBoard[rowIdx[row][sqrInRow]]

commented: Does not take time to understand before he comments -1

Norm how about you follow the freakin logic. if you took time to do that you would hae know exactly what it was for. And O btw it is in the code in the comments. If something is not commented its because it should be easily uderstandable by the people I want to help. So far on anyones post all I have seen you do is ask a whole bunch of questions and comment on how they name things. I.E. where they capitalize letters. I cant read anything on the board without reading through your useless dribble first.

Critic my work

I am.
Yes, I can read code and figure out what it does.
My point is:
There are better ways to write code that will help the reader more quickly understand the code. Your code does not do that. Well chosen variable names are one way.

What were you looking for when you posted this?
If you can't take criticism don't ask for it.

I was asking for criticism on my methods and logic. Not on how the code was written. Maybe I could have chosen a better name, however that is not were your problem came into play. You did not know what the variable was doing. This is either because you cant follow the logic or you did not try. It is okay if you cant follow it. The loops make it complicated. It is not okay to post anything if you don't understand the logic. It is def not okay if you did not even try.

Example
Someone had classes ( one with a gui and the other out ). They wanted to know how they can call their class without the gui into the class with their gui ( the super class ). They said their professor gave them the code.
The name of their class with gui was MyClass or something
The name of their other class was Firm
He said the professors code was

MyClass Firm = new MyClass();
Firm.setVisible

Clearly he was confused on what the professor ment
He needed

Firm someName = new Firm();

The problem was clear
he even wrote it in the forum for you to see clearly
Instead of reading what he wrote, you asked 100 questions. Most of witch had nothing to do with the problem. The you criticized his capitialization in naming variables and classes. UNDERSTAND BEFORE YOU COMMENT DUDE. Its like that all over the board. If I try to learn something new from any forum (not just mine), I must first look at your dribble and determine if your being useful. Its crazy

OK. Norm you were right about the 2d arrays. I tried it and it made my calculations go alot quicker and made the logic alot easier. Thanks

OK. Norm you were right about the 2d arrays. I tried it and it made my calculations go alot quicker and made the logic alot easier. Thanks

Then it would be nice if you reversed your dump down vote on his profile that you did, due to your ignorance of possible advice.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.