Sunday, May 13, 2012

Tic Tac Toe Game (Swing,Java)



Here I present a simple TicTacToe Program.
You can download my code and play in your computer.

Download Source Code:
TicTacToe

Save to file: TicTacToeMain.java

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class TicTacToeMain extends JFrame implements ActionListener {

 private JButton [][]buttons = new JButton[3][3];
 private JButton playButton = new JButton("Play");
 private JLabel statusLabel = new JLabel("");
 private TicTacToeAI game = null;
 private int human = 0;
 private int computer = 0;
 private boolean isPlay = false;
 private String []chars=new String[]{"","X","O"};

 private void setStatus(String s) {
  statusLabel.setText(s);
 }

 private void setButtonsEnabled(boolean enabled) {
  for(int i=0;i<3;i++)
   for(int j=0;j<3;j++) {
    buttons[i][j].setEnabled(enabled);
    if(enabled) buttons[i][j].setText(" ");
   }
 }

 public TicTacToeMain() {

  setTitle("Tic Tac Toe");
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  setResizable(false);

  JPanel centerPanel = new JPanel(new GridLayout(3,3));
  Font font = new Font("Arial",Font.BOLD, 32);
  for(int i=0;i<3;i++)
   for(int j=0;j<3;j++) {
    buttons[i][j] = new JButton(" ");
    buttons[i][j].setFont(font);
    buttons[i][j].addActionListener(this);
    buttons[i][j].setFocusable(false);
    centerPanel.add(buttons[i][j]);
   }

  playButton.addActionListener(this);

  JPanel northPanel = new JPanel();
  northPanel.add(statusLabel);

  JPanel southPanel = new JPanel();
  southPanel.add(playButton);

  setStatus("Click 'Play' To Start");
  setButtonsEnabled(false);

  add(northPanel,"North");
  add(centerPanel,"Center");
  add(southPanel,"South");

  setSize(300,300);

  // I'm lazy to implement the correct way
  setLocationRelativeTo(null);
 }

 public static void main(String []args) {
  new TicTacToeMain().setVisible(true);
 }

 private void computerTurn() {
  if(!isPlay) return;

  int []pos = game.nextMove(computer);
  if(pos!=null) {
   int i = pos[0];
   int j = pos[1];
   buttons[i][j].setText(chars[computer]);
   game.setBoardValue(i,j,computer);
  }

  checkState();
 }

 private void gameOver(String s) {
  setStatus(s);
  setButtonsEnabled(false);
  isPlay = false;
 }

 private void checkState() {
  if(game.isWin(human)) {
   gameOver("Congratulations, You've Won!");
  }
  if(game.isWin(computer)) {
   gameOver("Sorry, You Lose!");
  }
  if(game.nextMove(human)==null && game.nextMove(computer)==null) {
   gameOver("Draw, Click 'Play' For Rematch!");
  }
 }

 private void click(int i,int j) {
  if(game.getBoardValue(i,j)==TicTacToeAI.EMPTY) {
   buttons[i][j].setText(chars[human]);
   game.setBoardValue(i,j,human);
   checkState();
   computerTurn();
  }
 }

 public void actionPerformed(ActionEvent event) {
  if(event.getSource()==playButton) {
   play();
  }else {
   for(int i=0;i<3;i++)
    for(int j=0;j<3;j++)
     if(event.getSource()==buttons[i][j])
      click(i,j);
  }
 }

 private void play() {
  game = new TicTacToeAI();
  human = TicTacToeAI.ONE;
  computer = TicTacToeAI.TWO;
  setStatus("Your Turn");
  setButtonsEnabled(true);
  isPlay = true;
 }
}
Save to file: TicTacToeAI.java

public class TicTacToeAI {

 /* the board */
 private int board[][];
 /* empty */
 public static final int EMPTY = 0;
 /* player one */
 public static final int ONE = 1;
 /* player two */
    public static final int TWO = 2;

 public TicTacToeAI() {
  board = new int[3][3];
 }

