0

I'm trying to make an Othello AI, currently trying to implement MiniMax. I've created a board object, from the current board I want to create a list of all "child" boards, these are copies of the current board but with each having one legal move applied to them. I'm having an issue creating multiple "child" boards, so far my code is applying all of the legal moves to just one board and only having that single board in the children board list. Any help would be much appreciated.

minimax method in the MiniMax class

       public static void minimax(){
    
 
   
            ArrayList<int[]> legalMoves;
            legalMoves = gameHandler.potentialMovesList();
            int min = -1000;
            int max = 1000;
    
            //-----legal moves list-----
            char disc;
            if (Main.blackTurn = true){
                disc = 'b';
            }
            else {
                disc = 'w';
            }
    
            int count = 0;
            
            for (int[] i : legalMoves) {
                System.out.println(i[0] + " " + i[1]);
    
                ArrayList<board> children = board.addChild(Main.grid, i, disc, count);
                count++;
            }
            //-------------------------
    
    
    //        ----------children list-----------;
    ////        for (int x = 0; x < board.getChildren().size(); x++){
    ////            System.out.println(board.getChildren().get(x));
    ////        }
    //        -------------------------
    
            //-----------list scores----------
            int maxIndex = 0;
            int maxBoardVal = 0;
    
            for (int i =0; i < board.getChildren().size() ; i++){
    
                if (board.getChildren().get(i).getBoardVal() > maxBoardVal){
                    maxBoardVal = board.getChildren().get(i).getBoardVal();
                    maxIndex = i;
                }
                System.out.println(board.getChildren().get(i).getBoardVal()); //children only has 1 item in currently
            }
            //-------------------------
    
            int[] coord = legalMoves.get(maxIndex);
            int x = coord[0];
            int y = coord[1];
    
    
            Main.blackTurn = false; //set it to be white turn
    
            System.out.println("minimax move select");
            System.out.println(x);
            System.out.println(y);
            System.out.println("------");
            Main.grid.setMove(new int[]{x, y}, 'w');    //need to change this from 'w' hardcoded to whichever AIs turn it is (both could be ai)
    
            System.out.println("pick: " + x + " " + y);
    
            gameHandler.flipDiscs('w','b',x,y, Main.grid.getBoard());
    
            Main.blackTurn = !Main.blackTurn; //swap back to black (player) turn
    
            //(this is only for one depth), for multiple depth we need to then make a list of all moves
            //from each next ply (after accouting for every move that the opposite colour could make)
        }

public class board {

private static char disc;
private static char[][] gameboard;
private static boolean blackTurn;
private static ArrayList<board> children;
private static int boardEval;

//private static board[] children;
//depth 0 = Main.grid
//depth 1 = Main.grid with a move made

//initializer to make first empty board
public board() {
    gameboard = new char[8][8];
    for (int i = 0; i < 8; i++){
        for (int j = 0; j < 8; j++){
            gameboard[i][j] = ' ';
        }
    }
}

public static void setGameboard(char[][] gameboard) {
    board.gameboard = gameboard;
}

public static void setChildren(ArrayList<board> children) {
    board.children = children;
}

public static ArrayList<board> getChildren(){
    return children;
}

public char[][] getBoard(){
    return gameboard;
}

public boolean getTurn(){
    return blackTurn;
}

public static char getTile(int[] yo) {
    char value = gameboard[yo[0]][yo[1]];
    return value;
}

public static void setMove(int[] coord, char discColour){
    gameboard[coord[0]][coord[1]] = discColour;
}

public static void printBoard(board grid){
   //prints the logical grid in command line
        for (int i =0; i< 8; i++){
            for (int z =0; z< 8; z++){
                System.out.print(grid.getBoard()[z][i]);
                System.out.print("|");
            }
            System.out.println();
            for (int q =0; q< 16; q++) {
                System.out.print("-");
            }
            System.out.println();
        }
        System.out.println("end of grid");
}

public static void initialBoard(board grid){
    for (int i = 0; i < 8; i++){
        for (int j = 0; j < 8; j++){
            int[] yo = {i, j};
            board.setMove(yo, ' ');
        }
    }

    board.setMove(new int[]{3, 3}, 'w');
    board.setMove(new int[]{4, 3}, 'b');
    board.setMove(new int[]{3, 4}, 'b');
    board.setMove(new int[]{4, 4}, 'w');
}

public static int[] getScore(board board){
    int blackScore = 0;
    int whiteScore = 0;
    for (int i = 0; i <= 7; i++){   //iterate over all tiles on board
        for (int j = 0; j <= 7; j++) {

            if (board.getTile(new int[]{i, j}) == 'b'){
                blackScore++;
            }
            else if(board.getTile(new int[]{i, j}) == 'w'){
                whiteScore++;
            }
        }
    }
    int score[] = {blackScore, whiteScore};
    return score;
}

public static ArrayList<board> addChild(board board, int[] move, char discColour, int count{

    board child = board;
    ArrayList<board> children = board.getChildren();
    child.setMove(move, discColour);    //make the move on the child board
    child.setBoardVal(MiniMax.evalFunction(board, Main.blackTurn)); //set value of child
    children.add(child);   //add child to list
    board.setChildren(children);   //set global list to local list

    return children;
}

public static void setBoardVal(int boardVal){
    boardEval = boardVal;
}

public static int getBoardVal(){
    return boardEval;
}
  • Looks like you're creating a new ArrayList `Children` every time with the same board type variable `child` inside the method `addChild`. The first argument in the `addChild` method is always `Main.grid`. Maybe you can re-check on this logic. – Barefooter Feb 14 '22 at 13:46
  • I'm just trying to get it working for 1 move ahead currently, then I'll try to do the recursion to create the full game tree to a given depth. When I remove the declaration of the new ArrayList `Children` (within the addChild method), I get this error: **"Cannot invoke "java.util.ArrayList.add(Object)" because "com.company.othello.board.children" is null"** – Stuart Groom Feb 14 '22 at 17:22
  • I've seen something about doing "board child = parentBoard" creating a hard copy. The pointers of the child point to the same values as the parent, so if either has values changed it applies to the other. I've found the clone method which can be used to create a soft copy which won't have this issue. – Stuart Groom Feb 17 '22 at 12:47

0 Answers0