Exemplo n.º 1
0
 def correct_solution(self):
     """Corrects solution."""
     for i in range(0, self.size[0]):
         for j in range(0, self.size[1]):
             if self.puzzle[i, j] > 0:
                 queue = define_block(i, j)
                 visited = []
                 while queue:
                     q = queue.pop()
                     visited.append(q)
                     for p in adjacent_squares(*q):
                         p_sym = symmetric_point(i, j, *p)
                         q_sym = symmetric_point(i, j, *q)
                         pos_wall = wall_between(p[0], p[1], q[0], q[1])
                         sym_wall = wall_between(p_sym[0], p_sym[1],
                                                 q_sym[0], q_sym[1])
                         if not self.is_wall(
                                 *pos_wall) and not self.is_wall(
                                     *sym_wall) and p not in visited:
                             queue.append(p)
                         elif self.is_wall(
                                 *pos_wall) and not self.is_wall(*sym_wall):
                             self.solution[sym_wall[0], sym_wall[1]] = 1
                         elif not self.is_wall(*pos_wall) and self.is_wall(
                                 *sym_wall):
                             self.solution[pos_wall[0], pos_wall[1]] = 1
                 block = get_unique(visited)
                 for b in block:
                     self.solution[b[0], b[1]] = self.puzzle[i, j]
Exemplo n.º 2
0
 def check_closed(self):
     """Checks if there are new closed blocks."""
     for i, row in enumerate(self.solution):
         for j, el in enumerate(row):
             if self.puzzle[i, j] > 0 and not closest_closed(
                     i, j, self.solution):
                 queue = define_block(i, j)
                 visited = []
                 while queue:
                     p = queue.pop()
                     visited.append(p)
                     next_ones = adjacent_squares(p[0], p[1])
                     for n in next_ones:
                         if self.is_inside(*n) and not self.puzzle[n[0], n[1]] < 0 \
                                 and not self.is_wall(*wall_between(p[0], p[1], n[0], n[1])) \
                                 and n not in visited:
                             n_sym = symmetric_point(i, j, n[0], n[1])
                             p_sym = symmetric_point(i, j, p[0], p[1])
                             if (self.is_inside(*n_sym) and self.is_inside(*p_sym)) and \
                                     not self.puzzle[n_sym[0], n_sym[1]] < 0 or \
                                     not self.is_wall(*wall_between(p_sym[0], p_sym[1], n_sym[0], n_sym[1])):
                                 queue.append(n)
                 if self.puzzle[i, j] > 0:
                     block = get_unique(np.array(visited))
                     if self.block_is_closed(block, self.solution):
                         for b in block:
                             self.solution[b[0], b[1]] = self.puzzle[i, j]
Exemplo n.º 3
0
    def fill_from_dot(self, i, j, k=0, block=None):
        """
        Fills block from given dot.
        :param k: describes how far from dot algorithm will attempt to fill puzzle
        :param i: position
        :param j: position
        :param block: if not empty, function can use only points in block
        :return: how many walls were put in
        """
        filled_count = 0
        queue = define_block(i, j)
        visited = []
        no_queue = False
        while queue:
            p = queue.pop()
            visited.append(p)
            next_ones = []
            for n in adjacent_squares(p[0], p[1]):
                if 0 < k < point_dist(n[0], n[1], i, j):
                    no_queue = True
                wall = wall_between(n[0], n[1], p[0], p[1])
                if n not in visited:
                    if block is not None:
                        if n in block:
                            if not (self.is_inside(*wall) and self.puzzle[wall[0], wall[1]] > 0) \
                                    and not (self.is_inside(*n) and self.solution[n[0], n[1]] < 0):
                                next_ones.append(n)
                    else:
                        if not (self.is_inside(*wall) and self.puzzle[wall[0], wall[1]] > 0) \
                                and not (self.is_inside(*n) and self.puzzle[n[0], n[1]] > 0):
                            next_ones.append(n)
            for n in next_ones:
                n_sym = symmetric_point(i, j, n[0], n[1])
                p_sym = symmetric_point(i, j, p[0], p[1])
                new_wall = wall_between(p_sym[0], p_sym[1], n_sym[0], n_sym[1])
                curr_wall = wall_between(p[0], p[1], n[0], n[1])
                if self.is_wall(*curr_wall) and \
                        self.is_inside(*new_wall) and not (self.is_wall(*new_wall)
                                                           or self.puzzle[new_wall[0], new_wall[1]] > 0):
                    self.solution[new_wall[0], new_wall[1]] = 1
                    filled_count += 1
                if self.is_wall(*new_wall) and \
                        self.is_inside(*curr_wall) and not (self.is_wall(*curr_wall)
                                                            or self.puzzle[curr_wall[0], curr_wall[1]] > 0):
                    self.solution[curr_wall[0], curr_wall[1]] = 1
                    filled_count += 1
            if not no_queue:
                for n in next_ones:
                    curr_wall = wall_between(p[0], p[1], n[0], n[1])
                    if not self.is_wall(*curr_wall) and \
                            self.is_inside(*n) and self.solution[n[0], n[1]] < 1:
                        queue.append(n)

        if self.puzzle[i, j] > 0:
            block = get_unique(np.array(visited))
            if self.block_is_closed(block, self.solution):
                for b in block:
                    self.solution[b[0], b[1]] = self.puzzle[i, j]

        return filled_count
