public Iterable<Board> neighbors() {
        Stack<Board> q = new Stack<Board>();

        int md;
        // case 1: blank not in row 0, swap blankIndex and blankIndex-N
        if (blankRow != 0) {
            int row = (tiles[blankIndex - N] - 1) / N;
            if (row <= blankRow - 1) md = this.mdistance + 1;
            else md = this.mdistance - 1;
            q.push(new Board(swap(blankIndex, blankIndex - N),
                        blankRow - 1, blankCol, md));
            //q.push(new Board(swap(blankIndex, blankIndex - N)));
        }

        // case 2: blank not in row N-1, swap blankIndex and blankIndex+N
        if (blankRow != N - 1) {
            int row = (tiles[blankIndex + N] - 1) / N;
            if (row >= blankRow + 1) md = this.mdistance + 1;
            else md = this.mdistance - 1;
            q.push(new Board(swap(blankIndex, blankIndex + N),
                        blankRow + 1, blankCol, md));
            //q.push(new Board(swap(blankIndex, blankIndex + N)));
        }

        // case 3: blank not in column 0, swap blankIndex and blankIndex-1
        if (blankCol != 0) {
            int column = (tiles[blankIndex - 1] - 1) % N;
            if (column <= blankCol - 1) md = this.mdistance + 1;
            else md = this.mdistance - 1;
            q.push(new Board(swap(blankIndex, blankIndex - 1),
                        blankRow, blankCol - 1, md));
            //q.push(new Board(swap(blankIndex, blankIndex - 1)));
        }

        // case 4: blank not in column N-1, swap blankIndex and blankIndex+1
        if (blankCol != N - 1) {
            int column = (tiles[blankIndex + 1] - 1) % N;
            if (column >= blankCol + 1) md = this.mdistance + 1;
            else md = this.mdistance - 1;
            q.push(new Board(swap(blankIndex, blankIndex + 1),
                       blankRow, blankCol + 1, md));
            //q.push(new Board(swap(blankIndex, blankIndex + 1)));
        }

        return q;
    }