javaswingjbuttontic-tac-toe

Hello I am creating a TicTacToe game for myself to understand Java better


however I am not sure where I am supposed to enter the whoWins() method. Do I enter this method in the actionperformed Method of the buttons or do i need to something different. Please help.

public class TTT extends JFrame implements ActionListener {

        private JButton buttons[] = new JButton[9];
        private JButton exitButton;
        public JLabel title;
        public JPanel titlePanel, panel;
        private int count = 0;
        int symbolCount = 0;
        private boolean win = false;

        public TTT() {

            title = new JLabel("Welcome to my Tic Tac Toe Game!");
            titlePanel = new JPanel();
            title.setFont(new Font(Font.SERIF, 0, 30));
            titlePanel.add(title);
            this.add(titlePanel, BorderLayout.NORTH);

            panel = new JPanel(new GridLayout(3, 3));
            for (int i = 0; i < buttons.length; i++) {
                buttons[i] = new JButton();
                panel.add(buttons[i]);
                buttons[i].setEnabled(true);
                buttons[i].addActionListener(this);
            }
            this.add(panel, BorderLayout.CENTER);

            JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.CENTER));
            exitButton = new JButton("Quit");
            panel1.add(exitButton);
            this.add(panel1, BorderLayout.SOUTH);
            exitButton.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    System.exit(WIDTH);
                }
            });

        }

        public void whoWins() {
            //Determines who wins using for the horizontal rows.
            if (buttons[0].getText() == buttons[1].getText() && buttons[1].getText() == buttons[2].getText() && buttons[0].getText() != "") {
                win = true;
            } else if (buttons[3].getText() == buttons[4].getText() && buttons[4].getText() == buttons[5].getText() && buttons[3].getText() != "") {
                win = true;
            } else if (buttons[6].getText() == buttons[7].getText() && buttons[7].getText() == buttons[8].getText() && buttons[6].getText() != "") {
                win = true;
            } //Determines the verticles wins
            else if (buttons[0].getText() == buttons[3].getText() && buttons[3].getText() == buttons[6].getText() && buttons[0].getText() != "") {
                win = true;
            } else if (buttons[1].getText() == buttons[4].getText() && buttons[4].getText() == buttons[7].getText() && buttons[1].getText() != "") {
                win = true;
            } else if (buttons[2].getText() == buttons[5].getText() && buttons[5].getText() == buttons[8].getText() && buttons[2].getText() != "") {
                win = true;
            }
            // Diagnol Wins 
            else if (buttons[0].getText()==buttons[4].getText()&&buttons[4].getText()==buttons[8].getText()&& buttons[0].getText()!= "") {
                win = true;
            }else if (buttons[2].getText()==buttons[4].getText()&&buttons[4].getText()==buttons[6].getText()&& buttons[1].getText()!= "") {
                win = true;
            }else {
                win = false;
            }

            //who won
            if (win = true) {
                JOptionPane.showMessageDialog(null, "wins");
            }else if (count == 9 && win == false) {
                JOptionPane.showMessageDialog(null, "Tie game");
            }
        }

        public static void main(String[] args) {
            TTT ref1 = new TTT();
            ref1.setTitle("Tic Tac Toe");
            ref1.setVisible(true);
            ref1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            ref1.setSize(500, 500);
            ref1.setLocationRelativeTo(null);
    //        ref1.whoWins();

        }

        @Override
        public void actionPerformed(ActionEvent e) {
            count++;
            for (JButton button : buttons) {
                if (button == e.getSource()) {
                    if (symbolCount % 2 == 0) {
                        button.setText("X");
                        button.setEnabled(false);
                    } else {
                        button.setText("O");
                        button.setEnabled(false);
                    }
                }            
            }        
            if (count >= buttons.length) {
                JOptionPane.showMessageDialog(null, "End");
            }
            symbolCount++;
        }

    }

