public Sudoku(boolean autoPossBasic, boolean autoPossAdvanced,
            boolean autoFillBasic, boolean autoFillAdvanced, boolean possAsNum,
            boolean initialPoss, int initNumbers, int size,
            final MouseListenerMethod m, int difficulty) {
        super(new GridBagLayout());
        this.size = size;
        this.selectedRow = size*size / 2;
        this.selectedColumn = size*size / 2;
        this.errorRow = size*size / 2;
        this.errorColumn = size*size / 2;
        this.possAsNum = possAsNum;
        if (difficulty == Grid.DIFFICULTY_NONE) {
            this.grid = Grid.generate(autoPossBasic, autoPossAdvanced,
                    autoFillBasic, autoFillAdvanced, initialPoss,
                    initNumbers, size);
        } else {
            this.grid = Grid.uniqueGen(autoPossBasic, autoPossAdvanced,
                    autoFillBasic, autoFillAdvanced, initialPoss,
                    difficulty, size);
        }
        this.label = new JLabel[size*size][size*size];
        this.containsValue = new boolean[size*size][size*size];
        
        GridBagConstraints c = new GridBagConstraints();
        for (int i = 0; i < size*size; i++) {
            for (int j = 0; j < size*size; j++) {
                label[i][j] = new JLabel();
                label[i][j].setPreferredSize(new Dimension(50, 50));
                label[i][j].setOpaque(true);
                label[i][j].setBackground(new Color(255, 255, 191));
                label[i][j].setHorizontalAlignment(JLabel.CENTER);
                if (grid.isEditable(i, j)) {
                    label[i][j].setFont(FONT_POSS);
                    label[i][j].setForeground(COLOR_POSS);
                } else {
                    label[i][j].setForeground(COLOR_UNEDITABLE);
                    label[i][j].setFont(FONT_UNEDITABLE);
                }
                
                int top = i > 0 && i % size == 0? 2 : 0;
                int left = j > 0 && j % size == 0? 2 : 0;
                label[i][j].setBorder(new CompoundBorder(
                        new MatteBorder(top, left, 0, 0, Color.black),
                                new CompoundBorder(new LineBorder(Color.black, 1),
                                                   new EmptyBorder(1, 1, 1, 1))));
                
                final int fi = i, fj = j;
                label[i][j].addMouseListener(new MouseAdapter() {
                    @Override
                    public void mousePressed(MouseEvent e) {
                        select(fi, fj);
                        m.exec(e);
                    }
                });
                c.gridx = j;
                c.gridy = i;
                add(label[i][j], c);
                containsValue[i][j] = grid.value(i, j) != 0;
            }
        }
        
        select(selectedRow, selectedColumn);
        refresh();
    }