Exemplo n.º 4
0
    def fill_block(self, x, y, c):
        """
        Fills unfilled blocks in puzzle with dots.
        :param x: position
        :param y: position
        :param c: color to fill
        :return:
        """
        queue = misc.define_block(x, y)
        visited = []
        while queue:
            q = queue.pop()
            visited.append(q)
            queue2 = misc.adjacent_squares(*q)
            for q2 in queue2:
                if q2 not in visited and \
                    not self.solver.is_wall(*misc.wall_between(q[0], q[1], q2[0], q2[1])) and \
                        self.solver.is_inside(*q2):
                    queue.append(q2)

        block = misc.get_unique(np.array(visited))
        if len(block) == 1:
            b = block[0]
            self.solver.puzzle[b[0], b[1]] = c
            self.solver.solution[b[0], b[1]] = c
        elif len(block) == 2:
            new_dot = misc.wall_between(block[0][0], block[0][1], block[1][0], block[1][1])
            self.solver.puzzle[new_dot[0], new_dot[1]] = c
            self.solver.solution[block[0][0], block[0][1]] = c
            self.solver.solution[block[1][0], block[1][1]] = c
        else:
            # check if symmetric
            xs = [a[0] for a in block]
            ys = [a[1] for a in block]
            dot = [int((min(xs) + max(xs))/2), int((min(ys) + max(ys))/2)]
            symmetric = True
            for b in block:
                sym_b = misc.symmetric_point(dot[0], dot[1], b[0], b[1])
                if [sym_b[0], sym_b[1]] not in block.tolist():
                    symmetric = False
            if symmetric:
                self.solver.puzzle[dot[0], dot[1]] = c
                for b in block:
                    self.solver.solution[b[0], b[1]] = c
            else:
                new_dot = block[np.random.randint(len(block))]
                self.solver.puzzle[new_dot[0], new_dot[1]] = c
                return True
        return False
Exemplo n.º 5
0
    def remove_redundant_walls(self):
        """Removes any redundant walls inside blocks."""
        for i in range(0, self.size[0]):
            for j in range(0, self.size[1]):
                if self.solver.puzzle[i, j] > 0:
                    queue = misc.define_block(i, j)
                    visited = []
                    while queue:
                        q = queue.pop()
                        visited.append(q)
                        queue2 = misc.adjacent_squares(*q)
                        for q2 in queue2:
                            if q2 not in visited and \
                                not self.solver.is_wall(*misc.wall_between(q[0], q[1], q2[0], q2[1])) and \
                                    self.solver.is_inside(*q2):
                                queue.append(q2)

                    block = misc.get_unique(np.array(visited))
                    all_walls = []
                    for b in block:
                        all_walls.append(misc.define_frame(b[0], b[1]))
                    all_walls = np.array(all_walls).reshape(-1, 2)
                    red_walls = np.array([x for x in all_walls if misc.count(all_walls, x) > 1])
                    for w in red_walls:
                        self.solver.solution[w[0], w[1]] = 0
Exemplo n.º 6
0
 def init_fill(self):
     """Fills obvious lines between two dots: if two squares contain dot or part of dot there is line."""
     for x in range(0, self.size[0], 2):
         for y in range(0, self.size[1], 2):
             if self.contains_dot(x, y):
                 adjacent = adjacent_squares(x, y)
                 for pair in adjacent:
                     if self.is_inside(*pair):
                         i, j = pair
                         if self.contains_dot(
                                 i, j) and not self.is_same_dot(x, y, i, j):
                             a, b = wall_between(x, y, i, j)
                             self.solution[a, b] = 1
