TicTacToe AI Java

26,774

Solution 1

So I thought i'd come back after finding the old code I did for this and answer how I did it.

It's probably still far from perfect but it's very close.

I started with a very simple class of player which would get and set markers.

public class player {

    public String Marker;

    // set marker method

    public void setMarker(String marker){

        Marker = marker;

    }

    //get marker method 

    public String getMarker(){

        return Marker;

    }

}

I then added a set class which would set up and print the board after each move.

import java.util.Random;
import java.util.Scanner;



public class set {

    // setup variables default board size and board
    private int N = 3;
    public String[][] board = new String [N][N];

    public boolean hasWon (String [] [] board){
        //horizontal 
        for(int i = 0; i<3; i++){
            if(board[i][0].equals(board[i][1]) && board[i][1].equals(board[i][2])){
                return true;
            }
        }
        //vertical
        for(int i = 0; i<3; i++){
            if(board [0][i].equals(board[1][i]) && board[1][i].equals(board[2][i])){
                return true;
            }
        }
        //diagonal
        if(board[0][0].equals(board[1][1]) && board[1][1].equals(board[2][2]) || board[2][0].equals(board[1][1]) && board[1][1].equals(board[0][2]))
            return true;
        return false;
    }


    int x = 1;

    public void createBoard(){
        for(int i = 0; i < board.length; i++){
            for(int j = 0; j < board.length; j++){
                board[i][j] = "" + (x);
                x++;
            }
        }
    }

    public void printBoard(){

        for(int i = 0; i < board.length; i++){
            for(int j = 0; j < board.length; j++){
                System.out.print("[" + board[i][j] + "]" + " ");

            }
            System.out.println();
        }

    }

    public String[][] getBoard(){

        return board;

    }



}

The Computer class with AI.

