Hey guys~! I am working on a code and I am having some difficulties with it -- Basically I have a 3x3 grid of JButtons that represent the squares on a TicTacToe grid. The code seems to run fine but then after it determines a victor it crashes and says something about AWT Event Dispatch and a class casting error. Does anyone know how to get rid of this? Here is my code so far:

import javax.swing.JButton;
/**
 * This class was designed to give me extra capabilities for my buttons that the
 * JButton does not seem to offer.  I used the variable "tempText" to try to assign a
 * string to this Tile that can be evaluated in my code because setText() creates a
 * thread to update the button and it might not have finished by the time my own code
 * gets to the evaluation part.
 */
public class Tile extends JButton
{
    private int row;
    private int col;
    private String tempText;
    private static int counter = 0; //for testing
    
    public Tile(int row, int col)
    {
        super("  ");
        tempText = "  ";
        this.row = row;
        this.col = col;
        setSize(10,10);
    }
    
    public void clear()
    {
        tempText = "  ";
        setText("  ");
    }
    
    public boolean isEmpty()
    {
        return (tempText.equals("  "));
    }
    
    public void setTempText(String s)
    {
        tempText = s;
    }
    
    public void setText(String s)
    {
        setTempText(s);
        super.setText(s);
    }
    
    public String getTempText()
    {
        return tempText;
    }
    
    public boolean isFilled()
    {
        return !isEmpty();
    }
    
    public int getRow()
    {
        return row;
    }
    
    public int getCol()
    {
        return col;
    }
    
    /**
     * Precondition: other is an instance of Tile
     */
    public boolean equals(Object other)
    {
        Tile temp = (Tile)other;
        return tempText.equals(temp.tempText);
    }
}
package games;

/**
 * This class is designed to create a 2D grid for any object type.
 * It is mainly designed for gaming purposes.  It works correctly.
 */
public class Grid<T>
{
    private Object[][] grid;
    
    /**
     * Creates a new grid based on a given number of rows and columns
     * @param rows Number of rows in the grid
     * @param cols Number of columns in the grid
     */
    public Grid(int rows, int cols)
    {
        grid = new Object[rows][cols];
    }
    
    /**
     * Sets an element in the grid based on the inputted coordinate and item provided
     * @param row The row index
     * @param col The column index
     * @param item The element to place
     */
    public void set(int row, int col, T item)
    {
        grid[row][col] = item;
    }
    
    /**
     * Retrieves the element stored at the inputted coordinate
     * @param row The row index
     * @param col The column index
     * @return The element at the specified location
     */
    public T get(int row, int col)
    {
        return (T)grid[row][col];
    }
    
    /**
     * Prints the grid in a crude format
     */
    public void print()
    {
        for (int r=0;r<grid.length;r++)
        {
            for (int c=0;c<grid[0].length;c++)
            {
                System.out.print(get(r,c)+"\t");
            }
            System.out.println();
        }
    }
    
    /**
     * Empties the grid
     */
    public void empty()
    {
        for (int r=0;r<grid.length;r++)
        {
            for (int c=0;c<grid[0].length;c++)
            {
                set(r,c,null);
            }
            System.out.println();
        }
    }
    
    /**
     * Generates an ArrayList of objects in the grid
     * @return List of objects in grid
     */
    public java.util.ArrayList<T> list()
    {
        java.util.ArrayList<T> temp = new java.util.ArrayList<T>();
        for (int r=0;r<grid.length;r++)
        {
            for (int c=0;c<grid[0].length;c++)
            {
                temp.add(get(r,c));
            }
        }
        return temp;
    }
}
import java.util.*;
/**
 * Board extending the Grid class specifically for Tic-Tac-Toe
 */
public class Board extends games.Grid<Tile>
{
    /**
     * Constructs a new board from a certain number of rows and columns
     * @param rows Number of rows
     * @param cols Number of columns
     */
    public Board(int rows, int cols)
    {
        super(rows,cols);
        for (int i=0;i<rows;i++)
        {
            for (int j=0;j<cols;j++)
            {
                set(i,j,new Tile(i,j));
            }
        }
    }
    
