Hi,
I am making tic tac toe, and I basically have it all working, except the GUI has a few bugs. Right now, I am not using a layout. I am using "setBounds" instead.
When a player wins, an image saying "you win" should be displayed over the title image and the game board. That works, except when you move the mouse over the buttons, the "you win" image is covered by those buttons.
Also, when the program first runs, the buttons are not visible unless you roll over them with a mouse...
Here is the code:
//import everything:
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.applet.AudioClip;
import java.net.*;
//the class with the JFrame and the ActionListner:
public class TicTacToe extends JFrame implements ActionListener
{
//this is an array of the buttons (spots). We use an array, not
//an arrayList because the number of buttons is constant; it does
//not change.
JButton spots[] = new JButton[9];
//this will keep track of turns
int turn = 1;
//this is a JLabel: it will display the text
JLabel lbl = new JLabel(new ImageIcon("title.png"));
//this JLabel will display whose turn it is
JLabel turnLbl = new JLabel("X's Turn");
ImageIcon red = new ImageIcon("red.png");
ImageIcon blue = new ImageIcon("blue.png");
ImageIcon blank = new ImageIcon("blank.png");
ImageIcon loseImg = new ImageIcon("lose.png");
ImageIcon winImg = new ImageIcon("win.png");
ImageIcon drawImg = new ImageIcon("draw.png");
JLabel lose = new JLabel(loseImg);
JLabel win = new JLabel(winImg);
JLabel draw = new JLabel(drawImg);
URL hitURL = null, cheerURL = null, booURL = null;
AudioClip hit = null, cheer = null, boo = null;
//the constructor
public TicTacToe()
{
super("TicTacToe: Boxing Style");
setSize(450,700);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//this will hold the buttons:
Container container = getContentPane();
//this will tell the computer how to display the buttons:
container.setLayout(null);
//we will add the winning, losing, and draw labels, butt
//move them off the screen.
container.add(lose);
lose.setBounds(-500,-500,331,438);
container.add(win);
lose.setBounds(-500,-500,331,438);
container.add(draw);
lose.setBounds(-500,-500,331,438);
//add the lbl:
container.add(lbl);
lbl.setBounds(20,0,400,288);
try
{
hitURL = this.getClass().getResource("hit.wav");
booURL = this.getClass().getResource("boo.wav");
cheerURL = this.getClass().getResource("cheer.wav");
hit = JApplet.newAudioClip(hitURL);
boo = JApplet.newAudioClip(booURL);
cheer = JApplet.newAudioClip(cheerURL);
}
catch(Exception e){}
//before we can add the buttons to the container, we must
//initialize them. Use a for loop to do it:
int newLine = 0;
int lineCount = 0;
for(int i = 0; i < spots.length; i++)
{
//initialize it with a blank image
spots[i] = new JButton(blank);
//this checks whether to use a new row
if(i==3 || i ==6)
{
newLine++;
lineCount = 0;
}
//set the position of the button
spots[i].setBounds(75+(lineCount*100),300+(newLine*100),100,100);
//add it to the container
container.add(spots[i]);
//and now add the action listener:
spots[i].addActionListener(this);
lineCount++;
}
//add the JLabel that describes the turn
container.add(turnLbl);
turnLbl.setBounds(200,630,100,30);
container.setComponentZOrder(lose,0);
container.setComponentZOrder(win,0);
container.setComponentZOrder(draw,0);
}
public void reset()
{
for(int i = 0; i < spots.length; i++)
{
spots[i].setIcon(blank);
spots[i].addActionListener(this);
}
turn = 1;
}
//the mandatory method:
public void actionPerformed(ActionEvent e)
{
hit.play();
try
{
Thread.sleep(600);
}
catch(Exception excep){}
//this will check the button pressed:
for(int i = 0; i < spots.length; i++)
{
if(e.getSource()==spots[i])
{
//set the button to X
spots[i].setIcon(red);
//now, change the JLabel that describes the player's turn
turnLbl.setText("X's (Red's) Turn");
//disable the btn so it can't be re-pressed
spots[i].removeActionListener(this);
}
}
turn++;
//before letting the other player go, check whether a player won:
checkWin();
//this method lets the computer select its turn
ai();
}
public void ai()
{
boolean movedYet;
//if this is the computer's first turn, then try to go in the top left
//if already taken, take the middle
if(turn == 2)
{
//if the top left is taken, take the middle
if(spots[0].getIcon().equals(red))
{
spots[4] .setIcon(blue);
spots[4].removeActionListener(this);
movedYet = true;
}
//else, take the top left
else
{
spots[0] .setIcon(blue);
spots[0].removeActionListener(this);
movedYet = true;
}
}
//if this is not the first turn, then check for 2 out of 3 spots
//taken. If there are none, go to a random location
else
{
//callin this method checks for two in a row of the first String passed in.
//It then takes the 3rd spot with the 2nd String passed in:
movedYet = twoInARow(blue);
//if the computer didn't take an offensive spot, take a defensive
//one.
if(!movedYet)
{
movedYet = twoInARow(red);
//if there is no defensive move, take the next open one.
if(!movedYet)
{
//this loop finds the first untaken spot:
for(int i = 0; i < spots.length; i++)
{
//if empty, take it!
if(spots[i].getIcon().equals(blank))
{
spots[i] .setIcon(blue);
spots[i].removeActionListener(this);
movedYet = true;
break;
}
}
}
}
}
turn++;
System.out.println(turn);
checkWin();
if(!movedYet)
{
//if no spot was taken, it must be a cat's game:
draw.setBounds(50,50,331,438);
reset();
}
}
public boolean twoInARow(Icon a)
{
for(int i = 0; i < 3; i++)
{
//this checks for 2 in a row from the top
if(spots[i].getIcon().equals(a) &&
spots[i+3].getIcon().equals(a) &&
spots[i+6].getIcon().equals(blank))
{
spots[i+6].setIcon(blue);
spots[i+6].removeActionListener(this);
return true;
}
//this checks (from the top and bottom)
//for a taken spot, then a gap, then a taken one:
if(spots[i].getIcon().equals(a) &&
spots[i+6].getIcon().equals(a) &&
spots[i+3].getIcon().equals(blank))
{
spots[i+3].setIcon(blue);
spots[i+3].removeActionListener(this);
return true;
}
//this checks for 2 in a row from the bottom
if(spots[i+6].getIcon().equals(a) &&
spots[i+3].getIcon().equals(a) &&
spots[i].getIcon().equals(blank))
{
spots[i] .setIcon(blue);
spots[i].removeActionListener(this);
return true;
}
//this checks for 2 in a row from the left
if(spots[i*3].getIcon().equals(a) &&
spots[(i*3)+1].getIcon().equals(a) &&
spots[(i*3)+2].getIcon().equals(blank))
{
spots[(i*3)+2] .setIcon(blue);
spots[(i*3)+2].removeActionListener(this);
return true;
}
//this checks (from the left and right)
//for a taken spot, then a gap, then a taken one
if(spots[i*3].getIcon().equals(a) &&
spots[(i*3)+2].getIcon().equals(a) &&
spots[(i*3)+1].getIcon().equals(blank))
{
spots[(i*3)+1] .setIcon(blue);
spots[(i*3)+1].removeActionListener(this);
return true;
}
//this checks for 2 in a row from the right
if(spots[(i*3)+2].getIcon().equals(a) &&
spots[(i*3)+1].getIcon().equals(a) &&
spots[i*3].getIcon().equals(blank))
{
spots[i*3] .setIcon(blue);
spots[i*3].removeActionListener(this);
return true;
}
//now we will check for a diagnol 2 in a row:
for(int j = 0; j <= 2; j+=2)
{
//this will check for diagnol X wins
if(spots[j].getIcon()==a &&
spots[4].getIcon()==a &&
spots[8-j].getIcon().equals(blank))
{
spots[8-j] .setIcon(blue);
spots[8-j].removeActionListener(this);
return true;
}
//this checks (from a diagnol)
//for a taken spot, then a gap, then a taken one
if(spots[j].getIcon()==a &&
spots[8-j].getIcon()==a &&
spots[4].getIcon().equals(blank))
{
spots[4] .setIcon(blue);
spots[4].removeActionListener(this);
return true;
}
if(spots[8-j].getIcon()==a &&
spots[4].getIcon()==a &&
spots[j].getIcon().equals(blank))
{
spots[j] .setIcon(blue);
spots[j].removeActionListener(this);
return true;
}
}
}
return false;
}
public void checkWin()
{
//first, we will use to go through three iterations. This allows us to
//check for both horizontal and vertical wins without using too
//much code:
for(int i = 0; i < 3; i++)
{
//this checks for a vertical X win
if(spots[i].getIcon().equals(red) &&
spots[i+3].getIcon().equals(red) &&
spots[i+6].getIcon().equals(red))
{
cheer.play();
try
{
Thread.sleep(600);
}
catch(Exception excep){}
win.setBounds(50,50,331,438);
reset();
return;
}
//this checks for a vertical O win
if(spots[i].getIcon().equals(blue) &&
spots[i+3].getIcon().equals(blue) &&
spots[i+6].getIcon().equals(blue))
{
boo.play();
try
{
Thread.sleep(600);
}
catch(Exception excep){}
lose.setBounds(50,50,331,438);;
reset();
return;
}
//this checks for a horizontal X win
if(spots[i*3].getIcon().equals(red) &&
spots[(i*3)+1].getIcon().equals(red) &&
spots[(i*3)+2].getIcon().equals(red))
{
cheer.play();
try
{
Thread.sleep(600);
}
catch(Exception excep){}
win.setBounds(50,50,331,438);
reset();
return;
}
//this checks for a horizontal O win
if(spots[i*3].getIcon().equals(blue) &&
spots[(i*3)+1].getIcon().equals(blue) &&
spots[(i*3)+2].getIcon().equals(blue))
{
boo.play();
try
{
Thread.sleep(600);
}
catch(Exception excep){}
lose.setBounds(50,50,331,438);;
reset();
return;
}
}
//now, this loop will check for diagnol wins
for(int i = 0; i <= 2; i+=2)
{
//this will check for diagnol X wins
if(spots[i].getIcon().equals(red) &&
spots[4].getIcon().equals(red) &&
spots[8-i].getIcon().equals(red))
{
cheer.play();
try
{
Thread.sleep(600);
}
catch(Exception excep){}
win.setBounds(50,50,331,438);
reset();
return;
}
//this will check for diagnol O wins
if(spots[i].getIcon().equals(blue) &&
spots[4].getIcon().equals(blue) &&
spots[8-i].getIcon().equals(blue))
{
boo.play();
try
{
Thread.sleep(600);
}
catch(Exception excep){}
lose.setBounds(50,50,331,438);;
reset();
return;
}
}
}
//starter (main) method:
public static void main(String[] args) {
TicTacToe ttt = new TicTacToe();
}
}
Thanks!