public Map<String, Integer> alphabeta(Model model, int depth, int alpha, int beta, String player){
		
        Map<String, Integer> result = new HashMap<>();
        
        Integer bestDirection = null;
        int bestScore;
        
        if(gameTerminated(model)) {
            if(model.isSucceed()) {
                bestScore = Integer.MAX_VALUE; //highest possible score
            }
            else {
                bestScore = Math.min(model.getScore(), 1); //lowest possible score
            }
        }
        else if(depth == 0) {
            bestScore = heuristicScore(model.getScore(), numOfemptyCellsFoo(model), calculateClusteringScore(model.getData()));
        }
        else {
            if(player.equals(user)) {
                for(int i = 1; i < 5; i++) {
                    Model copyModel = new Game2048Model((Game2048Model)model);
                    int pointsBeforeMove = model.getScore();
                    int points = 0;
                    
                    if(i == 1){
                    	if(copyModel.moveUp()){
	                    	int pointsAfterMove = copyModel.getScore();
	                    	points = pointsAfterMove - pointsBeforeMove;
                    	}
                    }
                    else if(i == 2){
                    	if(copyModel.moveDown()){
	                    	int pointsAfterMove = copyModel.getScore();
	                    	points = pointsAfterMove - pointsBeforeMove;
                    	}
                    }
                    else if(i == 3){
                    	if(copyModel.moveRight()){
	                    	int pointsAfterMove = copyModel.getScore();
	                    	points = pointsAfterMove - pointsBeforeMove;
                    	}
                    }
                    else if(i == 4){
                    	if(copyModel.moveLeft()){
	                    	int pointsAfterMove = copyModel.getScore();
	                    	points = pointsAfterMove - pointsBeforeMove;
                    	}
                    }
                    
                    if(points == 0 && isEqual(model.getData(), copyModel.getData())) {
                    	continue;
                    }
                    
                    Map<String, Integer> currentResult = alphabeta(copyModel, depth - 1, alpha, beta, computer);
                    int currentScore = ((Number)currentResult.get("Score")).intValue();
                                        
                    if(currentScore > alpha) { //maximize score
                        alpha = currentScore;
                        bestDirection = i;
                    }
                    
                    if(beta <= alpha) {
                        break; //beta cutoff
                    }
                }
                
                bestScore = alpha;
            }
            else {
                List<Integer> moves = getEmptyCellIds(model.getData());
                int[] possibleValues = {2, 4};

                int i,j;
                abloop: for(Integer cellId : moves) {
                    i = cellId/model.getData().length;
                    j = cellId%((model.getData()[0]).length);

                    for(int value : possibleValues) {
                        Model copyModel = new Game2048Model((Game2048Model)model);
                     	setEmptyCell(copyModel, i, j, value);

                        Map<String, Integer> currentResult = alphabeta(copyModel, depth - 1, alpha, beta, user);
                        int currentScore = ((Number)currentResult.get("Score")).intValue();
                        if(currentScore < beta) { //minimize best score
                            beta = currentScore;
                        }
                        
                        if(beta <= alpha) {
                            break abloop; //alpha cutoff
                        }
                    }
                }
                
                bestScore = beta;
                
                if(moves.isEmpty()) {
                    bestScore = 0;
                }
            }
        }
        
        //System.out.println("Score" + bestScore + "," + "Direction" + "," + bestDirection);
        result.put("Score", bestScore);
        result.put("Direction", bestDirection);
        return result;
    }