Exemplo n.º 7
0
 def update_user_filling(self):
     """Updates blocked regions and fills them."""
     for i in range(self.size[0]):
         for j in range(self.size[1]):
             if self.puzzle[i, j] > 0:
                 block = []
                 if self.block_is_closed(define_block(i, j),
                                         self.user_solution):
                     block = define_block(i, j)
                 else:
                     queue = define_block(i, j)
                     visited = []
                     search = True
                     while queue and search:
                         p = queue.pop()
                         visited.append(p)
                         next_ones = adjacent_squares(p[0], p[1])
                         for n in next_ones:
                             if self.is_inside(*n) and n not in visited:
                                 if not self.is_wall(*wall_between(
                                         p[0], p[1], n[0], n[1]),
                                                     user=True):
                                     queue.append(n)
                                 if self.puzzle[n[0], n[1]] > 0 and \
                                         not self.is_wall(*wall_between(p[0], p[1], n[0], n[1])):
                                     search = False
                                     break
                     if search:
                         block = get_unique(np.array(visited))
                 if len(block) > 0:
                     if self.block_is_closed(block, self.user_solution):
                         for b in block:
                             self.user_solution[b[0], b[1]] = self.puzzle[i,
                                                                          j]
     for i, row in enumerate(self.user_solution):
         for j, el in enumerate(row):
             self.fill_color[
                 i, j] = el if i % 2 == 0 and j % 2 == 0 and el > 0 else 0
Exemplo n.º 8
0
    def find_blocked_regions(self):
        """Finds parts of blocks with all walls checked and one dot.
        Then fills symmetric part of that block."""
        filled_count = 0
        for i, row in enumerate(self.solution):
            for j, el in enumerate(row):
                if i % 2 == 0 and j % 2 == 0 and el == 0:
                    queue = []
                    dots = []
                    visited = [[i, j]]

                    for p in adjacent_squares(i, j):
                        pos_wall = wall_between(i, j, p[0], p[1])
                        cor_dot = self.dot_in_corner(i, j, p[0], p[1])
                        if self.is_inside(
                                *pos_wall) and self.puzzle[pos_wall[0],
                                                           pos_wall[1]] > 0:
                            dots.append(pos_wall)
                        elif not self.is_wall(*pos_wall) and self.is_inside(
                                *p) and self.puzzle[p[0], p[1]] > 0:
                            dots.append(p)
                        elif not self.is_wall(*pos_wall):
                            queue.append(p)
                        if not cor_dot == [-1, -1]:
                            dots.append(cor_dot)
                    while queue:
                        p = queue.pop()
                        sym_part = False
                        if len(dots) == 1:
                            for d in dots:
                                s = symmetric_point(d[0], d[1], p[0], p[1])
                                if [s[0], s[1]] in visited:
                                    sym_part = True
                        if not sym_part:
                            visited.append(p)
                            next_ones = adjacent_squares(p[0], p[1])
                            for n in next_ones:
                                pos_wall = wall_between(p[0], p[1], n[0], n[1])
                                if n not in visited and not self.is_wall(
                                        *pos_wall):
                                    corner_dot = self.dot_in_corner(
                                        n[0], n[1], p[0], p[1])
                                    if self.is_inside(*pos_wall) and self.puzzle[pos_wall[0], pos_wall[1]] > 0 \
                                            and pos_wall not in dots:
                                        dots.append(pos_wall)
                                    elif self.is_inside(*n) and self.puzzle[
                                            n[0], n[1]] > 0 and n not in dots:
                                        dots.append(n)
                                    elif self.is_inside(
                                            *n
                                    ) and n not in visited and n not in dots:
                                        queue.append(n)
                                    if not corner_dot == [
                                            -1, -1
                                    ] and corner_dot not in dots:
                                        dots.append(corner_dot)
                    block = get_unique(np.array(visited))
                    if len(dots) == 1 and len(block) > 0:
                        dot = dots[0]
                        filled_count += self.fill_from_dot(dot[0],
                                                           dot[1],
                                                           k=0,
                                                           block=block)
                    elif len(dots) > 1 and len(block) > 0:
                        self.test_dots(i, j, dots)
        return filled_count