Header Ads

Java share soure code game TicTacToe - Minimax algorithm -Java swing

After learning the MiniMax algorithm in Computer science class, I decided to practice it on Tic Tac Toe. The algorithm is simple to understand but too implement to this game it not too easy.. for me, it took me much more time than I expected.
Big thanks to this blog ,it help me alot , and i make this game on java swing base on that code !
So, I would like to share what I have learned here.Take a look..


Demo :



Here is source of that game :
<!-----------------------------------------------------------!-->
public class Turn {
    
    enum NextMove {

        O, X, E
    }
    NextMove next;
}

<!----------------------------------------------------------!-->
class Point{
    

    int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public String toString() {
      return "(" + x + ", " + y + ")";
    }  
    
}

<!---------------------------------------------------------!-->
class PointsAndScores{
    
    int score;
    Point point;

    PointsAndScores(int score, Point point) {
        this.score = score;
        this.point = point;
    }

<!-----------------------------------------------------------------------------------!-->

class BoardGame {
    static int check = 0 ;
    List<Point> availablePoints;
    int[][] boardGame = new int[3][3];

    public BoardGame() {
    }

    public boolean isGameOver() {
        
        return (isXWon() || isOWon() || getAvailableStates().isEmpty());
    }

    public boolean isXWon() {
        if ((boardGame[0][0] == boardGame[1][1] && boardGame[0][0] == boardGame[2][2] && boardGame[0][0] == 1) || (boardGame[0][2] == boardGame[1][1] && boardGame[0][2] == boardGame[2][0] && boardGame[0][2] == 1)) {
           //x win
            return true;
        }
        for (int i = 0; i < 3; ++i) {
            if (((boardGame[i][0] == boardGame[i][1] && boardGame[i][0] == boardGame[i][2] && boardGame[i][0] == 1)
                    || (boardGame[0][i] == boardGame[1][i] && boardGame[0][i] == boardGame[2][i] && boardGame[0][i] == 1))) {
                //  x win
                return true;
            }
        }
        return false;
    }

    public boolean isOWon() {
        if ((boardGame[0][0] == boardGame[1][1] && boardGame[0][0] == boardGame[2][2] && boardGame[0][0] == 2) || (boardGame[0][2] == boardGame[1][1] && boardGame[0][2] == boardGame[2][0] && boardGame[0][2] == 2)) {
            //o win
            return true;
        }
        for (int i = 0; i < 3; ++i) {
            if ((boardGame[i][0] == boardGame[i][1] && boardGame[i][0] == boardGame[i][2] && boardGame[i][0] == 2)
                    || (boardGame[0][i] == boardGame[1][i] && boardGame[0][i] == boardGame[2][i] && boardGame[0][i] == 2)) {
                //  o win
                return true;
            }
        }

        return false;
    }

