Exemple #1
0
    def solve(self) -> bool:
        """Solve the sudoku board recursively using a backtracking algorithm
        and shows the steps visually."""

        coordinates = solver.find_empty(self.puzzle)
        if not coordinates:
            return True

        row, col = coordinates
        grid_x = col // 3
        grid_y = row // 3
        square_size = (55, 55)

        for i in range(1, 10):
            self.clock.tick(self.speed)
            self.display.fill(DARK_BLUE)
            self.draw_empty_board()
            self.draw_numbers(DARK_BLUE)
            self.draw_buttons()

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()

                if event.type == pygame.MOUSEBUTTONDOWN:
                    mouse_pos = pygame.mouse.get_pos()
                    if 688 < mouse_pos[0] < 1019 and 550 < mouse_pos[1] < 605:
                        self.new_speed()

                    if 730 < mouse_pos[0] < 970 and 340 < mouse_pos[1] < 410:
                        self.quick_solve(use_copy=True)
                        return True

            if solver.is_valid(self.puzzle, row, col, i):
                self.puzzle[row][col] = i
                self.draw_empty_board()
                pygame.draw.rect(self.display, self.GREEN,
                                 ((45 + (col * 60) + (grid_x * 5), 120 +
                                   (row * 60) + (grid_y * 5)), square_size))
                self.draw_numbers(self.GREEN)
                self.draw_numbers(self.DARK_BLUE, use_copy=True)
                pygame.display.update()

                if self.solve():
                    return True

            self.puzzle[row][col] = 0
            self.draw_empty_board()
            pygame.draw.rect(self.display, self.RED,
                             ((45 + (col * 60) + (grid_x * 5), 120 +
                               (row * 60) + (grid_y * 5)), square_size))
            self.draw_numbers(self.GREEN)
            self.draw_numbers(self.DARK_BLUE, use_copy=True)
            pygame.display.update()

        return False
    def place(self, val):
        row, col = self.selected
        self.cells[row][col].set_val(val)

        # Check if placement is valid to keep track for completion
        if solver.is_valid(self.state, col, row, val):
            self.cells[row][col].valid = True
        else:
            self.cells[row][col].valid = False

        self.update_state()
