I have been trying to learn to program in a more object oriented manner and I am at the moment working on a Tic Tac Toe game. I have tried to split my classes so that it would make sense, OOP wise. I am just concerned whether I have split it up correctly and if I am really following the standards of OOP programming. I am especially concerned about the fact that I am creating a Scoreboard object inside GameBoard
in order to access the methods of scoreboard. I'm not sure if there is a more neat way to do this.
BoardButton.java
import javax.swing.JButton;
public class BoardButton extends JButton
{
private String sign;
private boolean pressed;
private int xPos,yPos,value;
public BoardButton(int xPos, int yPos) {
this.xPos = xPos;
this.yPos = yPos;
value = 0;
}
public void setSign(String sign) {
setText(sign);
}
public String getSign() {
return getText();
}
public boolean getState() {
return pressed;
}
public void setState(boolean pressed) {
this.pressed = pressed;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
ScoreBoard.java
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.Box;
import java.awt.Font;
import java.awt.Color;
import javax.swing.BoxLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Scoreboard extends JPanel
{
private JButton reset, newGame;
private JLabel circle, cross, tie, scores;
public Scoreboard() {
newGame = new JButton("New Game");
reset = new JButton("Reset Scores");
reset.addActionListener(new BtnListener());
newGame.addActionListener(new BtnListener());
cross = new JLabel("Cross: 0 wins");
circle = new JLabel("Circle: 0 wins");
tie = new JLabel("Ties: 0");
scores = new JLabel("Scores");
scores.setFont(new Font("Arial", Font.BOLD, 20));
scores.setForeground(Color.darkGray);
cross.setFont(new Font("Arial", Font.BOLD, 15));
cross.setForeground(Color.lightGray);
circle.setFont(new Font("Arial", Font.BOLD, 15));
circle.setForeground(Color.lightGray);
tie.setFont(new Font("Arial", Font.BOLD, 15));
tie.setForeground(Color.lightGray);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(Box.createVerticalStrut(10));
add(scores);
add(circle);
add(Box.createVerticalStrut(20));
add(cross);
add(Box.createVerticalStrut(20));
add(tie);
add(reset);
add(Box.createVerticalStrut(100));
}
public void updateScore(int circleScore, int crossScore, int tieScore) {
circle.setText("Cirlcle: " + Integer.toString(circleScore) + " wins");
cross.setText("Cross: " + Integer.toString(crossScore) + " wins");
tie.setText("Ties: " + Integer.toString(tieScore));
}
class BtnListener implements ActionListener {
public void actionPerformed (ActionEvent e) {
if(e.getSource() == reset) {
circle.setText("Circle: 0 wins");
cross.setText("Cross: 0 wins");
tie.setText("Ties: 0");
}
}
}
}
GameBoard.java
import javax.swing.JPanel;
import java.awt.Font;
import java.awt.Color;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JOptionPane;
import java.awt.Component;
import java.awt.GridLayout;
public class GameBoard extends JPanel
{
private BoardButton[][] btn;
private int crossCount, circleCount, tieCount, clicks;
private boolean win;
private Timer timer;
private Scoreboard scoreboard;
public GameBoard(Scoreboard scoreboard, Timer timer) {
win = false;
this.scoreboard = scoreboard;
this.timer = timer;
btn = new BoardButton[3][3];
for(int i=0; i<3; i++){
for(int j=0; j<3; j++) {
btn[i][j]=new BoardButton(j,i);
btn[i][j].setFont(new Font("Arial", Font.BOLD, 70));
btn[i][j].setForeground(Color.blue);
btn[i][j].addActionListener(new BoardListener());
add(btn[i][j]);
}
}
setLayout(new GridLayout(3,3));
}
public void checkWin() {
int diagSum1 = 0;
int diagSum2 = 0;
int colSum = 0;
int rowSum = 0;
String winner = "";
diagSum1 = btn[0][2].getValue() + btn[1][1].getValue() + btn[2][0].getValue();
diagSum2 = btn[0][0].getValue() + btn[1][1].getValue() + btn[2][2].getValue();
if(diagSum1 == 3 || diagSum2 == 3) {
winner = "Cross";
crossCount++;
win = true;
}
else if(diagSum1 == -3 || diagSum2 == -3) {
winner = "Circle";
circleCount++;
win = true;
}
for(int i = 0; i<3; i++) {
for(int j = 0; j<3; j++) {
rowSum += btn[i][j].getValue();
colSum += btn[j][i].getValue();
}
if(rowSum == 3 || colSum == 3 && winner.equals("")) {
winner = "Cross";
crossCount++;
win = true;
}
else if(rowSum == -3 || colSum == -3 && winner.equals("")) {
winner = "Circle";
circleCount++;
win = true;
}
rowSum = 0;
colSum = 0;
}
if(clicks == 9 && winner.equals("")) {
winner = "No one";
win = true;
tieCount++;
}
if(win) {
setPanelEnabled(this, false);
timer.setRunning(false);
JOptionPane.showMessageDialog(null, winner + " is the winner!","Results",-1);
}
scoreboard.updateScore(circleCount, crossCount, tieCount);
}
public void reset() {
for(int i=0; i<3; i++){
for(int j=0; j<3; j++) {
timer.reset();
btn[i][j].setSign("");
btn[i][j].setState(false);
btn[i][j].setValue(0);
clicks = 0;
win = false;
}
}
}
public void setPanelEnabled(JPanel panel, Boolean isEnabled) {
panel.setEnabled(isEnabled);
Component[] components = panel.getComponents();
for(int i = 0; i < components.length; i++) {
if(components[i].getClass().getName() == "javax.swing.JPanel") {
setPanelEnabled((JPanel) components[i], isEnabled);
}
components[i].setEnabled(isEnabled);
}
}
class BoardListener implements ActionListener {
public void actionPerformed (ActionEvent e) {
BoardButton buttonClicked = (BoardButton)e.getSource();
if(buttonClicked.getState()==false) {
clicks++;
if(clicks%2==0) {
buttonClicked.setText("X");
buttonClicked.setForeground(Color.blue);
buttonClicked.setValue(1);
checkWin();
}
else {
buttonClicked.setText("O");
buttonClicked.setValue(-1);
buttonClicked.setForeground(Color.red);
checkWin();
}
}
buttonClicked.setState(true);
}
}
}
TicTacToeGUI.java
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.BorderLayout;
import javax.swing.JLabel;
public class TicTacToeGUI extends JFrame {
private JPanel mainPanel;
private Timer timer;
private Scoreboard scoreboard;
private GameBoard game;
private JButton newGame;
public TicTacToeGUI() {
mainPanel = new JPanel();
timer = new Timer();
scoreboard = new Scoreboard();
game = new GameBoard(scoreboard, timer);
newGame = new JButton("New Game");
newGame.addActionListener(new BtnListener());
scoreboard.add(newGame);
mainPanel.setLayout(new BorderLayout());
mainPanel.add(game, BorderLayout.CENTER);
mainPanel.add(scoreboard, BorderLayout.EAST);
mainPanel.add(timer, BorderLayout.SOUTH);
add(mainPanel);
timer.setRunning(true);
setTitle("TicTacToe");
setSize(500,475);
setLocationRelativeTo(null);
setVisible(true);
}
class BtnListener implements ActionListener {
public void actionPerformed (ActionEvent e) {
if(e.getSource() == newGame) {
game.reset();
game.setPanelEnabled(game, true);
timer.setRunning(true);
}
}
}
}
TicTacToeMain.java
public class TicTacToeMain
{
public static void main(String[] args) {
TicTacToeGUI g = new TicTacToeGUI();
}
}