Search code examples
javamultidimensional-arraytic-tac-toe

Java TicTacToeGame, code keeps changing the Xs to Os and vise verse


I am building a Tic Tac Toe game in java. I have gotten the game to a stage where I can display the title, a reset button, the grid and draw the Xs and Os when the player clicks in the grid (the game currently has no game logic as I will add later). My problem at the moment, is that each time the player clicks on the grid, any X's will change to Os and the Os to Xs. I think the problem is within the paint() method of the TicTacToeGame.java, but I can't work it out as I am still learning. If someone could offer some advice, it would greatly be appreciated. Here is the code to the classes that makes up my game.

TicTacToeGame.java

import java.applet.Applet;
import java.awt.Button;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;

import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TicTacToeGame extends Applet {
    private final int START_X = 40;
    private final int START_Y = 100;
    private final int ROWS = 3;
    private final int COLS = 3;
    private final int BOX_WIDTH = 50;
    private final int BOX_HEIGHT = 50;
    private final Color BACKCOLOR = Color.black;
    private final Color BORDERCOLOR = Color.white;

    private final Label TITLE = new Label("Tic-Tac-Toe");

    private int player = 1;
    private final Font TITLEFONT = new Font("Arial", Font.BOLD, 16);   //used to format the title TicTacToe

    private TicTacToeBox boxes[][];    //used to create the game elements

    private Button resetButton;    //button for resetting the game

    /**
     * This method is used to initalize the game
     */
    public void init() {

        add(TITLE);   //adds the title

        TITLE.setFont(TITLEFONT);   //sets the titles fonts

        resetButton = new Button("New Game/Reset"); // creates a reset/newgame button

        resetButton.setLocation(20, 88);    //use to position the reset button but doesn't seem to work.

        add(resetButton); // adds the reset button

        resetButton.addActionListener(new ActionListener() { // creates an
                                                                // action
                                                                // listener for
                                                                // the botton

                    public void actionPerformed(ActionEvent e) { // this is the
                                                                    // action to
                                                                    // be
                                                                    // performed
                                                                    // when the
                                                                    // reset
                                                                    // button is
                                                                    // clicked

                        buildBoxes(); // method used to build the boxes

                        repaint(); // method used to redraw the grid

                    } // end actionPerformed()
                }); // end addActionListener()

        boxes = new TicTacToeBox[ROWS][COLS]; // Initializes a 2d array with 3 rows and 3 columns

        buildBoxes(); // builds the boxes

        resize(200, 300);   //resizes the applet

    }//end init()

    /**
     * This method is used to create the graphics
     */
    public void paint(Graphics g) {

        // loop through the boxes and draw them.
        for (int row = 0; row < boxes.length; row++) {

            for (int col = 0; col < boxes[row].length; col++) {

                boxes[row][col].draw(g);

                if (boxes[row][col].isClicked()) {

                    removeMouseListener(boxes[row][col]);    //removes the mouse listener so this boxes[row][col] can nolonger be clicked

                    if (player == 1) {

                        boxes[row][col].setPlayer("x");   //if player variable ==1 set the boxes[row][col].player variable to x

                        boxes[row][col].setPlayerSeclection(true);

                    } else {

                        boxes[row][col].setPlayer("y");   //if player variable is other, set the boxes[row][col].player variable to y

                        boxes[row][col].setPlayerSeclection(true);
                    } //end if/else

                    if(boxes[row][col].playerSeclection == true) { //used to draw the Xs and Os based on previous selections

                      if (boxes[row][col].player.equals("x")) {    //used to draw the Xs

                        boxes[row][col].drawCross(boxes[row][col].getX(),boxes[row][col].getY(),boxes[row][col].getHeight(),boxes[row][col].getWidth(), g);

                        player = 2;   //sets the variable player to 2

                    } else{   //used to draw the Ys

                        boxes[row][col].drawNought(boxes[row][col].getX(),boxes[row][col].getY(),boxes[row][col].getHeight(),boxes[row][col].getWidth(), g);

                        player = 1;   //sets the variable player to 1
                    }//end if/else

                    } //end if

                }//end if(isClicked)

            }//end loop

        }//end loop

    }//end paint

    private void removeMouseListeners() {

        for (int row = 0; row < boxes.length; row++) {

            for (int col = 0; col < boxes[row].length; col++) {

                removeMouseListener(boxes[row][col]);

            }//end loop

        }//end loop

    }//end removeMouseListeners()

    /**
     * This method is used to build the boxes for the game
     */
    private void buildBoxes() {

        removeMouseListeners(); //removeMouseListeners()

        for (int row = 0; row < boxes.length; row++) {

            for (int col = 0; col < boxes[row].length; col++) {

                boxes[row][col] = new TicTacToeBox(START_X + col * BOX_WIDTH,START_Y + row * BOX_HEIGHT, BOX_WIDTH, BOX_HEIGHT,
                        BACKCOLOR, BORDERCOLOR, this);

                addMouseListener(boxes[row][col]);

            }//end loop

        }//end loop

    }// end of buildBoxes()

}//end class