Exemple #3
0
 def update_board(self, position, number):
     if number == -1 or position == None:
         return False
     row, column = map(lambda x: (x - self.PADDING) // self.CELL_SIZE, position)
     if row < 0 or row > 8 or column < 0 or column > 8:
         return False
     if self.INITIAL_BOARD[row][column] == 0:
         if is_valid(self.board, (row, column), number) or number == 0:
             self.board[row][column] = number
             self.invalid_cell = None
         else:
             self.invalid_cell = position
Exemple #4
0
    def place(self, val):
        row, col = self.selected
        if self.cubes[row][col].value == 0:
            self.cubes[row][col].set(val)
            self.update_model()

            if is_valid(self.model, val,
                        (row, col)) and solve_board(self.model):
                return True
            else:
                self.cubes[row][col].set(0)
                self.cubes[row][col].set_temp(0)
                self.update_model()
                return False
def main():
	for team_id, task_id in enumerate(task_ids):
		print("Generating task for team" , team_id)

		flag = flags[team_id]
		
		task_folder = os.path.join(PACKAGE_PATH, task_id)
		os.makedirs(task_folder, exist_ok=True)
		
		task_file = os.path.join(task_folder, "scanner")
		
		os.system("python3 {} {} {}".format(GENERATOR, flag, task_file))

		assert is_valid(task_file, flag)
Exemple #6
0
    def place_num(self, value):
        """Check validation of a number to place in the board"""
        row, col = self.selected
        if self.cubes[row][col].value == 0:
            self.cubes[row][col].set_value(value)
            self.update_model()

            if is_valid(self.model, value, (row, col)) and solve(self.model):
                return True
            elif is_valid_sudoku(self.model):
                return True
            else:
                self.cubes[row][col].set_value(0)
                self.cubes[row][col].set_temporary(0)
                self.update_model()
                return False
Exemple #7
0
def solve_gui(board):
    """
    Solves the given sudoku board using backtracking algorithm.
    Added graphic capabilities on top of solver.solve method.
    """
    # Find empty space. If none exists, return true.
    empty = solver.find_zero(board)
    if not empty:
        return True
    row, col = empty

    # Try all possible values in the coordinate of empty space.
    # If value is valid, recurse the 'solve' method.
    # Otherwise, reset value to 0 and try another value to recurse.
    for i in range(1, 10):
        if solver.is_valid(row, col, i, board):
            board[row][col] = i
            delay_draw(col, row, i, black, 90)
            if solve_gui(board):
                return True
            board[row][col] = 0
            delay_draw(col, row, i, blue, 90)
    return False
Exemple #8
0
 def test_valid(self):
     self.assertTrue(is_valid(self.valid))
Exemple #9
0
 def test_same_diag(self):
     self.assertFalse(is_valid(self.invalid_diag))
Exemple #10
0
 def test_same_col(self):
     self.assertFalse(is_valid(self.invalid_row))
    def __init__(self,
                 img_path=None,
                 img=None,
                 max_size=1000,
                 predict_threshold=0.5,
                 overlay=True):
        """
        Initializes the Sudoku grid from an image.

        Args:
            img_path (str): path to the image of sudoku
            img (numpy.ndarray): loaded image instead of img_path
            max_size (int): maximum allowed size of image
            predict_threshold (float): minimun threshold to predict digit
            overlay (bool): generate the output image
        """
        if img_path is None and img is None:
            raise ValueError("img_path and img both cannot be None.")
        if img_path is not None and img is not None:
            raise ValueError("Only one of img_path and img can be used.")
        if img_path:
            if not os.path.exists(img_path):
                raise FileNotFoundError(img_path)
            img = cv2.imread(img_path, cv2.IMREAD_COLOR)

        self.status = 'processing'
        self.original = ip_utils.scale_down(img, max_size)
        self.solved_image = None
        self.grayscale = cv2.cvtColor(self.original.copy(), cv2.COLOR_BGR2GRAY)

        # crop and warp to get the sudoku grid
        self.cropped, self.crop_matrix, self.crop_corners = ip_utils.crop_grid(
            self.grayscale)
        self.cropped_color = None

        # divide the grid into cells
        self.grid_cells = ip_utils.divide_into_cells(self.cropped)

        # extract the digits from the cells
        self.digits = ip_utils.get_digits(self.cropped,
                                          self.grid_cells,
                                          size=28)

        # convert the images of digits to digits using digit recognition model
        self.board = [[0] * 9 for _ in range(9)]
        self.solved_board = None
        pred_indices = []
        pred_digits = []
        for i, digit in enumerate(self.digits):
            # if digit is present in cell
            if cv2.countNonZero(digit) > 0:
                pred_digits.append(digit)
                pred_indices.append((i // 9, i % 9))
        predicted = predict_digits(np.array(pred_digits),
                                   threshold=predict_threshold)
        for (i, j), d in zip(pred_indices, predicted):
            self.board[i][j] = d

        # check if recognized sudoku puzzle is valid
        if not solver.is_valid(self.board):
            self.status = 'Unable to detect a valid Sudoku puzzle.'
            return

        self.solved_board = copy.deepcopy(self.board)

        if solver.solve(self.solved_board, validate=False):
            if overlay:
                self.solved_image = self.digits_overlay()
            self.status = 'solved'
        else:
            self.status = 'Either the sudoku is invalid or image is blurry.'
Exemple #12
0
def run(board):
    init_board()
    set_board(board)
    orig_board = copy.deepcopy(board)

    selected = False
    valued = False
    prev_val = -1
    while True:
        for event in pygame.event.get():

            # Game exit.
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()

            # Key pressed.
            elif event.type == pygame.KEYDOWN:

                # Pressed space bar which solves the sudoku game using backtracking.
                if event.key == pygame.K_SPACE:
                    if selected:
                        reset_selected_box(valued, prev_pos, prev_val)
                        selected = False
                        valued = False
                    solve_gui(board)

                # Pressed number character with box selected.
                elif event.key in [
                        pygame.K_1, pygame.K_2, pygame.K_3, pygame.K_4,
                        pygame.K_5, pygame.K_6, pygame.K_7, pygame.K_8,
                        pygame.K_9
                ]:
                    if selected:
                        reset_selected_box(valued, prev_pos, prev_val)
                        valued = True
                        delay_draw(prev_pos[0] // 55, prev_pos[1] // 55,
                                   event.unicode, grey, 0)
                        prev_val = event.unicode

                # Pressing enter with a box filled in with value.
                # Value is either valid or invalid.
                elif event.key == pygame.K_RETURN:

                    # Enter only works if there is a box selected and valued.
                    if selected & valued:
                        value = int(prev_val)
                        col, row = prev_pos[0] // 55, prev_pos[1] // 55

                        # Input is valid.
                        if solver.is_valid(row, col, value, board):
                            board[row][col] = value
                            delay_draw(col, row, value, green, 200)
                            delay_draw(col, row, value, black, 0)

                        # Input is invalid.
                        else:
                            delay_draw(col, row, value, red, 200)
                            delay_draw(col, row, value, blue, 0)
                        selected = False
                        valued = False
                        prev_val = -1

            # Mouse selection.
            elif event.type == pygame.MOUSEBUTTONDOWN:
                x, y = pygame.mouse.get_pos()
                col, row = x // 55, y // 55

                # Selected box can be changed.
                if empty_pos(x, y, orig_board):
                    if board[row][col] != 0:
                        delay_draw(col, row, board[row][col], blue, 0)
                        board[row][col] = 0
                    if selected:
                        reset_selected_box(valued, prev_pos, prev_val)
                        valued = False
                    delay_draw(col, row, "?", grey, 0)
                    selected = True
                    prev_pos = (x, y)