class Computer extends player {

public Computer(){

}

int boardsize = 3;


public void takeTurn(String[][] board, Human human) {

    int vertical = 0;
    int horizontal = 0;
    int diagonal = 0;
    boolean mademove = false;

    // check if you can take a win horizontally
    for(int i = 0; i<3; i++){

        if(board[0][i].equals(board[1][i]) && board[0][i].equals(Marker)){

            if(board[2][i] != human.getMarker() && board[2][i] != Marker){
                board[2][i] = Marker;
                mademove = true;
                return;
            }

        }

    }

    for(int i = 0; i<3; i++){

        if(board[2][i].equals(board[1][i]) && board[2][i].equals(Marker)){

            if(board[0][i] != human.getMarker() && board[0][i] != Marker){
                board[0][i] = Marker;
                mademove = true;
                return;
            }

        }


    }



    // check if you can take a win horizontally
    for(int i = 0; i<3; i++){

        if(board[i][0].equals(board[i][1]) && board[i][0].equals(Marker)){

            if(board[i][2] != human.getMarker() && board[i][2] != Marker){
                board[i][2] = Marker;
                mademove = true;
                return;
            }

        }

    }

    for(int i = 0; i<3; i++){

        if(board[i][2].equals(board[i][1]) && board[i][2].equals(Marker)){

            if(board[i][0] != human.getMarker() && board[i][0] != Marker){
                board[i][0] = Marker;
                mademove = true;
                return;
            }

        }

    }


    // check if you can take a win diagonally bottom


    if(board[0][0].equals(board[1][1]) && board[0][0].equals(Marker)){

        if(board[2][2] != human.getMarker() && board[2][2] != Marker){
            board[2][2] = Marker;
            mademove = true;
            return;
        }
    }

    if(board[2][2].equals(board[1][1]) && board[2][2].equals(Marker)){

        if(board[0][0] != human.getMarker() && board[0][0] != Marker){
            board[0][0] = Marker;
            mademove = true;
            return;
        }
    }

    if(board[0][0].equals(board[1][1]) && board[0][0].equals(Marker)){

        if(board[2][2] != human.getMarker() && board[2][2] != Marker){
            board[2][2] = Marker;
            mademove = true;
            return;
        }
    }

    if(board[0][2].equals(board[1][1]) && board[0][2].equals(Marker)){

        if(board[2][0] != human.getMarker() && board[2][0] != Marker){
            board[2][0] = Marker;
            mademove = true;
            return;
        }
    }

    if(board[2][0].equals(board[1][1]) && board[2][0].equals(Marker)){

        if(board[0][2] != human.getMarker() && board[0][2] != Marker){
            board[0][2] = Marker;
            mademove = true;
            return;
        }
    }


    // BLOCKS!!!! //

    // check if you can block a win horizontally
    for(int i = 0; i<3; i++){

        if(board[0][i].equals(board[1][i]) && board[0][i].equals(human.getMarker())){
            if(board[2][i] != Marker && board[2][i] != human.getMarker()){
                board[2][i] = Marker;
                mademove = true;
                return;
            }

        }

    }

    for(int i = 0; i<3; i++){

        if(board[2][i].equals(board[1][i]) && board[0][i].equals(human.getMarker())){

            if(board[0][i] != Marker && board[0][i] != human.getMarker()){
                board[0][i] = Marker;
                mademove = true;
                return;
            }

        }


    }

    // check if you can block a win vertically


    for(int i = 0; i<3; i++){

        if(board[i][0].equals(board[i][1]) && board[i][0].equals(human.getMarker())){

            if(board[i][2] != Marker && board[i][2] != human.getMarker()){
                board[i][2] = Marker;
                mademove = true;
                return;
            }

        }

    }

    for(int i = 0; i<3; i++){

        if(board[i][2].equals(board[i][1]) && board[i][2].equals(human.getMarker())){

            if(board[i][0] != Marker && board[i][0] != human.getMarker()){
                board[i][0] = Marker;
                mademove = true;
                return;
            }

        }

    }

    for(int i = 0; i<3; i++){

        if(board[2][i].equals(board[1][i]) && board[2][i].equals(human.getMarker())){

            if(board[0][i] != Marker && board[0][i] != human.getMarker()){
                board[0][i] = Marker;
                mademove = true;
                return;
            }

        }

    }



    // check if you can block a win diagonally 


    if(board[0][0].equals(board[1][1]) && board[0][0].equals(human.getMarker())){

        if(board[2][2] != Marker && board[2][2] != human.getMarker()){
            board[2][2] = Marker;
            mademove = true;
            return;
        }
    }

    if(board[2][2].equals(board[1][1]) && board[2][2].equals(human.getMarker())){

        if(board[0][0] != Marker && board[0][0] != human.getMarker()){
            board[0][0] = Marker;
            mademove = true;
            return;
        }
    }

    if(board[0][0].equals(board[1][1]) && board[0][0].equals(human.getMarker())){
        if(board[2][2] != Marker && board[2][2] != human.getMarker()){
            board[2][2] = Marker;
            mademove = true;
            return;
        }
    }

    if(board[0][2].equals(board[1][1]) && board[0][2].equals(human.getMarker())){

        if(board[2][0] != Marker && board[2][0] != human.getMarker()){
            board[2][0] = Marker;
            mademove = true;
            return;
        }
    }

    if(board[2][0].equals(board[1][1]) && board[2][0].equals(human.getMarker())){

        if(board[0][2] != Marker && board[0][2] != human.getMarker()){
            board[0][2] = Marker;
            mademove = true;
            return;
        }
    }




    // make random move if above rules dont apply
    int rand1 = 0;
    int rand2 = 0;

    while(!mademove){

        rand1 = (int) (Math.random() * 3);
        rand2 = (int) (Math.random() * 3);

        if(board[rand1][rand2] != "x" && board[rand1][rand2] != "o"){
            board[rand1][rand2] = Marker;
            mademove = true;        

        }

    }


}   

}

Human class

import java.util.Scanner;

class Human extends player {

public Human(){

}


public void takeTurn(String[][] board) {

    Scanner s = new Scanner(System.in);

    boolean turn = true;

    while(turn){
        System.out.println("please enter row");
        int row = s.nextInt();
        System.out.println("please enter col");
        int col = s.nextInt();
        System.out.print("you entered "+row+" "+col);
        System.out.println();
        if(board[row - 1][col - 1] != "x" && board[row - 1][col - 1] != "o"){
            board[row - 1][col - 1] = Marker;
            turn = false;
        } // closes if
        else {
            System.out.println("Already Marker here! please guess again!");
        }
    } // ends while
} // ends method

} // ends class

Finally the playing of the game.

    import java.util.Scanner;

public class play {



