Реализация разумной эвристики Шекера с алгоритмом Negamax - PullRequest
0 голосов
/ 01 октября 2018

Итак, я пытался создать ИИ, способный выигрывать во многих играх в шашки, проблема в том, что реализация, которую я сделал сейчас, кажется неэффективной для памяти, и я получаю такие предупреждения, как:

Исключение в потоке "main" java.lang.OutOfMemoryError: Куча Javaв состоянии рассчитать каждый возможный ход может быть.В настоящее время я сделал следующее:

import java.util.*;

public class Player {
    static int myPlayer = 0;
    static int opponentPlayer = 0;

    public GameState play(final GameState pState, final Deadline pDue) {
        /*
         * introducing neccessary constants
         */
        myPlayer = pState.getNextPlayer();
        double alpha = Double.NEGATIVE_INFINITY;
        double beta = Double.POSITIVE_INFINITY;
        Node root = new Node(Double.NEGATIVE_INFINITY, pState);
        int depth = 0;
        double v = -10;
        Calculator calculator = new Calculator(opponentPlayer, myPlayer);
        Vector<GameState> nextStates = new Vector<GameState>();
        pState.findPossibleMoves(nextStates);
        /*
         * creating a node with pState as state
         */
        Node nodeToStoreFirstState = new Node(v, pState);
        Node interestingNode = null;
        if(myPlayer == Constants.CELL_RED) {
            opponentPlayer = Constants.CELL_WHITE;
        }
        else {
            opponentPlayer = Constants.CELL_RED;
        }


        if (nextStates.size() == 0) {
            // Must play "pass" move if there are no other moves possible.
            return new GameState(pState, new Move());
        }
        else {
            negaMax(nodeToStoreFirstState, depth, alpha, beta, myPlayer, root, calculator);
            interestingNode = root.findingHighestValue();
            return interestingNode.getState();

        }
    }



    public static Vector<Node> calculationFirstMove(GameState pState, int myPlayer, int opponentPlayer) {
        /*
         * heuristics for first moves,
         * check right and left moves, rewarding them with different v
         */ 
        // sätt Constants.CELL_RED till myPlayer och Constnats.CELL_WHITE till opponentPLayer
        Vector<GameState> lNextStates = new Vector<GameState>();
        pState.findPossibleMoves(lNextStates);
        Vector<Node> nodesStored = new Vector<Node>();
        for(GameState state : lNextStates) {
            double v = 0;
            Node storingValue = new Node(v, state);
            for(int row = 0; row < GameState.NUMBER_OF_SQUARES; row++) {
                for(int col = 0; col < GameState.NUMBER_OF_SQUARES; col++) {
                    if(pState.get(row, col) == myPlayer) {
                        if(pState.get(row+1, col+1) == opponentPlayer) {
                            if(pState.get(row + 2, col + 2 ) == Constants.CELL_EMPTY) {
                                v = v + 30;
                                if(pState.get(row + 3, col + 3) == opponentPlayer) {
                                    if(pState.get(row + 4, col + 4) == Constants.CELL_EMPTY){
                                        v = v + 100;
                                    }
                                }
                            }
                        }

                    }
                    // sätt Constants.CELL_RED till myPlayer och Constnats.CELL_WHITE till opponentPLayer
                    if(pState.get(row, col) == myPlayer) {
                        if(pState.get(row+1, col-1) == opponentPlayer) {
                            if(pState.get(row + 2, col -2) == Constants.CELL_EMPTY) {
                                v = 30;
                                if(pState.get(row + 3, col - 3) == opponentPlayer) {
                                    if(pState.get(row + 4, col - 4) == Constants.CELL_EMPTY){
                                        v = 100;
                                    }
                                }
                            }
                        }

                    }
                }
            }
            storingValue.setValue(v);
            nodesStored.add(storingValue);
        }
        return nodesStored;
        }

    public static Vector<Node> setNodesInOrder(GameState pState) {
        Vector<Node> nodesStored = calculationFirstMove(pState, myPlayer, opponentPlayer);
        Node currentLargestNode = nodesStored.get(0);
        for(int child = 1; child < nodesStored.size(); child ++) {
            Node comparingNode = nodesStored.get(child);
            Node largestNode = currentLargestNode.compareTo(comparingNode);
            nodesStored.add(largestNode);
        }
        return nodesStored;
    }


    public double negaMax(Node node, int depth, double alpha, double beta, int currentPlayer, Node root, Calculator calculator) {
        double v = 0;
        Vector<Node> nodesInOrder = Player.setNodesInOrder(node.getState());
        if(depth == 0 || nodesInOrder.size() == 0) {
            //v = calculator.totsum  // implementera heuristik som vanligt
            //v = calculator.heuristics(node.getState());
            v = nodesInOrder.elementAt(0).getValue();
            Node state = new Node(v, node.getState());
            state.setParent(root);
        }

        else if(currentPlayer == myPlayer) {
            v = Double.NEGATIVE_INFINITY;
            for(Node child : nodesInOrder) {
                Node newNode = new Node(v, child.getState());
                root.setChild(newNode);
                newNode.setParent(root);
                v = Math.max(v, negaMax(child, depth -1, alpha, beta, opponentPlayer, root, calculator));
                newNode.setValue(v);
                alpha = Math.max(alpha, v);
                if(beta <= alpha) {
                    break;
                }
            }
        }
        else {
            v = Double.POSITIVE_INFINITY;
            for(Node child : nodesInOrder) {
                Node newNode = new Node(v, child.getState());
                root.setChild(newNode);
                newNode.setParent(root);
                v = Math.min(v, negaMax(child, depth-1, alpha, beta, myPlayer, root, calculator));
                newNode.setValue(v);
                beta = Math.min(beta, v);
                if(beta <= alpha) {
                    break;
                }
            }
        }
        return v;   
    }
}

Это куча кода, я знаю об этом, и поэтому я в основном пишу свой вопрос так же, как и я, ожидаю, что мой метод CalculationFirstMove будет оченьнеэффективно, я думаю, что я нахожусь в положении, когда мне нужна помощь, чтобы пойти с этой точки.Заранее спасибо!

...