TicTacToeBox.java

import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;

public class TicTacToeBox extends ClickableBox {

  String player;    //used to store the player who click the box

    boolean playerSeclection = false;    //determines is a box has been clicked or not

    /**
     * This is the constructor for building the Tictactoe board
     * 
     * @param x
     *            This is the starting position for the box along the x axis
     * @param y
     *            This is the starting position for the box along the y axis
     * @param width
     *            This is the width of the box
     * @param height
     *            This is the height of the box
     * @param parent
     *            This is the container for additional elements
     */

    public TicTacToeBox(int x, int y, int width, int height, Color backColor, Color borderColor, Container parent) {
        super(x, y, width, height, backColor, borderColor, parent);

    }//end TicTacToeBox()


    /**
     * This method is used to get the value of getPlayer. Either x or o
     * @return
     */
    public String getPlayer() {
        return player;
    }//ends getPlayer


/**
 * This method is used to set the variable setPlayer to either x or 0
 * @param player
 */
    public void setPlayer(String player) {
        this.player = player;
    }

    /**
     * This method is used to draw the cross
     * @param x  starting x position of the box
     * @param y  starting y position of the box
     * @param height  height of the box
     * @param width  width of the box
     * @param g  graphic object for drawing
     */
    public void drawCross(int x, int y, int height, int width, Graphics g){
        g.setColor(Color.red);  //sets the crosses color
        g.drawLine(x, y, x + width, y + height);  //draws the first line
        g.drawLine(x, y + height, x + width, y);  //draws the second line

    }//end drawX()

    /**
     * This method is used to draw the nought
     * @param x  starting position of the box
     * @param y  starting y position of the box
     * @param height  height of the box
     * @param width  width of the box
     * @param g  Graphics object
     */
    public void drawNought(int x, int y, int height, int width, Graphics g){
        g.setColor(Color.blue);  //sets the oval color
        g.drawOval(x, y, width-2, height-2);  //draws the oval
    }

    /**
     * This method is used to get the Player selection
     * @return
     */
    public boolean getPlayerSeclection() {
    return playerSeclection;
  }

/**
 * This method is used to set wether or not the player has selected a box
 * @param playerSeclection
 */
  public void setPlayerSeclection(boolean playerSeclection) {
    this.playerSeclection = playerSeclection;
  }

}

ClickableBox.java

import java.awt.event.MouseAdapter;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.Container;

public class ClickableBox extends MouseAdapter {

  private int x, y, width, height; // storage for the position, width and height
                                   // of a clickable box
  private Color borderColor, backColor, oldColor; // storage for the border
                                                  // color, the background color
                                                  // and the old/previous color
                                                  // of the clickable box
  private boolean drawBorder, clicked; // true/false storage for the variable
                                       // drawBorder and clicked
  private Container parent; // storage for container object variable

  /**
   * Constructor method
   * 
   * @param x
   *          This is the top left position of the mask for the x axes
   * @param y
   *          This is the top left position of the mask for the y axes
   * @param width
   *          This is how wide the mask will be
   * @param height
   *          This is how high the mask will be
   * @param borderColor
   *          This is the border color of the mask
   * @param backColor
   *          This is the background color of the mask
   * @param drawBorder
   *          This is boolean as to weather the border will be drawn?
   * @param parent
   *          This is a parent container??
   */
  public ClickableBox(int x, int y, int width, int height, Color borderColor, Color backColor, boolean drawBorder,
      Container parent) {

    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.backColor = backColor;
    this.borderColor = borderColor;
    this.drawBorder = drawBorder;
    this.parent = parent;

  }// end CLickableBox() constructor