    /**
     * Scans for a row with a certain number of a certain tile present.
     * If the number is 2, it will return a Tile where the empty space is.
     * If the number is not 2, it will return a Tile of that type that is not on the board.
     * @param symbol String representation of the symbol for the Tile
     * @param num Number of tiles that should be in the set
     * @return Tile to be returned.
     */
    public Tile numPresent(String symbol, int num)
    {
        ArrayList<Tile> symbolList = new ArrayList<Tile>();
        symbolList.add(new Tile(-1,-1));
        symbolList.get(0).setText(symbol);
        
        Tile[] temp = new Tile[3];
        ArrayList<Tile> tempList;
        
        temp[0] = get(0,0);
        temp[1] = get(0,1);
        temp[2] = get(0,2);
        tempList = new ArrayList<Tile>(Arrays.asList(temp));
        tempList.retainAll(symbolList);
        if (tempList.size()==num)
        {
            if (num==2)
            {
                if (tempList.get(0).isEmpty())
                    return tempList.get(0);
            }
            else
                return symbolList.get(0);
        }
        
        temp[0] = get(1,0);
        temp[1] = get(1,1);
        temp[2] = get(1,2);
        tempList = new ArrayList<Tile>(Arrays.asList(temp));
        tempList.retainAll(symbolList);
        if (tempList.size()==num)
        {
            if (num==2)
            {
                if (tempList.get(0).isEmpty())
                    return tempList.get(0);
            }
            else
                return symbolList.get(0);
        }
        
        temp[0] = get(2,0);
        temp[1] = get(2,1);
        temp[2] = get(2,2);
        tempList = new ArrayList<Tile>(Arrays.asList(temp));
        tempList.retainAll(symbolList);
        if (tempList.size()==num)
        {
            if (num==2)
            {
                if (tempList.get(0).isEmpty())
                    return tempList.get(0);
            }
            else
                return symbolList.get(0);
        }
        
        temp[0] = get(0,0);
        temp[1] = get(1,0);
        temp[2] = get(2,0);
        tempList = new ArrayList<Tile>(Arrays.asList(temp));
        tempList.retainAll(symbolList);
        if (tempList.size()==num)
        {
            if (num==2)
            {
                if (tempList.get(0).isEmpty())
                    return tempList.get(0);
            }
            else
                return symbolList.get(0);
        }
        
        temp[0] = get(0,1);
        temp[1] = get(1,1);
        temp[2] = get(2,1);
        tempList = new ArrayList<Tile>(Arrays.asList(temp));
        tempList.retainAll(symbolList);
        if (tempList.size()==num)
        {
            if (num==2)
            {
                if (tempList.get(0).isEmpty())
                    return tempList.get(0);
            }
            else
                return symbolList.get(0);
        }
        
        temp[0] = get(0,2);
        temp[1] = get(1,2);
        temp[2] = get(2,2);
        tempList = new ArrayList<Tile>(Arrays.asList(temp));
        tempList.retainAll(symbolList);
        if (tempList.size()==num)
        {
            if (num==2)
            {
                if (tempList.get(0).isEmpty())
                    return tempList.get(0);
            }
            else
                return symbolList.get(0);
        }
        
        temp[0] = get(0,0);
        temp[1] = get(1,1);
        temp[2] = get(2,2);
        tempList = new ArrayList<Tile>(Arrays.asList(temp));
        tempList.retainAll(symbolList);
        if (tempList.size()==num)
        {
            if (num==2)
            {
                if (tempList.get(0).isEmpty())
                    return tempList.get(0);
            }
            else
                return symbolList.get(0);
        }
        
        temp[0] = get(2,0);
        temp[1] = get(1,1);
        temp[2] = get(0,2);
        tempList = new ArrayList<Tile>(Arrays.asList(temp));
        tempList.retainAll(symbolList);
        if (tempList.size()==num)
        {
            if (num==2)
            {
                if (tempList.get(0).isEmpty())
                    return tempList.get(0);
            }
            else
                return symbolList.get(0);
        }
        return null;
    }
    