Solution

  • If you really want to do this right, then I suggest making some big changes, some M-V-C type changes:


    For example,...

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.GridLayout;
    import java.awt.Window;
    import java.awt.event.*;
    import java.awt.image.BufferedImage;
    import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;
    import java.io.IOException;
    import java.util.EnumMap;
    import java.util.Map;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    import javax.swing.event.SwingPropertyChangeSupport;
    
    public class TicTacToeMain {
    
       private static void createAndShowGui() {
          TttView view = null;
          try {
             view = new TttView();
          } catch (IOException e) {
             e.printStackTrace();
             System.exit(-1);
          }
          TttModel model = new TttModel();
          new TttControl(model, view);
    
          JFrame frame = new JFrame("Tic Tac Toe");
          frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
          frame.getContentPane().add(view.getMainPanel());
          frame.pack();
          frame.setLocationByPlatform(true);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }
    
    enum TttPiece {
       EMPTY, X, O
    }
    
    class TttView {
      // public static final String IMAGE = "/imgFolder/TicTacToe.png";
      public static final String PATH_TO_IMG_URL = "https://i.sstatic.net/mwfLB.png";
      private static final int GAP = 5;
      private JPanel mainPanel = new JPanel();
      private JPanel tttPanel = new JPanel();
      private Map<TttPiece, Icon> iconMap = new EnumMap<>(TttPiece.class);
      private JLabel[][] grid = new JLabel[TttModel.ROWS][TttModel.COLS];
      private TttControl control;
    
      public TttView() throws IOException {
          // BufferedImage img = ImageIO.read(getClass().getResourceAsStream(IMAGE));
          URL imgUrl = new URL(PATH_TO_IMG_URL);
          BufferedImage img = ImageIO.read(imgUrl);
          Icon[] imgIcons = splitImg(img);
          iconMap.put(TttPiece.X, imgIcons[0]);
          iconMap.put(TttPiece.O, imgIcons[1]);
          iconMap.put(TttPiece.EMPTY, createEmptyIcon(imgIcons[0]));
    
          tttPanel.setLayout(new GridLayout(grid.length, grid[0].length, GAP, GAP));
          tttPanel.setBackground(Color.black);
          MyMouseAdapter mouseAdapter = new MyMouseAdapter();
          for (int row = 0; row < grid.length; row++) {
             for (int col = 0; col < grid[row].length; col++) {
                grid[row][col] = new JLabel(iconMap.get(TttPiece.EMPTY));
                grid[row][col].setOpaque(true);
                grid[row][col].setBackground(Color.LIGHT_GRAY);
                grid[row][col].addMouseListener(mouseAdapter);
                tttPanel.add(grid[row][col]);
             }
          }
    
          JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 0));
          btnPanel.add(new JButton(new ClearAction("Clear", KeyEvent.VK_C)));
          btnPanel.add(new JButton(new ExitAction("Exit", KeyEvent.VK_X)));
    
          int blGap = 2;
          mainPanel.setLayout(new BorderLayout(blGap, blGap));
          mainPanel.setBorder(BorderFactory.createEmptyBorder(blGap, blGap, blGap,
                blGap));
          mainPanel.add(tttPanel, BorderLayout.CENTER);
          mainPanel.add(btnPanel, BorderLayout.SOUTH);
       }
    
       public void setControl(TttControl control) {
          this.control = control;
       }
    
       public JComponent getMainPanel() {
          return mainPanel;
       }
    
       private Icon createEmptyIcon(Icon icon) {
          int width = icon.getIconWidth();
          int height = icon.getIconHeight();
          BufferedImage img = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_ARGB);
          return new ImageIcon(img);
       }
    
       private Icon[] splitImg(BufferedImage img) {
          int w = img.getWidth();
          int h = img.getHeight();
          int gap = 5;
          Icon[] icons = new ImageIcon[2];
          icons[0] = new ImageIcon(img.getSubimage(0, 0, w / 2 - gap, h / 2 - gap));
          icons[1] = new ImageIcon(img.getSubimage(w / 2 + gap, 0, w / 2 - gap, h
                / 2 - gap));
          return icons;
       }
    
       private class MyMouseAdapter extends MouseAdapter {
    
          @Override
          public void mousePressed(MouseEvent e) {
             if (control == null) {
                return;
             }
             for (int row = 0; row < grid.length; row++) {
                for (int col = 0; col < grid[row].length; col++) {
                   if (grid[row][col] == e.getSource()) {
                      control.gridPress(row, col);
                   }
                }
             }
          }
       }
    
       private class ClearAction extends AbstractAction {
    
          public ClearAction(String name, int mnemonic) {
             super(name);
             putValue(MNEMONIC_KEY, mnemonic);
          }
    
          @Override
          public void actionPerformed(ActionEvent evt) {
             if (control != null) {
                control.clear();
             }
          }
    
       }
    
       private class ExitAction extends AbstractAction {
          public ExitAction(String name, int mnemonic) {
             super(name);
             putValue(MNEMONIC_KEY, mnemonic);
          }
    
          @Override
          public void actionPerformed(ActionEvent evt) {
             if (control != null) {
                control.exit(evt);
             }
          }
       }
    
       public void setGridIcon(int row, int col, TttPiece tttPiece) {
          grid[row][col].setIcon(iconMap.get(tttPiece));
       }
    
    }
    
    class TttControl {
       private TttModel model;
       private TttView view;
    
       public TttControl(TttModel model, TttView view) {
          this.model = model;
          this.view = view;
          view.setControl(this);
    
          model.addPropertyChangeListener(new ModelListener());
       }
    
       public void exit(ActionEvent evt) {
          Window win = SwingUtilities
                .getWindowAncestor((Component) evt.getSource());
          win.dispose();
       }
    
       public void gridPress(int row, int col) {
          try {
             model.gridPress(row, col);
          } catch (TttException e) {
             // TODO: notify user
             // e.printStackTrace();
          }
       }
    
       public void clear() {
          model.clear();
       }
    
       private class ModelListener implements PropertyChangeListener {
          @Override
          public void propertyChange(PropertyChangeEvent evt) {
             if (TttModel.GRID_POSITION.equals(evt.getPropertyName())) {
                TttPiece[][] tttGrid = model.getTttGrid();
                for (int row = 0; row < tttGrid.length; row++) {
                   for (int col = 0; col < tttGrid[row].length; col++) {
                      view.setGridIcon(row, col, tttGrid[row][col]);
                   }
                }
             }
          }
       }
    
    }
    
    class TttModel {
       public static final int ROWS = 3;
       public static final int COLS = ROWS;
       public static final String GRID_POSITION = "grid position";
    
       private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(
             this);
       private TttPiece[][] tttGrid = new TttPiece[ROWS][COLS];
       private TttPiece player = TttPiece.X;
       private boolean gameOver;
    
       public TttModel() {
          clear();
       }
    
       public void setGridPosition(int row, int col, TttPiece piece)
             throws TttException {
          if (gameOver) {
             return;
          }
          if (tttGrid[row][col] == TttPiece.EMPTY) {
             tttGrid[row][col] = piece;
             checkForWin(row, col, piece);
             nextPlayer();
             pcSupport.firePropertyChange(GRID_POSITION, null, tttGrid);
          } else {
             String message = "Invalid setGridPosition for row: %d, col: %d, piece: %s. "
                   + "Spot already occupied by piece: %s";
             message = String.format(message, row, col, piece, tttGrid[row][col]);
             throw new TttException(message);
          }
       }
    
       public TttPiece[][] getTttGrid() {
          return tttGrid;
       }
    
       public void gridPress(int row, int col) throws TttException {
          setGridPosition(row, col, player);
       }
    
       public void nextPlayer() {
          player = player == TttPiece.X ? TttPiece.O : TttPiece.X;
       }
    
       private void checkForWin(int row, int col, TttPiece piece) {
          // TODO finish
    
       }
    
       public void clear() {
          for (int row = 0; row < tttGrid.length; row++) {
             for (int col = 0; col < tttGrid[row].length; col++) {
                tttGrid[row][col] = TttPiece.EMPTY;
             }
          }
          player = TttPiece.X;
          pcSupport.firePropertyChange(GRID_POSITION, null, tttGrid);
       }
    
       public void addPropertyChangeListener(PropertyChangeListener listener) {
          pcSupport.addPropertyChangeListener(listener);
       }
    
       public void removePropertyChangeListener(PropertyChangeListener listener) {
          pcSupport.removePropertyChangeListener(listener);
       }
    
    }
    
    @SuppressWarnings("serial")
    class TttException extends Exception {
    
       public TttException() {
          super();
       }
    
       public TttException(String message) {
          super(message);
       }
    
    }
    

    Using for my images:

    enter image description here

    With GUI looking like:

    enter image description here