    public static void main(String[] args) {


        System.out.println("Welcome to Tickle Tackle Toe!!! :D");
        System.out.println();

        //creat markers
        String marker1 = "x";
        String marker2 = "o";
        boolean playAgain = true;

        Scanner s = new Scanner(System.in);



        //create player objects
        Human human = new Human();
        Computer computer = new Computer();

        while(playAgain){
            //run board setup
            set Setup = new set();

            Setup.createBoard();
            Setup.printBoard();

            System.out.println("please choose your marker");
            System.out.println("type 1 for 'x' or 2 for 'o'");

            //set markers
            if(s.nextInt() == 1){
                // create player objects
                human.setMarker("x");
                computer.setMarker("o");
            } 
            else
            {
                human.setMarker("o");
                computer.setMarker("x");

            }




            // determine who goes first
            int first = (int) (Math.random() * 2);





            boolean won = false;
            int turns = 0;

            if(first == 0){
                System.out.println("You gots the winz!");
                System.out.println();
                while(!won){
                    human.takeTurn(Setup.getBoard());
                    turns++;
                    Setup.printBoard();
                    if(Setup.hasWon(Setup.getBoard())){
                        won = true;
                        System.out.println("Congrats you won!");
                    }
                    if(turns == 9){
                        won = true;
                        System.out.println("Its a bore draw!");
                        break;
                    }
                    if(!won){
                        computer.takeTurn(Setup.getBoard(), human);
                        turns++;
                        System.out.println();
                        Setup.printBoard();
                        System.out.println();
                        if(Setup.hasWon(Setup.getBoard())){
                            won = true;
                            System.out.println("You just got pwned by an A.I with an incomplete rule set. FACEPALM.");
                        }
                        if(turns == 9){
                            won = true;
                            System.out.println("Its a bore draw!");
                            break;
                        }
                    }

                }  // close while 1
            }
            else {

                System.out.println("Computer goes first!");
                System.out.println();
                while(!won){
                    computer.takeTurn(Setup.getBoard(), human);
                    turns++;
                    Setup.printBoard();
                    if(Setup.hasWon(Setup.getBoard())){
                        won = true;
                        System.out.println("You just got pwned by an A.I with an incomplete rule set. FACEPALM.");
                    }
                    if(turns == 9){
                        won = true;
                        System.out.println("Its a draw!");
                        break;
                    }
                    if(!won){
                        human.takeTurn(Setup.getBoard());
                        turns++;
                        System.out.println();
                        Setup.printBoard();
                        System.out.println();
                        if(Setup.hasWon(Setup.getBoard())){
                            won = true;
                            System.out.println("You gots the winz!");
                        }
                        if(turns == 9){
                            won = true;
                            System.out.println("Its a draw!");
                            break;
                        }
                    }



                }  // close while 2

            }

            System.out.println("Would you like to play again? Type 1 for yes or 2 to quit");
            System.out.println();
            if(s.nextInt() == 2){
                playAgain = false;
            }

        }

    }
}

Solution 2

If you win by placing the ninth piece, you'll get both the "you won" and "it's a draw!" messages, I don't think that's the intended behavior. Same if you lose on the ninth turn. On the other hand, the draw code is not reached when nobody has won, which is why the game doesn't end. This is easy to fix:

if(!won){
    computer.takeTurn(Setup.getBoard(), human);
    turns++;
    System.out.println();
    Setup.printBoard();
    System.out.println();
    if(Setup.hasWon(Setup.getBoard())){
        won = true;
        System.out.println("You lost!");
    } else if (turns == 9){
        won = true;
        System.out.println("Its a draw!");
    }
}

About making random moves, your current code loops through all nine tiles, places a marker on the first empty spot it encounters and then returns. What you would want is to make a list of all empty spots, and then randomly select one of them. Alternately, keep generating x and y coordinates between 0 and 2, check if it's empty and if so place a marker.

Share:
26,774
andrew-caulfield
Author by

andrew-caulfield

Senior Solutions Engineer @Deloitte Digital

Updated on May 24, 2020