    /**
     * Checks who the winner is.
     * @return The symbol of the winner, null if there is no winner.
     */
    public String winner()
    {
        Tile tile = numPresent("O",3);
        if (tile != null)
            return "O";
        tile = numPresent("X",3);
        if (tile != null)
            return "X";
        for (Tile t : list())
        {
            if (t.isEmpty())
                return null;
        }
        return "D";
    }
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Driver implements ActionListener
{
    private Board board;
    private String compSymbol;
    private String userSymbol;
    private boolean userFirst;
    
    private JFrame frame;
    private JPanel panel;
    
    public Driver()
    {
        frame = new JFrame("Tic Tac Toe");
        panel = new JPanel();
        frame.setSize(150,150);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        
        board = new Board(3,3);
        for (Tile t : board.list())
        {
            panel.add(t);
            t.addActionListener(this);
        }
        
        frame.add(panel);
        
        if ((int)(Math.random()*2)==0)
        {
            userFirst = false;
            compSymbol = "X";
            userSymbol = "O";
        }
        else
        {
            userFirst = true;
            compSymbol = "O";
            userSymbol = "X";
        }
    }
    
    public static void main (String[] args)
    {
        Driver d = new Driver();
        d.frame.setVisible(true);
        d.frame.requestFocus();
        if (!d.userFirst)
            d.computerTurn();
    }
      
    public void actionPerformed(ActionEvent e)
    {
        Tile temp = null;
        for (Tile t : board.list())
            if (e.getSource() == t)
                temp = t;
        temp.setTempText(userSymbol);
        scanWinner();
        Tile temp2 = computerTurn();
        scanWinner();
        temp.setText(userSymbol);
        if (temp2!=null)
            temp2.setText(compSymbol);
    }
    
    private void scanWinner()
    {
        String winner = board.winner();
        if (winner == null)
            return;
        else if (winner.equals("D"))
            JOptionPane.showMessageDialog(null,"Draw.");
        else if (winner.equals(userSymbol))
            JOptionPane.showMessageDialog(null,"You Are Victorious!");
        else
            JOptionPane.showMessageDialog(null,"You have been defeated...");
        System.exit(0);
    }
    
    private Tile computerTurn()
    {
        //Scan Dangers and place accordingly
        Tile danger = board.numPresent(userSymbol,2);
        if (danger!=null)
        {
            danger.setTempText(compSymbol);
            return danger;
        }

        /*Unfinished code for the computer's turn here...*/

        return null;
    }
}

I know this is a lot of code, but I really don't know where I'm going wrong -- I am getting an error that I have never seen before so I don't really understand it. Also, the error doesn't appear when it occurs for some reason -- it seems to be waiting for me to finish the code before displaying.

Recommended Answers

All 6 Replies

Hi
The rise in the egale function in the Title class:

public boolean equals(Object other)
    {
        
        [B]Tile temp = (Tile)other;[/B]
        return tempText.equals(temp.getText());
    }

You could not cast the button to Title Object:
May be you should do this:

public boolean equals(Object other)
    {
        
        JButton temp=(JButton)other;
        return tempText.equals(temp.getText());
    }

This will execute without error.

but the semantics of the egale methode misleads.
Hope it helps.

I actually tried that, but I don't really understand why there is a non-Tile JButton being created because I didn't make any in my code. Also, the main issue I am coming across is that the Tile's string is not being updated upon click -- for instance, the following is a possible sequence:
1. I click somewhere.
2. The computer moves (assume randomly)
3. I click somewhere else.
4. Since the click has not yet changed the text on the button, the computer still moves randomly instead of trying to deflect my move because it sees no threat since the board has not yet been updated
5. The board is updated
6. I click in the final spot and win.
***How to I solve this? It has to do with the threading order -- i want the setText() method to be finished BEFORE my code continues running.

And what is an egale method?

please can you explain the six steps more; I'm not sure that I understand.

And what is an egale method?

I mean the eguals method.

Ok this is what I am basically trying to do:

I want a GUI to show up with 9 buttons. I randomize who goes first. If the computer goes first the computer starts off with his move. Then I wait for a button click on the spot the user wants to choose. When the user chooses his spot, the spot should be recorded, and then the game will scan to see if there is a 3-in-a-row, resulting in a winner, or if all the squares have been filled, in which case it would be a tie. If there is no winner yet, the computer moves. Then again there is a scan for the winner. If there is no winner yet, we wait for the user to go again, and the cycle repeats every time the user chooses a spot. The problem I am having is that when I am trying to have the computer decide where to go, it needs to know where the user went. But because the text of the Tile the user selected has not yet been changed (I think b/c the setText() thread is behind the main application one), the computer acts without knowledge of the move the user just made. I need to make sure that the board is updated after the user goes before the computer makes his move. How do I do this?

I solved it with an empty loop :P

That sounds like a 'hack' solution rather than a true fix. Assuming that your computer's decision of where to go is fast, you should just run all of your code on the Swing Event Dispatch Thread. For example, see how they call createAndShowGUI() in this example (pay attention to the code in main and in the createAndShowGUI method, the rest is unimportant). You can't run into the problem you described if the code is all running in one thread, and in this case, doing so shouldn't cause your application to freeze since you have very little time sensitive code.

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.