    public List<Point> getAvailableStates() {
        availablePoints = new ArrayList<>();
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                if (boardGame[i][j] == 0) { // trang thai do dang rong
                    availablePoints.add(new Point(i, j));
                }
            }
        }
//        for(int i = 0 ; i < availablePoints.size() ; i++)
//        {
//            System.out.println(availablePoints.get(i).toString()+"\n");
//        }
        return availablePoints;
    }

    public void placeAMove(Point point, int player) {
        boardGame[point.x][point.y] = player;   //player = 1 for X, 2 for O
    }



    public void displayBoard() {
        System.out.println();

        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                System.out.print(boardGame[i][j] + " ");
            }
            System.out.println();

        }
    }


   
    Point computersMove;
    
    
    public int minimax(int depth, int turn) {  
        if (isXWon()) return +1; //X won
        if (isOWon()) return -1; // O won

        List<Point> pointsAvailable = getAvailableStates();
        if (pointsAvailable.isEmpty()) return 0; //draw
 
        int min = Integer.MAX_VALUE;
        int max = Integer.MIN_VALUE;
      
         
        for (int i = 0; i < pointsAvailable.size(); ++i) {  
            Point point = pointsAvailable.get(i);   
            if (turn == 1) { // human , X
            //    System.out.println("turn =1");
                placeAMove(point, 1); 
                int currentScore = minimax(depth + 1, 2);
                max = Math.max(currentScore, max);
                if(depth == 0)System.out.println("position ("+pointsAvailable.get(i).x+", "+pointsAvailable.get(i).y+") = "+currentScore);
                if(currentScore >= 0){ if(depth == 0) computersMove = point;} 
                if(currentScore == 1){boardGame[point.x][point.y] = 0; break;} 
                if(i == pointsAvailable.size()-1 && max < 0){if(depth == 0) computersMove = point;}
            //    System.out.println("MAX = "+max);
            } else if (turn == 2) { // computer , 2
            //    System.out.println("turn =2");
                placeAMove(point, 2); 
                int currentScore = minimax(depth + 1, 1);
                min = Math.min(currentScore, min); 
                if(min == -1){boardGame[point.x][point.y] = 0; break;}
              //  System.out.println("Min = "+min);
            }
            boardGame[point.x][point.y] = 0; //Reset this point
        } 
      //  System.out.println("return : "+ (turn == 1?max:min));
        return turn == 1?max:min;
    }  
    
  //Functions for GUI
    public int returnNextMove() {
        if (isGameOver()) return -1;
        minimax(0, 1); 
        return computersMove.x * 3 + computersMove.y;
    }
    
    public void resetBoard(){
        for(int i = 0;i<3;++i)
            for(int j=0;j<3;++j)
                boardGame[i][j] = 0;
    }
}



//Class GUI - MAIN

public class TicTacToe_GUI extends JFrame implements ActionListener, MouseListener{

    JPanel pGame;
    JPanel pControl;
    JPanel plogo;
    JButton  btplay, exit;
    JRadioButtonMenuItem  human , computer;
    int WHO_FIRST = 0;
    BoardGame boardGame = new BoardGame();
    Turn turn  = new Turn();
    GridLayout grid = new GridLayout(3, 3);
    JButton bt1, bt2, bt3, bt4, bt5, bt6, bt7, bt8, bt9;
    JButton button[];
    ImageIcon iX = new ImageIcon("image/x.png");
    ImageIcon iO = new ImageIcon("image/o.jpg");
    public TicTacToe_GUI() {
        setTitle("Nguyen Van Thanh() - DEMO TICTACTOE - ThanhCS94");
        setLayout(new BorderLayout());
        setBackground(Color.WHITE);
        pGame = new JPanel();
        pGame.setBackground(Color.WHITE);
        pGame.setLayout(grid);
        plogo = new JPanel();
        add(pGame, BorderLayout.CENTER);
        add(plogo, BorderLayout.NORTH);
        plogo.add(new JLabel(new ImageIcon("logo.jpg")));
        pControl = new  JPanel();
        pControl.setLayout(new GridLayout(4, 1));
        JPanel whofirst = new JPanel();
        whofirst.add(human = new JRadioButtonMenuItem ("I'm first")); 
        human.setBackground(Color.WHITE);
        whofirst.add(computer = new JRadioButtonMenuItem ("You first")); 
        computer.setBackground(Color.WHITE);
        ButtonGroup a = new ButtonGroup();
        a.add(human);
        a.add(computer);
        human.setSelected(true);
        
        pGame.setVisible(false);
        pControl.add(whofirst);
        pControl.setBackground(Color.WHITE);
        whofirst.setBackground(Color.WHITE);
        pControl.add(btplay = new  JButton());
        pControl.add(exit = new  JButton());
        btplay.setIcon(new ImageIcon("play.png"));
        exit.setIcon(new ImageIcon("ecit.jpg"));
        btplay.setOpaque(false);
        btplay.setContentAreaFilled(false);
        btplay.setBorderPainted(false);
        
        exit.setOpaque(false);
        exit.setContentAreaFilled(false);
        exit.setBorderPainted(false);
        btplay.addActionListener(this);
        exit.addActionListener(this);
        add(pControl, BorderLayout.EAST);
        setButton();
    

         
        for(final JButton bt : button)
        {
            bt.addActionListener(new  ActionListener() {
                
                @Override
                public void actionPerformed(ActionEvent e) {
                    

                    if(bt.getName().equalsIgnoreCase(""))
                    {
                    int indext = -1;
                    for(int i = 0  ; i < button.length ; i++)
                    {
                        if(bt ==  button[i])
                        {
                            indext =i;
                            System.out.println("position : "+indext);
                            button[i].setIcon(new ImageIcon("image/x.png"));
                        }
                    }
                    
                    
                    
                    boardGame.placeAMove(new Point(indext/3, indext%3), 2);
                    boardGame.displayBoard();
                    System.out.println("Placed a move at: (" + indext/ 3 + ", " + indext % 3 + ")");
                    boolean mark = true;
                    int next = boardGame.returnNextMove();
                    
                    if (next != -1) {   //If the game isn't finished yet!   
                        int indexCell = next;

                        button[indexCell].setIcon(new ImageIcon("image/o.jpg"));
                        button[indexCell].setName("1");//used
                      //  button[indexCell].setUserData(mark); //Used!
                     //   System.out.println("Computer has evaluated the next move! " + indexCell);
                        boardGame.placeAMove(new Point(indexCell / 3, indexCell % 3), 1);
                       bt.setName("1");
                    }
                    
                    
                    if (boardGame.isGameOver()) {
                       
                        if (boardGame.isXWon()) {

                            JOptionPane.showMessageDialog(null, "You lost");
                            boardGame.resetBoard();
                            boardGame.displayBoard();
                            setVisible(false);
                            new TicTacToe_GUI();
                            
                        } else {
                            JOptionPane.showMessageDialog(null, "Draw");
                            boardGame.resetBoard();
                            boardGame.displayBoard();
                            setVisible(false);
                            new TicTacToe_GUI();
                        }
                        

                    }
                    
                    }
                    
                }
            });
            
            
               
            
        }
        
        int x=this.getToolkit().getScreenSize().width/2-200;
        int y=this.getToolkit().getScreenSize().height/2-200;
        setLocation(x,y);
        setSize(400, 450);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
        
    }
    
