src/ai/MiniMaxAI.java
public Move maxAlphaBeta(Board board, int depth, double a, double b) {
        Random r = new Random();

        /* If MAX is called on a state that is terminal or after a maximum depth is reached,
         * then a heuristic is calculated on the state and the move returned.
         */
        if ((board.checkForGameOver()) || (depth == maxDepth)) {
            Move lastMove = new Move(board.getLastMove().getRow(), board.getLastMove().getColumn(), board.evaluate());
            return lastMove;
        }
        // The children-moves of the state are calculated
        ArrayList<Board> children = new ArrayList<Board>(board.getChildren(Constants.P1));
        Move maxMove = new Move(Integer.MIN_VALUE);
        for (Board child : children) {
            // And for each child min is called, on a lower depth.
            Move move = minAlphaBeta(child, depth + 1, a, b);
            // The child-move with the greatest value is selected and returned by max.
            if (move.getValue() >= maxMove.getValue()) {
                if ((move.getValue() == maxMove.getValue())) {
                    // If the heuristic has the same value, then we randomly choose one of the two moves.
                    if (r.nextInt(2) == 0) {
                        maxMove.setRow(child.getLastMove().getRow());
                        maxMove.setColumn(child.getLastMove().getColumn());
                        maxMove.setValue(move.getValue());
                    }
                } else {
                    maxMove.setRow(child.getLastMove().getRow());
                    maxMove.setColumn(child.getLastMove().getColumn());
                    maxMove.setValue(move.getValue());
                }
            }

            // Beta pruning.
            if (maxMove.getValue() >= b) {
                // System.out.println("Beta pruning: " + b);
                return maxMove;
            }

            // Update the a of the current max node.
            a = (a > maxMove.getValue()) ? a : maxMove.getValue();
        }
        return maxMove;
    }
// The max and min functions are called interchangeably, one after another until a max depth is reached.
The max and min functions are called interchangeably, one after another until a max depth is reached.
The max and min functions are called interchangeably one after another until a max depth is reached .
public Move maxAlphaBeta(Board board, int depth, double a, double b) {
        Random r = new Random();
        /* If MAX is called on a state that is terminal or after a maximum depth is reached,
         * then a heuristic is calculated on the state and the move returned.
         */
        if ((board.checkForGameOver()) || (depth == maxDepth)) {
            Move lastMove = new Move(board.getLastMove().getRow(), board.getLastMove().getColumn(), board.evaluate());
            return lastMove;
        }
        ArrayList<Board> children = new ArrayList<Board>(board.getChildren(Constants.P1));
        Move maxMove = new Move(Integer.MIN_VALUE);
        for (Board child : children) {
            Move move = minAlphaBeta(child, depth + 1, a, b);
            if (move.getValue() >= maxMove.getValue()) {
                if ((move.getValue() == maxMove.getValue())) {
                    if (r.nextInt(2) == 0) {
                        maxMove.setRow(child.getLastMove().getRow());
                        maxMove.setColumn(child.getLastMove().getColumn());
                        maxMove.setValue(move.getValue());
                    }
                } else {
                    maxMove.setRow(child.getLastMove().getRow());
                    maxMove.setColumn(child.getLastMove().getColumn());
                    maxMove.setValue(move.getValue());
                }
            }
            if (maxMove.getValue() >= b) {
                return maxMove;
            }
            a = (a > maxMove.getValue()) ? a : maxMove.getValue();
        }
        return maxMove;
    }
public Move maxAlphaBeta ( Board board , int depth , double a , double b ) { Random r = new Random ( ) ; /* If MAX is called on a state that is terminal or after a maximum depth is reached,
         * then a heuristic is calculated on the state and the move returned.
         */ if ( ( board . checkForGameOver ( ) ) || ( depth == maxDepth ) ) { Move lastMove = new Move ( board . getLastMove ( ) . getRow ( ) , board . getLastMove ( ) . getColumn ( ) , board . evaluate ( ) ) ; return lastMove ; } ArrayList < Board > children = new ArrayList < Board > ( board . getChildren ( Constants . P1 ) ) ; Move maxMove = new Move ( Integer . MIN_VALUE ) ; for ( Board child : children ) { Move move = minAlphaBeta ( child , depth + 1 , a , b ) ; if ( move . getValue ( ) >= maxMove . getValue ( ) ) { if ( ( move . getValue ( ) == maxMove . getValue ( ) ) ) { if ( r . nextInt ( 2 ) == 0 ) { maxMove . setRow ( child . getLastMove ( ) . getRow ( ) ) ; maxMove . setColumn ( child . getLastMove ( ) . getColumn ( ) ) ; maxMove . setValue ( move . getValue ( ) ) ; } } else { maxMove . setRow ( child . getLastMove ( ) . getRow ( ) ) ; maxMove . setColumn ( child . getLastMove ( ) . getColumn ( ) ) ; maxMove . setValue ( move . getValue ( ) ) ; } } if ( maxMove . getValue ( ) >= b ) { return maxMove ; } a = ( a > maxMove . getValue ( ) ) ? a : maxMove . getValue ( ) ; } return maxMove ; }
The max and min functions are called interchangeably, one after another until a max depth is reached.
The max and min functions are called interchangeably one after another until a max depth is reached .
// The children-moves of the state are calculated // And for each child min is called, on a lower depth. // The child-move with the greatest value is selected and returned by max. // If the heuristic has the same value, then we randomly choose one of the two moves. // Beta pruning. // System.out.println("Beta pruning: " + b); // Update the a of the current max node.