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);
}
}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. ;-)
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]]
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.