public static LinkedList<Move> solve(int[][] board) throws NoMoveException {
        boolean[][] localUsedBoard = new boolean[8][8];
        //List of moves to return
        LinkedList<Move> localMoves = new LinkedList<Move>();
        LinkedList<Move> moves = new LinkedList<Move>();
        //Right and down moves
        Move rightMove, downMove;
        //Initial local scoring
        int rightScore = 0, downScore = 0, moveScore = 0;
        //Max score and the max associate move
        int diffScore = 0;
        //Base score
        int baseScore = Board.scoreAll(board);
        //Max calculated score
        int maxScore = baseScore;

        for (int i = 0; i < 7; i++) {
            for (int j = 0; j < 7; j++) {
                rightScore = makeMoveScore(board, rightMove = new Move(j, i, j + 1, i), localUsedBoard);
                downScore = makeMoveScore(board, downMove = new Move(j, i, j, i + 1), localUsedBoard);
                if (Math.max(rightScore, downScore) >= 3) {
                    if (rightScore > downScore) {
                        rightMove.score = rightScore;
                        localMoves.add(rightMove);
                    } else {
                        downMove.score = downScore;
                        localMoves.add(downMove);
                    }
                }
            }
        }

        Collections.sort(localMoves, new ScoreComparator());

        for (Move currentMove : localMoves) {
            moveScore = makeMoveScoreAll(board, currentMove);
            diffScore = moveScore - maxScore;
            if (diffScore > 0) {
                maxScore = moveScore;
                board = Board.swapGems(board, currentMove.x1, currentMove.y1, currentMove.x2, currentMove.y2);
                moves.add(currentMove);
            }
        }

        if (moves.size() > 0) {
            Collections.sort(moves, new InvYComparator());
            return moves;
        }

        throw new NoMoveException();
    }