Comments

  • andrew-caulfield
    andrew-caulfield almost 4 years

    So this is a college assignment and everything is pretty much done except the AI doesn't know how to "take the win" and its moves at the start aren't as random as I'd like to be as they always go top corner and work their way down. The assignment only required two rules for the AI in that it could "take the win" or "block the win".

    Also the game doesn't seem to end when the board is filled. It asks me to choose my move.

    I was hoping some people might have suggestions as to how I can improve it or point out where it is I'm going wrong.

    Any help would be greatly appreciated.

    Here is the play

    import java.util.Scanner;
    
    public class play {
    
    
    
        public static void main(String[] args) {
    
    
            System.out.println("Welcome to Tickle Tackle Toe!!! :D");
            System.out.println();
    
            //creat markers
            String marker1 = "x";
            String marker2 = "o";
            boolean playAgain = true;
    
            Scanner s = new Scanner(System.in);
    
    
    
            //create player objects
            Human human = new Human();
            Computer computer = new Computer();
    
            while(playAgain){
            //run board setup
            set Setup = new set();
    
            Setup.createBoard();
            Setup.printBoard();
    
            System.out.println("please choose your marker");
            System.out.println("type 1 for 'x' or 2 for 'o'");
    
            //set markers
            if(s.nextInt() == 1){
             // create player objects
             human.setMarker("x");
             computer.setMarker("o");
            } 
            else
            {
            human.setMarker("o");
            computer.setMarker("x");
    
            }
    
    
    
    
        // determine who goes first
        int first = (int) (Math.random() * 2);
    
    
    
    
    
        boolean won = false;
        int turns = 0;
    
       if(first == 0){
       System.out.println("You go first!");
        System.out.println();
       while(!won){
        human.takeTurn(Setup.getBoard());
        turns++;
        Setup.printBoard();
        if(Setup.hasWon(Setup.getBoard())){
            won = true;
            System.out.println("Congrats you won!");
            }
            if(turns == 9){
            won = true;
            System.out.println("Its a draw!");
            break;
            }
        if(!won){
            computer.takeTurn(Setup.getBoard(), human);
            turns++;
            System.out.println();
            Setup.printBoard();
            System.out.println();
            if(Setup.hasWon(Setup.getBoard())){
                won = true;
                System.out.println("You lost!");
                }
                if(turns == 9){
            won = true;
            System.out.println("Its a draw!");
            break;
            }
            }
    
       }  // close while 1
      }
      else {
    
        System.out.println("Computer goes first!");
        System.out.println();
        while(!won){
        computer.takeTurn(Setup.getBoard(), human);
        turns++;
        Setup.printBoard();
        if(Setup.hasWon(Setup.getBoard())){
            won = true;
            System.out.println("You lost!");
            }
        if(!won){
            human.takeTurn(Setup.getBoard());
            turns++;
            System.out.println();
            Setup.printBoard();
            System.out.println();
            if(Setup.hasWon(Setup.getBoard())){
                won = true;
                System.out.println("Congrats you won!");
                }
            }
    
    
    
       }  // close while 2
    
      }
    
      System.out.println("Would you like to play again? Type 1 for yes or 2 to quit");
       System.out.println();
       if(s.nextInt() == 2){
       playAgain = false;
       }
    
      }
    
    }
    }
    

    And here is the computer class

    class Computer extends player {
    
        public Computer(){
    
        }
    
        int boardsize = 3;
    
    
        public void takeTurn(String[][] board, Human human) {
    
        int vertical = 0;
        int horizontal = 0;
        int diagonal = 0;
        boolean mademove = false;
    
        // check if you can take a win horizontally
        for(int i = 0; i<3; i++){
    
            if(board[0][i].equals(board[1][i]) && board[0][i].equals(Marker)){
    
                if(board[2][i] != human.getMarker()){
                board[2][i] = Marker;
                mademove = true;
                return;
                }
    
            }
    
        }
    
        for(int i = 0; i<3; i++){
    
            if(board[2][i].equals(board[1][i]) && board[2][i].equals(Marker)){
    
                if(board[0][i] != human.getMarker()){
                board[0][i] = Marker;
                mademove = true;
                return;
                }
    
            }
    
    
        }
    
    
            // check if you can take a win vertically
        for(int i = 0; i<3; i++){
    
            if(board[i][0].equals(board[i][1]) && board[i][0].equals(Marker)){
    
                if(board[i][2] != human.getMarker()){
                board[i][2] = Marker;
                mademove = true;
                return;
                }
    
            }
    
        }
    
        for(int i = 0; i<3; i++){
    
            if(board[i][2].equals(board[i][1]) && board[i][2].equals(Marker)){
    
                if(board[i][0] != human.getMarker()){
                board[i][0] = Marker;
                mademove = true;
                return;
                }
    
            }
    
        }
    
    
        // check if you can take a win diagonally 
    
    
            if(board[0][0].equals(board[1][1]) && board[0][0].equals(Marker)){
    
                if(board[2][2] != human.getMarker()){
                board[2][2] = Marker;
                mademove = true;
                return;
                }
        }
    
            if(board[2][2].equals(board[1][1]) && board[2][2].equals(Marker)){
    
                if(board[0][0] != human.getMarker()){
                board[0][0] = Marker;
                mademove = true;
                return;
                }
        }
    
            if(board[0][0].equals(board[1][1]) && board[0][0].equals(Marker)){
    
                if(board[2][2] != human.getMarker()){
                board[2][2] = Marker;
                mademove = true;
                return;
                }
        }
    
            if(board[0][2].equals(board[1][1]) && board[0][2].equals(Marker)){
    
                if(board[2][0] != human.getMarker()){
                board[2][0] = Marker;
                mademove = true;
                return;
                }
        }
    
            if(board[2][0].equals(board[1][1]) && board[2][0].equals(Marker)){
    
                if(board[0][2] != human.getMarker()){
                board[0][2] = Marker;
                mademove = true;
                return;
                }
        }
    
    
        // BLOCKS!!!! //
    
        // check if you can block a win horizontally
        for(int i = 0; i<3; i++){
    
            if(board[0][i].equals(board[1][i]) && board[0][i].equals(human.getMarker())){
                if(board[2][i] != Marker){
                board[2][i] = Marker;
                mademove = true;
                return;
                }
    
            }
    
        }
    
        for(int i = 0; i<3; i++){
    
            if(board[2][i].equals(board[1][i]) && board[0][i].equals(human.getMarker())){
    
                if(board[0][i] != Marker){
                board[0][i] = Marker;
                mademove = true;
                return;
                }
    
            }
    
    
        }
    
    
    
        // check if you can block a win horizontally
        for(int i = 0; i<3; i++){
    
            if(board[i][0].equals(board[i][1]) && board[i][0].equals(human.getMarker())){
    
                if(board[i][2] != Marker){
                board[i][2] = Marker;
                mademove = true;
                return;
                }
    
            }
    
        }
    
        for(int i = 0; i<3; i++){
    
            if(board[i][2].equals(board[i][1]) && board[i][2].equals(human.getMarker())){
    
                if(board[i][0] != Marker){
                board[i][0] = Marker;
                mademove = true;
                return;
                }
    
            }
    
        }
    
    
        // check if you can block a win diagonally 
    
    
            if(board[0][0].equals(board[1][1]) && board[0][0].equals(human.getMarker())){
    
                if(board[2][2] != Marker){
                board[2][2] = Marker;
                mademove = true;
                return;
                }
        }
    
            if(board[2][2].equals(board[1][1]) && board[2][2].equals(human.getMarker())){
    
                if(board[0][0] != Marker){
                board[0][0] = Marker;
                mademove = true;
                return;
                }
        }
    
            if(board[0][0].equals(board[1][1]) && board[0][0].equals(human.getMarker())){
                board[2][2] = Marker;
                mademove = true;
                return;
        }
    
            if(board[0][2].equals(board[1][1]) && board[0][2].equals(human.getMarker())){
    
                if(board[2][0] != Marker){
                board[2][0] = Marker;
                mademove = true;
                return;
                }
        }
    
            if(board[2][0].equals(board[1][1]) && board[2][0].equals(human.getMarker())){
    
                if(board[0][2] != Marker){
                board[0][2] = Marker;
                mademove = true;
                return;
                }
        }
    
    
    
    
             // make random move if above rules dont apply
            for(int i = 0; i<3; i++){
            if(board[i][0] != "x" && board[i][0] != "o"){
                board[i][0] = Marker;
                return;
                }
            }
            for(int i = 0; i<3; i++){
            if(board[i][1] != "x" && board[i][0] != "o"){
                board[i][1] = Marker;
                return;
                }
            }
                for(int i = 0; i<3; i++){
            if(board[i][2] != "x" && board[i][0] != "o"){
                board[i][2] = Marker;
                return;
                }
            }
    
    
        }   
    }