Skip to content

Instantly share code, notes, and snippets.

@aramperes
Last active August 27, 2018 20:53
Show Gist options
  • Save aramperes/2a02101595b3c924d5c4a41ca125d2f7 to your computer and use it in GitHub Desktop.
Save aramperes/2a02101595b3c924d5c4a41ca125d2f7 to your computer and use it in GitHub Desktop.
package tictactoegame.ui;
import javax.swing.*;
import java.awt.*;
public class SwingTicTacToe extends JFrame {
/**
* The font used for the buttons.
*/
private static final Font FONT = new Font("Arial", Font.PLAIN, 50);
/**
* The board map (2D array, each char is one of '-', 'x', 'o').
*/
private final char[][] board = {{'-', '-', '-'}, {'-', '-', '-'}, {'-', '-', '-'}};
/**
* The buttons corresponding to the board.
*/
private final JButton[][] buttons = new JButton[3][3];
/**
* Whether it is X's turn currently.
*/
private boolean turnX = true;
private SwingTicTacToe(String title, int width, int height) {
super(title);
// Sets the size of the window
setSize(width, height);
// Puts the window in the middle of the screen, instead of the top left
setLocationRelativeTo(null);
// Makes the application exit when the window is closed
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// Makes the window not resizable
setResizable(false);
Container pane = getContentPane();
// Makes the grid 3x3
pane.setLayout(new GridLayout(3, 3));
// Initializes the buttons
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 3; x++) {
JButton button = new JButton();
button.setFont(FONT);
// Loop cursors are copied to final values, so they can be used inside anonymous classes
int finalX = x;
int finalY = y;
// Adds action listeners for each button
button.addActionListener(e -> {
// Sets the board value
board[finalY][finalX] = turnX ? 'x' : 'o';
updateButtons();
// Switches whose turn it is
turnX = !turnX;
// Checks if the game has ended
checkBoard();
});
// Removes the outline on buttons
button.setFocusable(false);
// Adds the button to the grid
pane.add(button);
buttons[y][x] = button;
}
}
updateButtons();
}
private void checkBoard() {
if (!someoneHasWon() && isBoardFull()) {
// If nobody won and the board is full, the game is a tie
JOptionPane.showMessageDialog(this, "It's a tie!");
// Start over
resetBoard();
}
if (someoneHasWon()) {
// Someone won, announce the winner
if (!turnX) {
JOptionPane.showMessageDialog(this, "X won!");
} else {
JOptionPane.showMessageDialog(this, "O won!");
}
// Start over
resetBoard();
}
}
/**
* Checks if whether someone has completed a winning move.
*/
private boolean someoneHasWon() {
// Diagonals
if (board[1][1] != '-') {
if (board[0][0] == board[1][1] && board[1][1] == board[2][2])
return true;
if (board[0][2] == board[1][1] && board[1][1] == board[2][0])
return true;
}
// Test rows
for (int i = 0; i < 3; ++i) {
if (board[i][0] != '-' && board[i][0] == board[i][1] && board[i][1] == board[i][2])
return true;
}
// Test columns
for (int j = 0; j < 3; ++j) {
if (board[0][j] != '-' && board[0][j] == board[1][j] && board[1][j] == board[2][j])
return true;
}
return false;
}
/**
* Checks whether no tiles are left empty.
*/
private boolean isBoardFull() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j] == '-') {
return false;
}
}
}
return true;
}
/**
* Resets the board to its original (empty) state.
*/
private void resetBoard() {
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 3; x++) {
board[y][x] = '-';
}
}
turnX = true;
updateButtons();
}
/**
* Updates the buttons to reflect the board.
*/
private void updateButtons() {
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 3; x++) {
char tile = board[y][x];
if (tile == '-') {
buttons[y][x].setEnabled(true);
buttons[y][x].setText("");
} else {
buttons[y][x].setText(String.valueOf(board[y][x]));
buttons[y][x].setEnabled(false);
}
}
}
}
public static void main(String[] args) throws Exception {
// Overrides the Swing look to the OS look.
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
// Start
SwingTicTacToe window = new SwingTicTacToe("TicTacToe", 500, 500);
window.setVisible(true);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment