0

I'm currently trying to make a TicTacToe game in Java; however I've hit a roadblock I can't quite figure out. I have a function so that when the user clicks within the top left corner, it should draw and X or an O, depending on the turn - at the moment I only have it so that it should draw an O. I'm going to implement the rest once I figure the initial part out. However, when I click to draw the oval, I get an error I don't understand. My code is below, and the error will be below that.

P.S. I'm only a senior in high school, so I think I know what I'm doing, but I probably have no idea.

Main class:

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


public class ticTacToeMain{

    public static void main(String[]args){
            ticTacToeBoard theBoard = new ticTacToeBoard();
            theBoard.setBackground(Color.white);
            JFrame frame = new JFrame();
            frame.add(theBoard);
            frame.setTitle("Tic Tac Toe");  
            frame.setSize(600,600);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);     
    }
}

Board class:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ticTacToeBoard extends JPanel{
    int turn=1;
    protected Graphics g2,g3;
    private static int x,y;

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.setColor(Color.black);
        g.drawLine(200, 0, 200, 600);
        g.drawLine(400, 0, 400, 600);
        g.drawLine(0,200, 600, 200);
        g.drawLine(0, 400, 600, 400);
        addMouseListener(new mouseListener());
    }
    public void drawX(int x1,int y1,int x2,int y2){
        g2.setColor(Color.red);
        g2.drawLine(x1, y1, x2, y2);

    }
    public void drawO(int x1, int y1, int width, int height){
        g3.setColor(Color.blue);
        g3.drawOval(x1,y1, width, height);
    }
    private class mouseListener extends MouseAdapter{
        public void mouseClicked(MouseEvent e){
            x = e.getX();
            y = e.getY();
            topLeftClicked();
        }
    }
    public void topLeftClicked(){
        if (x<200 && y<200 && turn == 0){
            drawX(25,25,175,175);
        }else if (x<200 && y<200 && turn == 1){
            drawO(25,25,150,150);
        }

    }

}

Here's the error:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at ticTacToeBoard.drawO(ticTacToeBoard.java:34)
    at ticTacToeBoard.topLeftClicked(ticTacToeBoard.java:48)
    at ticTacToeBoard$mouseListener.mouseClicked(ticTacToeBoard.java:41)
    at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:269)
    at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:269)
    at java.awt.Component.processMouseEvent(Component.java:6528)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
    at java.awt.Component.processEvent(Component.java:6290)
    at java.awt.Container.processEvent(Container.java:2234)
    at java.awt.Component.dispatchEventImpl(Component.java:4881)
    at java.awt.Container.dispatchEventImpl(Container.java:2292)
    at java.awt.Component.dispatchEvent(Component.java:4703)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4898)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4542)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4462)
    at java.awt.Container.dispatchEventImpl(Container.java:2278)
    at java.awt.Window.dispatchEventImpl(Window.java:2750)
    at java.awt.Component.dispatchEvent(Component.java:4703)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.awt.EventQueue$4.run(EventQueue.java:731)
    at java.awt.EventQueue$4.run(EventQueue.java:729)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Mandias09
  • 11
  • 2
  • Your instance variable `g3` is never initialized, so it is `null`. Btw, the same is true for `g2`. – Seelenvirtuose Feb 13 '16 at 15:20
  • @Seelenvirtuose so to initialize it, do I create another paint component, but this time involving g2? And then another involving g3? – Mandias09 Feb 13 '16 at 15:22
  • You have to do some tutorials for understanding how [Swing painting](https://docs.oracle.com/javase/tutorial/uiswing/painting/) works. In short: The whole painting is done in the overridden method `paintComponent`. You cannot call other paint methods as you do. The strategy is to store some information about what to paint (here the coordinates of X's and O's), then do the painting at whole in the `paintComponent` method. – Seelenvirtuose Feb 13 '16 at 15:27
  • @Seelenvirtuose Ah okay, thank you very much – Mandias09 Feb 13 '16 at 15:30

1 Answers1

0

PaintComponent method is called by swing framework when painting is needed, you should not add a mouse listener in that method or you will add a new one again and again each time component is repaint....

Concerning your error, it comes from g3 instance variable that is never initialised (so it is null and raise a npe). You may just set flag indcating if you are drawing o or x in topLeftClicked method and call repaint()... then use flag value in paintComponent to draw right symbol..... this will prevent you from storing unecessary Graphics instance variable...

P.A. Cros
  • 501
  • 3
  • 6