  public ClickableBox(int x, int y, int width, int height, Color borderColor, Color backColor, 
          Container parent) {

        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.backColor = backColor;
        this.borderColor = borderColor;
        this.parent = parent;

      }// end CLickableBox() constructor

  /**
   * Method to get the variable x
   * 
   * @return the variable x
   */
  public int getX() {
    return x;
  }// end getX()

  /**
   * Method used to set the variable x
   * 
   * @param x
   *          This is the value which x will be set to
   */
  public void setX(int x) {
    this.x = x;
  }// end setX()

  /**
   * Method to get the y variable
   * 
   * @return returns the variable y
   */
  public int getY() {
    return y;
  }// end getY()

  /**
   * Method used to set the variable y
   * 
   * @param y
   *          This is the value which y will be set to
   */
  public void setY(int y) {
    this.y = y;
  }// end setY()

  /**
   * Method getWidth is used to get the width from the variable width
   * 
   * @return returns the variable width
   */
  public int getWidth() {
    return width;
  }// end getWidth()

  /**
   * Method setWidth is used to set the width of the clickable box
   * 
   * @param width
   *          This is the value which the width will be set at
   */
  public void setWidth(int width) {
    this.width = width;
  }// end setWidth()

  /**
   * Method getHeight() is used to get the value of the variable height
   * 
   * @return Returns the value of height
   */
  public int getHeight() {
    return height;
  }// end getHeight()

  /**
   * Method setHeight() is used to set the height value
   * 
   * @param height
   *          This is the height of the clickable box
   */
  public void setHeight(int height) {
    this.height = height;
  }// end setHeight()

  /**
   * Method getBorderColor() is used to get the color of the border
   * 
   * @return Returns the color of the border
   */
  public Color getBorderColor() {
    return borderColor;
  }// end getBorderColor()

  /**
   * Method setBorderColor() is used to set the border's color
   * 
   * @param borderColor
   *          This is the color value which will be used as the border's color
   */
  public void setBorderColor(Color borderColor) {
    this.borderColor = borderColor;
  }// end getBorderColor()

  /**
   * Method getBackColor() is used to return the background color of the
   * clickable box
   * 
   * @return Returns the background color
   */
  public Color getBackColor() {
    return backColor;
  }// end getBackColor()

  /**
   * Method setBackColor() is used to set the background color
   * 
   * @param backColor
   *          This is the color value which will be used as the background color
   */
  public void setBackColor(Color backColor) {
    this.backColor = backColor;
  }// end setBackColor()

  /**
   * Method getOldColor() is used to return the previous color
   * 
   * @return Returns the previous color
   */
  public Color getOldColor() {
    return oldColor;
  }// end getOldColor()

  public void setOldColor(Color oldColor) {
    this.oldColor = oldColor;
  }

  public boolean isDrawBorder() {
    return drawBorder;
  }

  public void setDrawBorder(boolean drawBorder) {
    this.drawBorder = drawBorder;
  }

  /**
   * Method draw() is used to draw the clickable box
   * 
   * @param g
   *          Graphics variable
   */
  public void draw(Graphics g) {
    g.setColor(backColor);
    g.fillRect(x, y, width, height);
      g.setColor(borderColor);
      g.drawRect(x, y, width, height);

  }

  public void mouseReleased(MouseEvent e) {
    if (x < e.getX() && e.getX() < x + width && y < e.getY() && e.getY() < y + height) {
      clicked = true;
      parent.repaint();
    }
  }

  public boolean isClicked() {
    return clicked;
  }

  public void setClicked(boolean clicked) {
    this.clicked = clicked;
  }

}

Solution

  • I think the problem is that clicked is never set back to false. You probably want to call setClicked(false) after you have used the information to change the state. Otherwise, all the boxes stay in the clicked state and get toggled all the time...