 /* get the board value for position (i,j) */
 public int getBoardValue(int i,int j) {
  if(i < 0 || i >= 3) return EMPTY;
  if(j < 0 || j >= 3) return EMPTY;
  return board[i][j];
    }

 /* set the board value for position (i,j) */
 public void setBoardValue(int i,int j,int token) {
  if(i < 0 || i >= 3) return;
  if(j < 0 || j >= 3) return;
  board[i][j] = token;
    }

 /* calculate the winning move for current token */
 public int []nextWinningMove(int token) {

  for(int i=0;i<3;i++)
   for(int j=0;j<3;j++)
    if(getBoardValue(i, j)==EMPTY) {
     board[i][j] = token;
     boolean win = isWin(token);
     board[i][j] = EMPTY;
     if(win) return new int[]{i,j};
    }

  return null;
    }

    public int inverse(int token) {
  return token==ONE ? TWO : ONE;
 }

    /* calculate the best move for current token */
    public int []nextMove(int token) {

        /* lucky position in the center of board*/
        if(getBoardValue(1, 1)==EMPTY) return new int[]{1,1};

        /* if we can move on the next turn */
        int winMove[] = nextWinningMove(token);
        if(winMove!=null) return winMove;

        /* choose the move that prevent enemy to win */
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                if(getBoardValue(i, j)==EMPTY)
                {
                    board[i][j] = token;
              boolean ok = nextWinningMove(inverse(token)) == null;
                    board[i][j] = EMPTY;
                    if(ok) return new int[]{i,j};
                }

        /* choose available move */
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                if(getBoardValue(i, j)==EMPTY)
                    return new int[]{i,j};

        /* no move is available */
        return null;
    }

 /* determine if current token is win or not win */
 public boolean isWin(int token) {
  final int DI[]={-1,0,1,1};
  final int DJ[]={1,1,1,0};
  for(int i=0;i<3;i++)
   for(int j=0;j<3;j++) {

    /* we skip if the token in position(i,j) not equal current token */
    if(getBoardValue(i, j)!=token) continue;

    for(int k=0;k<4;k++) {
     int ctr = 0;
                 while(getBoardValue(i+DI[k]*ctr, j+DJ[k]*ctr)==token) ctr++;

     if(ctr==3) return true;
    }
  }
  return false;
    }
} 

18 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. can you help me to make this game but in console mode with java and minmax algorithm...same 3x3 but with the wall.ty :)

    ReplyDelete
  3. Good work, I have been for a simple code and yours works perfectly. Thanks

    ReplyDelete
  4. You really gave a great idea, a small version of tic tac toe game will work perfectly and one with this size of checkers.

    ReplyDelete
  5. Would love you to submit your code to http://www.programr.com. We offer an interesting way for beginners to learn java programming

    ReplyDelete
  6. @Ronald: Sure, thanks for introduce me programr.com

    ReplyDelete
  7. Thanks for codes, and I want to expand AI for 5x5 TicTacToe but I couldn't find how to change isWin() for 5x5. Can you please help me?

    ReplyDelete
  8. which artificial algorithm is used in this tic tac toe code???please reply

    ReplyDelete
  9. Which IDE should i use for this????

    ReplyDelete
    Replies
    1. You can use simple editor like textpad / wordpad.

      Delete
  10. This code isn't unbeatable, just click on center and last square and you have a fork!

    ReplyDelete
    Replies
    1. You should try this one:
      http://algojava.blogspot.com/p/tictactoe-7x7.html

      N=3, M=3

      Delete
  11. final int DI[]={-1,0,1,1}; final int DJ[]={1,1,1,0};
    Why we need above two?can u please explain me?

    ReplyDelete
  12. what if you want to make it choose a random player at the beginning? like instead of always human going first, computer goes first.

    ReplyDelete

  13. thanks for your help to get the source code that is simple

    ReplyDelete

  14. Learned a lot of new things from your post , Thaks for sharing


    Java Online Training

    ReplyDelete