This is a simple tic-tac-toe program written in Java to show how to code the 2-persons game (1 human, 1 computer).
The emphasis is to show a typical control mechanism that handles the states change between the human player and the computer player. User interface is minimum and no image is used. This program runs as a java Application and SWING is used.
Programming Language: JavaSE 1.6;
IDE used: Eclipse SDK 3.7.0
Additional API or Packages: None.
There are only 2 classes in my tictactoe package: Class
TicTacToe and Class
Board.
(1) Class
TicTacToe extends the JFrame class and acts as the main program. See Figure 1 below.
package tictactoe;
import javax.swing.*;
@SuppressWarnings("serial")
public class TicTacToe extends JFrame {
public TicTacToe() {
add(new Board());
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setTitle("TicTacToe");
setSize(295,240);
setLocationRelativeTo(null);
setVisible(true);
setResizable(false);
}
public static void main(String[] args) {
new TicTacToe();
}
}
Fig 1. Class TicTacToe
(2) Class
Board extends a JPanel class. It handles the UI (user interface) and the control. Most of the 2D Board Games programming in Java use this structure. (See Figure 2 below)
By using simply JButtons, I handled the flow control in the
mouseClicked method. I did not use any image in the UI portion and thus does not need to deal with the
paint() method.
package tictactoe;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
@SuppressWarnings("serial")
public class Board extends JPanel implements MouseListener {
private JPanel upperPanel;
private JPanel centerPanel;
private JLabel label;
private JButton startButton;
private JButton button[] = new JButton[9];
private String[][] value = new String[][] {
{"", "", ""}, {"", "", ""}, {"", "", ""} };
private int[][] winMatrixX = new int[][] { // 8 is correct, not 9
{0,0,0},{1,1,1},{2,2,2},{0,1,2},
{0,1,2},{0,1,2},{0,1,2},{0,1,2} };
private int[][] winMatrixY = new int[][] {
{0,1,2},{0,1,2},{0,1,2},{0,0,0},
{1,1,1},{2,2,2},{0,1,2},{2,1,0} };
private boolean startGame = false;
private boolean nextMoveIsComputer = false;
private String msg;
public Board() {
setLayout(new BorderLayout());
upperPanel = new JPanel();
startButton = new JButton("Start Game");
startButton.setName("StartButton");
startButton.addMouseListener(this);
upperPanel.add(startButton);
add(upperPanel,BorderLayout.NORTH);
// create an invisible area
add(Box.createRigidArea(new Dimension(15, 0)), BorderLayout.WEST);
add(Box.createRigidArea(new Dimension(15, 0)), BorderLayout.EAST);
msg =" Click Start Button to start the game.";
label = new JLabel(msg);
add(label, BorderLayout.SOUTH);
centerPanel = new JPanel();
centerPanel.setLayout(new GridLayout(3, 3, 0, 0));
add(centerPanel, BorderLayout.CENTER);
for (int i = 0; i < 9; i++) {
button[i]= new JButton();
centerPanel.add(button[i]);
button[i].setName(String.valueOf(i));
button[i].addMouseListener(this);
}
}
private void initGame() {
startGame = true; // first click start the game
nextMoveIsComputer = false;
value = new String[][] {
{"", "", ""}, {"", "", ""}, {"", "", ""} };
resetAllButtons();
msg=" Your turn ";
label.setText(msg);
}
private void resetAllButtons() {
for (int i = 0; i < 9; i++) {
button[i].setText("");
}
}
private void computerMoveNow() {
boolean stillInGame = true;
if (nextMoveIsComputer && stillInGame) {
decideMove();
}
nextMoveIsComputer = false;
}
private void decideMove() {
// Rule 0. Decide winner
if ( gameOver() ) return;
// Rule 1. Win: If computer player has two O in a row,
// play the third to get three in a row.
if (value[0][0].equals("") && value[0][1].equals("O") &&
value[0][2].equals("O")) {
value[0][0]="O";button[0].setText("0");
msg=" I won !";label.setText(msg);
nextMoveIsComputer=false;startGame=false;return;}
if (value[0][0].equals("O") && value[0][1].equals("") &&
value[0][2].equals("O")) {
value[0][1]="O";button[1].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][0].equals("O") && value[0][1].equals("O") &&
value[0][2].equals("")) {
value[0][2]="O";button[2].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[1][0].equals("") && value[1][1].equals("O") &&
value[1][2].equals("O"))
{value[1][0]="O";button[3].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[1][0].equals("O") && value[1][1].equals("") &&
value[1][2].equals("O"))
{value[1][1]="O";button[4].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[1][0].equals("O") && value[1][1].equals("O") &&
value[1][2].equals(""))
{value[1][2]="O";button[5].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[2][0].equals("") && value[2][1].equals("O") &&
value[2][2].equals("O"))
{value[2][0]="O";button[6].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[2][0].equals("O") && value[2][1].equals("") &&
value[2][2].equals("O"))
{value[2][1]="O";button[7].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[2][0].equals("O") && value[2][1].equals("O") &&
value[2][2].equals(""))
{value[2][2]="O";button[8].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][0].equals("") && value[1][0].equals("O") &&
value[2][0].equals("O"))
{value[0][0]="O";button[0].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][0].equals("O") && value[1][0].equals("") &&
value[2][0].equals("O"))
{value[1][0]="O";button[3].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][0].equals("O") && value[1][0].equals("O") &&
value[2][0].equals(""))
{value[2][0]="O";button[6].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][1].equals("") && value[1][1].equals("O") &&
value[2][1].equals("O"))
{value[0][1]="O";button[1].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][1].equals("O") && value[1][1].equals("") &&
value[2][1].equals("O"))
{value[1][1]="O";button[4].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][1].equals("O") && value[1][1].equals("O") &&
value[2][1].equals(""))
{value[2][1]="O";button[7].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][2].equals("") && value[1][2].equals("O") &&
value[2][2].equals("O"))
{value[0][2]="O";button[2].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][2].equals("O") && value[1][2].equals("") &&
value[2][2].equals("O"))
{value[1][2]="O";button[5].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][2].equals("O") && value[1][2].equals("O") &&
value[2][2].equals(""))
{value[2][2]="O";button[8].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][0].equals("") && value[1][1].equals("O") &&
value[2][2].equals("O"))
{value[0][0]="O";button[0].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][0].equals("O") && value[1][1].equals("") &&
value[2][2].equals("O"))
{value[1][1]="O";button[4].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][0].equals("O") && value[1][1].equals("O") &&
value[2][2].equals(""))
{value[2][2]="O";button[8].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][2].equals("") && value[1][1].equals("O") &&
value[2][0].equals("O"))
{value[0][2]="O";button[2].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][2].equals("O") && value[1][1].equals("") &&
value[2][0].equals("O"))
{value[1][1]="O";button[4].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
if (value[0][2].equals("O") && value[1][1].equals("O") &&
value[2][0].equals(""))
{value[2][0]="O";button[6].setText("0");
msg=" I won !"; label.setText(msg);
nextMoveIsComputer=false; startGame=false; return;
}
// Rule 2. Block: If the [opponent] has two in a row,
// play the third to block them.
if (value[0][0].equals("") && value[0][1].equals("X") &&
value[0][2].equals("X"))
{value[0][0]="O";button[0].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][0].equals("X") && value[0][1].equals("") &&
value[0][2].equals("X"))
{value[0][1]="O";button[1].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][0].equals("X") && value[0][1].equals("X") &&
value[0][2].equals(""))
{value[0][2]="O";button[2].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[1][0].equals("") && value[1][1].equals("X") &&
value[1][2].equals("X"))
{value[1][0]="O";button[3].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[1][0].equals("X") && value[1][1].equals("") &&
value[1][2].equals("X"))
{value[1][1]="O";button[4].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[1][0].equals("X") && value[1][1].equals("X") &&
value[1][2].equals(""))
{value[1][2]="O";button[5].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[2][0].equals("") && value[2][1].equals("X") &&
value[2][2].equals("X"))
{value[2][0]="O";button[6].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[2][0].equals("X") && value[2][1].equals("") &&
value[2][2].equals("X"))
{value[2][1]="O";button[7].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[2][0].equals("X") && value[2][1].equals("X") &&
value[2][2].equals(""))
{value[2][2]="O";button[8].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][0].equals("") && value[1][0].equals("X") &&
value[2][0].equals("X"))
{value[0][0]="O";button[0].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][0].equals("X") && value[1][0].equals("") &&
value[2][0].equals("X"))
{value[1][0]="O";button[3].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][0].equals("X") && value[1][0].equals("X") &&
value[2][0].equals(""))
{value[2][0]="O";button[6].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][1].equals("") && value[1][1].equals("X") &&
value[2][1].equals("X"))
{value[0][1]="O";button[1].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][1].equals("X") && value[1][1].equals("") &&
value[2][1].equals("X"))
{value[1][1]="O";button[4].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][1].equals("X") && value[1][1].equals("X") &&
value[2][1].equals(""))
{value[2][1]="O";button[7].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][2].equals("") && value[1][2].equals("X") &&
value[2][2].equals("X"))
{value[0][2]="O";button[2].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][2].equals("X") && value[1][2].equals("") &&
value[2][2].equals("X"))
{value[1][2]="O";button[5].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][2].equals("X") && value[1][2].equals("X") &&
value[2][2].equals(""))
{value[2][2]="O";button[8].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][0].equals("") && value[1][1].equals("X") &&
value[2][2].equals("X"))
{value[0][0]="O";button[0].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][0].equals("X") && value[1][1].equals("") &&
value[2][2].equals("X"))
{value[1][1]="O";button[4].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][0].equals("X") && value[1][1].equals("X") &&
value[2][2].equals(""))
{value[2][2]="O";button[8].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][2].equals("") && value[1][1].equals("X") &&
value[2][0].equals("X"))
{value[0][2]="O";button[2].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][2].equals("X") && value[1][1].equals("") &&
value[2][0].equals("X"))
{value[1][1]="O";button[4].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
if (value[0][2].equals("X") && value[1][1].equals("X") &&
value[2][0].equals(""))
{value[2][0]="O";button[6].setText("0");
msg=" Your turn"; label.setText(msg);
nextMoveIsComputer=false; return;
}
// Rule 3. Fork: Create an opportunity where you can win in two ways.
// Rule 4. Block opponent's Fork:
// Option 1: Create two in a row to force the opponent into
// defending, as long as it doesn't result in them creating
// a fork or winning. For example, if "X" has a corner, "O"
// has the center, and "X" has the opposite corner as well,
// "O" must not play a corner in order to win. (Playing a
// corner in this scenario creates a fork for "X" to win.)
// Option 2: If there is a configuration where the opponent
// can fork, block that fork.
// Rule 5. Center: Play the center.
if (value[1][1].equals("")) {
value[1][1]="O";button[4].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
// Rule 6. Opposite corner: If the opponent is in the
// corner, play the opposite corner.
if (value[0][0].equals("") && value[2][2].equals("X")) {
value[0][0]="O";button[0].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
if (value[0][1].equals("") && value[2][1].equals("X")) {
value[0][1]="O";button[1].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
if (value[0][2].equals("") && value[2][0].equals("X")) {
value[0][2]="O";button[2].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
if (value[1][0].equals("") && value[1][2].equals("X")) {
value[1][0]="O";button[3].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
if (value[1][0].equals("X") && value[1][2].equals("")) {
value[1][2]="O";button[5].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
if (value[0][2].equals("X") && value[2][0].equals("")) {
value[2][0]="O";button[6].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
if (value[0][1].equals("X") && value[2][1].equals("")) {
value[2][1]="O";button[7].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
if (value[0][0].equals("X") && value[2][2].equals("")) {
value[2][2]="O";button[8].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
// Rule 7. Empty corner: Play in a corner square.
if (value[0][0].equals("")) {
value[0][0]="O";button[0].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
if (value[0][2].equals("")) {
value[0][2]="O";button[2].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
if (value[2][0].equals("")) {
value[2][0]="O";button[6].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
if (value[2][2].equals("")) {
value[2][2]="O";button[8].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
// Rule 8. Empty side: Play in a middle square on any of
// the 4 sides.
if (value[0][1].equals("")) {
value[0][1]="O";button[1].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
if (value[1][0].equals("")) {
value[1][0]="O";button[3].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
if (value[1][2].equals("")) {
value[1][2]="O";button[5].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
if (value[2][1].equals("")) {
value[2][1]="O";button[7].setText("0");msg=" Your turn";
label.setText(msg); nextMoveIsComputer=false; return;
}
}
private boolean gameOver() {
int blank = 0;
for (int i = 0; i < 8; i++) {
int cross = 0;
int nough = 0;
for (int j = 0; j < 3; j++) {
if (value[winMatrixX[i][j]][winMatrixY[i][j]]=="X" ) {
cross++;
} else if (value[winMatrixX[i][j]][winMatrixY[i][j]]=="O" ) {
nough++;
} else
blank++;
}
if (cross == 3) {
msg=" You won !";
label.setText(msg);
startGame=false;
return true;
}
if (nough == 3) {
msg=" I won !";
label.setText(msg);
startGame=false;
return true;
}
}
if (blank == 0) {
msg=" Draw & Game Over!";
label.setText(msg);
startGame=false;
return true;
}
return false;
}
@Override
public void mouseClicked(MouseEvent e) {
JButton aButton = (JButton) e.getSource();
if (aButton.getName().equalsIgnoreCase(startButton.getName())) {
initGame();
} else {
if (startGame) { // game starts
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (aButton.getName().equalsIgnoreCase(button[i*3+j].getName())) {
if (value[i][j].equals("") ) {
value[i][j] = "X"; // computer:O, user: X
aButton.setText("X");
nextMoveIsComputer = true;
}
}
}
}
computerMoveNow();
} // end of inGame
} // of else
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
Fig 2. Class Board
The code has not been fully optimized or re-factored sufficiently. It is a working example though.
The is the TicTacToe java program.