Tic-Tac-Toe Game in Java using MVC

Below is a simple implementation of the classic Tic-Tac-Toe game in Java, structured using the Model-View-Controller (MVC) design pattern.

TicTacToe image

Model:

public class Model {
    private int moves;
    private String symbol;
    private int xScore = 0;
    private int oScore = 0;

    public Model() {
        moves = 0;
    }

    public void setChoice() {
        if (moves % 2 == 0 )
            symbol = "X";
        else
            symbol = "O";
    }

    public void addMoves() { 
        moves++; 
    }
    
    public String getSymbol() {
        return symbol;
    }
    
    public int getMoves() {
        return moves;
    }

    public int getXScore() {
        xScore++;
        return xScore;
    }

    public int getOScore() {
        oScore++;
        return oScore;
    }

    public void setMoves() {
        moves = 0;
        
    }
}
                

View:

    import java.awt.*;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.plaf.metal.MetalButtonUI;
    import javax.swing.JButton;
    
    class View extends JFrame {
        JButton[] buttons;
        Controller controller;
        boolean gameEnd;
        JLabel textField = new JLabel();
        JLabel xScore = new JLabel();
        JLabel oScore = new JLabel();
        JPanel textPanel = new JPanel();
        JPanel buttonPanel = new JPanel();
    
        public View(Controller controller) {
            super("TicTacToe");
            this.controller = controller;
            buttons = new JButton[9];
            buttonPanel.setPreferredSize(new Dimension(500, 500));
            this.setLayout(new BorderLayout());  
            this.setSize(500,600);
            this.setDefaultCloseOperation(EXIT_ON_CLOSE);
            
            addComponentListener(new java.awt.event.ComponentAdapter() {
                public void componentResized(java.awt.event.ComponentEvent evt) {
                    formComponentResized(evt);
                }
            });
            
            textField.setForeground(Color.BLACK);
            textField.setFont(new Font("Serif", Font.PLAIN, 20));
            textField.setHorizontalAlignment(JLabel.CENTER);
            textField.setText("It´s X's turn!");
            
            xScore.setForeground(Color.BLACK);
            xScore.setFont(new Font("Serif", Font.PLAIN, 20));
            xScore.setHorizontalAlignment(JLabel.RIGHT);
            xScore.setText("Player X Score: 0");
            
            oScore.setForeground(Color.BLACK);
            oScore.setFont(new Font("Serif", Font.PLAIN, 20));
            oScore.setText("Player O Score: 0");
            
            textPanel.setBounds(0, 0, 600, 100);
            textPanel.setLayout(new BorderLayout());
            textPanel.setBackground(Color.white);
            buttonPanel.setLayout(new GridLayout(3, 3));
            
    
            for (int i = 0; i < buttons.length; i++) {
                buttons[i] = new JButton();
                buttons[i].getPreferredSize();
                buttonPanel.add(buttons[i]);
                buttons[i].setFont(new Font("Serif", Font.PLAIN, 110));
                buttons[i].setFocusable(false);
                buttons[i].setBackground(Color.white);
            }
            this.add(buttonPanel);
            
            for (int i = 0; i < buttons.length; i++) {
                buttons[i].setActionCommand(String.valueOf(i));
                buttons[i].addActionListener(controller);
            }
            
            textPanel.add(oScore, BorderLayout.WEST);
            textPanel.add(textField, BorderLayout.CENTER);
            textPanel.add(xScore, BorderLayout.EAST);
            this.add(textPanel, BorderLayout.NORTH);

            pack();
            this.setVisible(true);
            gameEnd = false;
        }
    
        public boolean checkForWinner() {
            if ((buttons[0].getText()=="X") && (buttons[1].getText()=="X") && (buttons[2].getText()=="X")) {
                xWins(0,1,2);
                return true;
            }
    
            if ((buttons[3].getText()=="X") && (buttons[4].getText()=="X") && (buttons[5].getText()=="X")) {
                xWins(3,4,5);
                return true;
            }
    
            if ((buttons[6].getText()=="X") && (buttons[7].getText()=="X") && (buttons[8].getText()=="X")) {
                xWins(6,7,8);
                return true;
            }
    
            if ((buttons[0].getText()=="X") && (buttons[3].getText()=="X") && (buttons[6].getText()=="X")) {
                xWins(0,3,6);
                return true;
            }
    
            if ((buttons[1].getText()=="X") && (buttons[4].getText()=="X") && (buttons[7].getText()=="X")) {
                xWins(1,4,7);
                return true;
            }
    
            if ((buttons[2].getText()=="X") && (buttons[5].getText()=="X") && (buttons[8].getText()=="X")) {
                xWins(2,5,8);
                return true;
            }
    
            if ((buttons[0].getText()=="X") && (buttons[4].getText()=="X") && (buttons[8].getText()=="X")) {
                xWins(0,4,8);
                return true;
            }
    
            if ((buttons[2].getText()=="X") && (buttons[4].getText()=="X") && (buttons[6].getText()=="X")) {
                xWins(2,4,6);
                return true;
            }
    
            if ((buttons[0].getText()=="O") && (buttons[1].getText()=="O") && (buttons[2].getText()=="O")) {
                oWins(0,1,2);
                return true;
            }
    
            if ((buttons[3].getText()=="O") && (buttons[4].getText()=="O") && (buttons[5].getText()=="O")) {
                oWins(3,4,5);
                return true;
            }
    
            if ((buttons[6].getText()=="O") && (buttons[7].getText()=="O") && (buttons[8].getText()=="O")) {
                oWins(6,7,8);
                return true;
            }
    
            if ((buttons[0].getText()=="O") && (buttons[3].getText()=="O") && (buttons[6].getText()=="O")) {
                oWins(0,3,6);
                return true;
            }
    
            if ((buttons[1].getText()=="O") && (buttons[4].getText()=="O") && (buttons[7].getText()=="O")) {
                oWins(1,4,7);
                return true;
            }
    
            if ((buttons[2].getText()=="O") && (buttons[5].getText()=="O") && (buttons[8].getText()=="O")) {
                oWins(2,5,8);
                return true;
            }
    
            if ((buttons[0].getText()=="O") && (buttons[4].getText()=="O") && (buttons[8].getText()=="O")) {
                oWins(0,4,8);
                return true;
            }
    
            if ((buttons[2].getText()=="O") && (buttons[4].getText()=="O") && (buttons[6].getText()=="O")) {
                oWins(2,4,6);
                return true;
            }
            
            return false;
        }
    
        public void updateGame() { 
            if(checkForWinner() == true) {
                Object[] option={"Ok","Exit"};
                    int n=JOptionPane.showOptionDialog(this, "Play Again?","Message",JOptionPane.YES_NO_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE,null,option,option[0]);
                    if(n==0){
                        textField.setText("It´s X's turn!");
                        gameEnd = false;
                        for (int i = 0; i < buttons.length; i++) {
                            buttons[i].setEnabled(true);
                            buttons[i].setText("");
                            buttons[i].setBackground(Color.white);
                            controller.setMoves();
                        }
                    }
                    else{
                        gameEnd = true;
                    }
            }
            else if (controller.getMoves() == 9) {
                textField.setText("Match tie!");
                JOptionPane.showMessageDialog(this, "Match tie!","Message", JOptionPane.INFORMATION_MESSAGE);
                Object[] option={"Ok","Exit"};
                    int n=JOptionPane.showOptionDialog(this, "Play Again?","Message",JOptionPane.YES_NO_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE,null,option,option[0]);
                    if(n==0){
                    textField.setText("It´s X's turn!");
                        gameEnd = false;
                    for (int i = 0; i < buttons.length; i++) {
                        buttons[i].setEnabled(true);
                        buttons[i].setText("");
                        buttons[i].setBackground(Color.white);
                        controller.setMoves();
                    }
                    
                    }
                    else{
                        gameEnd = true;
                    }
                }    
        }
    
        public void endGame() {
            for (int i = 0; i < buttons.length; i++)
                buttons[i].setEnabled(false);
            
        }
        
        public void xWins(int pos1, int pos2, int pos3) {
            buttons[pos1].setBackground(Color.LIGHT_GRAY);
            buttons[pos2].setBackground(Color.LIGHT_GRAY);
            buttons[pos3].setBackground(Color.LIGHT_GRAY);
            textField.setText("X wins!");
            xScore.setText("Player X Score: "  + controller.getXScore() + "");
            JOptionPane.showMessageDialog(this, "Player X won the game!","Message", JOptionPane.INFORMATION_MESSAGE);
        }
    
        public void oWins(int pos1, int pos2, int pos3) {
            buttons[pos1].setBackground(Color.LIGHT_GRAY);
            buttons[pos2].setBackground(Color.LIGHT_GRAY);
            buttons[pos3].setBackground(Color.LIGHT_GRAY);
            textField.setText("O wins!");
            oScore.setText("Player O Score: "  + controller.getOScore() + "");
            JOptionPane.showMessageDialog(this, "Player O won the game!","Message", JOptionPane.INFORMATION_MESSAGE);
        }
    
        private void formComponentResized(java.awt.event.ComponentEvent evt) {
                for(int i=0;i<9;i++) {
                    buttons[i].setFont(buttons[i].getFont().deriveFont((float)(buttons[i].getWidth()/2)));
                }
        }
        
        public void setText(String symbol, int i) {
            if(symbol == "X") { 
                if (buttons[i].getText() == "") {
                    buttons[i].setUI(new MetalButtonUI() { 
                        protected Color getDisabledTextColor() {
                            return Color.red;
                        }
                    });
                    buttons[i].setText(symbol);
                    textField.setText("It´s O's turn!");
                }
            }
            else {
                if (buttons[i].getText() == "") {
                    buttons[i].setUI(new MetalButtonUI() { 
                        protected Color getDisabledTextColor() {
                            return Color.blue;
                        }
                    });
                    buttons[i].setText(symbol);
                    textField.setText("It´s X´s turn!");
                }
            }
            buttons[i].setEnabled(false);
        }
    
    }
                    

Controller:

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

class Controller implements ActionListener {
    private View view;
    private Model model;

    public Controller(Model model) {
        this.model = model;
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        if (view.gameEnd == false) {
            model.setChoice();
            if (e.getActionCommand() != "") {
            	int button = Integer.parseInt(e.getActionCommand());
            	view.setText(model.getSymbol(), button); 
            	model.addMoves();
            }
        }
    }

	public void setView(View view) {
		this.view = view;
	}
	
	public int getMoves() {
		return model.getMoves();
	}
	public int getXScore() {
		return model.getXScore();
		
	}
	public int getOScore() {
		return model.getOScore();
		
	}

	public void setMoves() {
		model.setMoves();
		
	}
}
                        

TicTacToe (main):

public class TicTacToe {

    public static void main(String[] args) {
        Model model = new Model();
        Controller controller = new Controller(model);
        View view = new View(controller);
        controller.setView(view);
        
        boolean run = true;
        while (run) {
            view.updateGame();
            if (view.gameEnd == true) {
                view.endGame();
                run = false;
            }
        }
        System.exit(0);
    }
}