    private void setButton() {
        bt1 = new  JButton(); bt1.setName("");
        bt2 = new  JButton();bt2.setName("");
        bt3 = new  JButton();bt3.setName("");
        bt4 = new  JButton();bt4.setName("");
        bt5 = new  JButton();bt5.setName("");
        bt6 = new  JButton();bt6.setName("");
        bt7 = new  JButton();bt7.setName("");
        bt8 = new  JButton();bt8.setName("");
        bt9 = new  JButton();bt9.setName("");
        
        
        button= new JButton[9];
        JButton bt[] = {bt1, bt2, bt3, bt4, bt5, bt6, bt7, bt8, bt9};
        
        for(int i  = 0 ; i < button.length ;i++)
        {
            button[i] = bt[i];
            button[i].setBackground(Color.WHITE);
            pGame.add(button[i]);
        }
        
    }

    public static void main(String[] args) {
        
        new TicTacToe_GUI();
    }

    
    @Override
    public void mouseClicked(MouseEvent e) {
        
        
    }

    @Override
    public void mousePressed(MouseEvent e) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource()==btplay)
        {
            WHO_FIRST =  getFirst();
            if(WHO_FIRST==1)//danh truoc
            {
                turn.next = Turn.NextMove.O;
                pControl.setVisible(false);
                pGame.setVisible(true);
            
            }
            if(WHO_FIRST==2)//computer
            {
                
                 pControl.setVisible(false);
                 pGame.setVisible(true);
                 int index = new Random().nextInt(9);
                 button[index].setIcon(new ImageIcon("image/o.jpg"));
                 button[index].setName("1");
                 boardGame.placeAMove(new Point(index / 3, index % 3), 1);
                 turn.next = Turn.NextMove.X;
                 
            }
        }
        if(e.getSource()==exit)
        {
            System.exit(0);
        }
        
    }

    private int getFirst() {
        if(human.isSelected())
            return 1;
        else if(computer.isSelected())
            return 2;
        return 0;
    }
}



1 comment:

Powered by Blogger.