예제 #1
0
 def solve_grid(self):
     self.error_label = None
     #check for edge cases:
     # -input wrong(not int, not 0 to 9)
     try:
         counter = 0
         for i in range(9):
             for j in range(9):
                 tmp = int(self.cells[i][j].get("1.0", 'end-1c'))
                 if tmp > 9:
                     self.error_label = Label(
                         self.window,
                         text=
                         "The sudoku input was not valid (not a number from 0 to 9)."
                     ).place(x=10, y=400)
                     return
                 if tmp != 0:
                     counter += 1
         if counter < 10:
             warning = Label(
                 self.window,
                 text=
                 "There are very few given numbers. Computing all possible solutions is not feasible\non generic computers."
             ).place(x=10, y=400)
             return
     except ValueError:
         self.error_label = Label(
             self.window,
             text="The sudoku input was not valid (not a number).").place(
                 x=10, y=400)
         return
     # -not enough filled in
     #create a Grid object with all values from the gui grid
     grid = Grid()
     for i in range(9):
         for j in range(9):
             # get each cell, convert string to int
             grid.set_cell(i, j, int(self.cells[i][j].get("1.0", 'end-1c')))
     #create Sudoku Solver object and calculate solution
     solver = SudokuSolver(grid)
     #check if sudoku is valid
     if solver.is_correct() is False:
         self.error_label = Label(
             self.window,
             text="The given input is not a valid sudoku.").place(x=10,
                                                                  y=400)
         return
     solver.solve()
     # display solution in new window
     if len(solver.get_solutions()) == 0:
         warning = Label(
             self.window,
             text="There are no solutions to the given sudoku.").place(
                 x=10, y=400)
     else:
         self.display_solutions(solver)
예제 #2
0
class SudokuSolverTests(unittest.TestCase):
    def setUp(self):
        self.empty = Sudoku()
        self.solver = SudokuSolver()
        tmp = Sudoku()
        tmp[0] = [2,4,8,3,9,5,7,1,6]
        tmp[1] = [5,7,1,6,2,8,3,4,9]
        tmp[2] = [9,3,6,7,4,1,5,8,2]
        tmp[3] = [6,8,2,5,3,9,1,7,4]
        tmp[4] = [3,5,9,1,7,4,6,2,8]
        tmp[5] = [7,1,4,8,6,2,9,5,3]
        tmp[6] = [8,6,3,4,1,7,2,9,5]
        tmp[7] = [1,9,5,2,8,6,4,3,7]
        tmp[8] = [4,2,7,9,5,3,8,6,1]
        self.complete = tmp
    def test_empty_puzzle_has_all_possible(self):
        nine = [1,2,3,4,5,6,7,8,9]
        for row in range(9):
            for col in range(9):
                self.assertEqual(nine, self.solver.possible(self.empty, row, col))
    def test_try_value(self):
        puzzle, worked = self.solver.try_value(self.empty, 0,0,1)
        self.assertTrue(worked)
        self.empty[0][0] = 0
    def test_try_value_raises_errors(self):
        self.assertRaises(IndexError, self.solver.try_value, self.empty, -1, 7, 7)
        self.assertRaises(IndexError, self.solver.try_value, self.empty, 7, 10, 7)
        self.assertRaises(ValueError, self.solver.try_value, self.empty, 0,0, 10)
        self.assertRaises(ValueError, self.solver.try_value, self.empty, 0,0,-1)
    def test_try_value_wont_clobber(self):
        self.assertRaises(ValueError, self.solver.try_value, self.complete, 0,0, 1)
    def test_solver_accepts_solved(self):
        self.assertTrue(self.solver.solve(self.complete))
    # next test is time consuming (maybe 10 seconds or so):
    # def test_solver_works(self):
    #     self.assertTrue(self.solver.solve(self.empty))
    def test_solver_works_from_paper(self):
        "grabbed a puzzle out of this weeks paper."
        paper = Sudoku()
        paper[0] = [0,0,0,0,2,0,3,0,1]
        paper[1] = [0,0,0,1,0,6,2,0,0]
        paper[2] = [1,7,2,0,5,0,4,0,6]
        paper[3] = [0,0,3,2,0,0,1,0,7]
        paper[4] = [0,0,9,0,0,1,6,2,0]
        paper[5] = [2,1,7,0,6,8,9,0,0]
        paper[6] = [4,9,0,6,1,0,0,3,2]
        paper[7] = [0,0,1,9,0,0,0,6,4]
        paper[8] = [7,0,6,0,8,0,5,1,9]
        solved = self.solver.solve(paper)
        self.assertTrue(solved)
예제 #3
0
 def action(self):
     board = [[int(window.buttons[j][i].get_text()) for i in range(9)]
              for j in range(9)]
     print(board)
     s = SudokuSolver(board)
     res = s.solve()
     if res:
         for i in range(9):
             for j in range(9):
                 window.buttons[i][j].setText(str(res[i][j]))
     else:
         print("No solutions.")
예제 #4
0
test_solver = SudokuSolver()

generator_a = AStarSudokuGenerator(kind='linear')
generator_a_rev = AStarSudokuGenerator(kind='reverse', solver = test_solver)
generator_rand = RandomSudokuGenerator()
generator_rev = ReverseSudokuGenerator()

#s1, l1, x1, y1 = generator_a.generate_sudoku(target = 25)
#s2, l2, x2, y2 = generator_a_rev.generate_sudoku(target = 25)
s3, l3, x3, y3 = generator_rand.generate_sudoku(target = 24)
#s4, l4, x4, y4 = generator_rev.generate_sudoku(target = 25)


#(ss1, _, _) = solver.solve(s1, max_sol = 2)
#(ss2, _, _) = solver.solve(s2, max_sol = 2)
(ss3, _, _) = solver.solve(s3, max_sol = 2)
#(ss4, _, _) = solver.solve(s4, max_sol = 2)

#assert len(ss1) == 1, 'A* genera un sudoku con più di una soluzione'
#assert len(ss2) == 1, 'A*Rev genera un sudoku con più di una soluzione'
assert len(ss3) == 1, 'Rand genera un sudoku con più di una soluzione'
#assert len(ss4) == 1, 'Rev genera un sudoku con più di una soluzione'

print '########################################'
#print 'A* - Generato sudoku con %d numeri' % l1
#print x1, y1
#print s1
#print 'A*Reverse - Generato sudoku con %d numeri' % l2
#print x2, y2
#print s2
print 'Random - Generato sudoku con %d numeri' % l3
예제 #5
0
class SudokuSolverGUI(object):
    def __init__(self):

        os.environ["SDL_VIDEO_CENTERED"] = "1"
        pygame.init()

        pygame.display.set_caption(CAPTION)
        self._screen = pygame.display.set_mode(RESOLUTION)
        self._clock = pygame.time.Clock()
        self._grid_font = pygame.font.Font(FONT_NAME, GRID_FONT_SIZE)
        self._help_font = pygame.font.Font(FONT_NAME, HELP_FONT_SIZE)

        # board settings
        self._board_pos = (RESOLUTION[0] - BOARD_SIZE) // 2, BOARD_Y
        self._grid_size = BOARD_SIZE // 9

        # calculate grid lines' coordinates
        grid_xs = [x * self._grid_size + self._board_pos[0] for x in xrange(10)]
        grid_ys = [y * self._grid_size + self._board_pos[1] for y in xrange(10)]

        vertical_lines_top = [(x, self._board_pos[1]) for x in grid_xs]
        vertical_lines_bottom = [(x, self._board_pos[1] + BOARD_SIZE - 4) for x in grid_xs]
        horizontal_lines_top = [(self._board_pos[0], y) for y in grid_ys]
        horizontal_lines_bottom = [(self._board_pos[0] + BOARD_SIZE - 4, y) for y in grid_ys]

        self._vertical_lines = zip(vertical_lines_top, vertical_lines_bottom)
        self._horizontal_lines = zip(horizontal_lines_top, horizontal_lines_bottom)

        # set grids
        self._grids = [
            Grid(grid_xs[j], grid_ys[i], self._grid_size, self._grid_size) for j in xrange(9) for i in xrange(9)
        ]
        self._reset_grids()

        # selection
        self._selected_grid = None

        # solver
        self._solver = SudokuSolver()

    def run(self):

        while True:
            # events handling
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    raise SystemExit
                elif event.type == MOUSEMOTION:
                    self._handle_mouse(event)
                elif event.type == KEYDOWN:
                    self._handle_keyboard(event)

            # draw stuffs
            self._draw_background()
            self._draw_grids()
            self._draw_grid_lines()
            self._draw_help_text()

            # step
            pygame.display.update()
            self._clock.tick(FRAMERATE)

    def _handle_mouse(self, event):

        # set mose over status
        if event.type == MOUSEMOTION:
            for grid in self._grids:
                grid.status &= ~S_MOUSEOVER
                if grid.collidepoint(event.pos):
                    grid.status |= S_MOUSEOVER
                    self._selected_grid = grid

    def _handle_keyboard(self, event):

        key_name = pygame.key.name(event.key)

        if key_name in map(str, xrange(1, 10)):
            # fill grid
            self._selected_grid.number = key_name
            self._selected_grid.status |= S_FILLED
            self._selected_grid.status &= ~S_ANSWER
        elif key_name == "0":
            # clear grid
            self._selected_grid.status &= ~(S_FILLED | S_ANSWER)
            self._selected_grid.number = None
        elif event.key == K_ESCAPE:
            # quit
            pygame.quit()
            raise SystemExit
        elif event.key == K_r:
            # reset
            self._reset_grids()
        elif event.key == K_SPACE:
            # solve
            self._solve()

    def _reset_grids(self):

        for grid in self._grids:
            grid.status = S_BLANK
            grid.number = None

    def _draw_background(self):

        self._screen.fill(Color(BACKGROUND_COLOR))

    def _draw_grids(self):

        for grid in self._grids:
            if grid.status & S_FILLED:
                pygame.draw.rect(self._screen, Color(FILLED_COLOR), grid)
            if grid.status & S_MOUSEOVER:
                pygame.draw.rect(self._screen, Color(MOUSE_OVER_COLOR), grid)
            if grid.number:
                color = GRID_ANSWER_COLOR if grid.status & S_ANSWER else GRID_TEXT_COLOR

                text = self._grid_font.render(grid.number, True, Color(color))

                x = grid.center[0] - text.get_width() // 2
                y = grid.center[1] - text.get_height() // 2

                self._screen.blit(text, (x, y))

    def _draw_grid_lines(self):

        # draw thin lines
        for i, (start_pos, end_pos) in enumerate(self._vertical_lines):
            if i % 3 != 0:
                pygame.draw.line(self._screen, Color(THIN_LINE_COLOR), start_pos, end_pos, 1)
        for i, (start_pos, end_pos) in enumerate(self._horizontal_lines):
            if i % 3 != 0:
                pygame.draw.line(self._screen, Color(THIN_LINE_COLOR), start_pos, end_pos, 1)
        # draw thick lines
        for i, (start_pos, end_pos) in enumerate(self._vertical_lines):
            if i % 3 == 0:
                pygame.draw.line(self._screen, Color(THICK_LINE_COLOR), start_pos, end_pos, 2)

        for i, (start_pos, end_pos) in enumerate(self._horizontal_lines):
            if i % 3 == 0:
                pygame.draw.line(self._screen, Color(THICK_LINE_COLOR), start_pos, end_pos, 2)

    def _draw_help_text(self):

        x, y = HELP_TEXT_POS

        for line in HELP_TEXT.split("\n"):
            text = self._help_font.render(line, True, Color(HELP_TEXT_COLOR))
            self._screen.blit(text, (x, y))
            y += HELP_TEXT_Y_INCREMENT

    def _solve(self):

        s = cStringIO.StringIO()
        for grid in self._grids:
            if not grid.status & S_FILLED:
                grid.status &= ~S_ANSWER
                grid.number = None
                s.write(".")
            else:
                s.write(grid.number)
        puzzle = s.getvalue()
        matrix = self._solver.solve(puzzle)

        for row, col, val in matrix:
            grid = self._grids[row * 9 + col]
            if not grid.number:
                grid.number = str(val)
                grid.status |= S_ANSWER
예제 #6
0
class SudokuSolverGUI(object):
    def __init__(self):

        os.environ['SDL_VIDEO_CENTERED'] = '1'
        pygame.init()

        pygame.display.set_caption(CAPTION)
        self._screen = pygame.display.set_mode(RESOLUTION)
        self._clock = pygame.time.Clock()
        self._grid_font = pygame.font.Font(FONT_NAME, GRID_FONT_SIZE)
        self._help_font = pygame.font.Font(FONT_NAME, HELP_FONT_SIZE)

        # board settings
        self._board_pos = (RESOLUTION[0] - BOARD_SIZE) // 2, BOARD_Y
        self._grid_size = BOARD_SIZE // 9

        # calculate grid lines' coordinates
        grid_xs = [
            x * self._grid_size + self._board_pos[0] for x in xrange(10)
        ]
        grid_ys = [
            y * self._grid_size + self._board_pos[1] for y in xrange(10)
        ]

        vertical_lines_top = [(x, self._board_pos[1]) for x in grid_xs]
        vertical_lines_bottom = [(x, self._board_pos[1] + BOARD_SIZE - 4)
                                 for x in grid_xs]
        horizontal_lines_top = [(self._board_pos[0], y) for y in grid_ys]
        horizontal_lines_bottom = [(self._board_pos[0] + BOARD_SIZE - 4, y)
                                   for y in grid_ys]

        self._vertical_lines = zip(vertical_lines_top, vertical_lines_bottom)
        self._horizontal_lines = zip(horizontal_lines_top,
                                     horizontal_lines_bottom)

        # set grids
        self._grids = [
            Grid(grid_xs[j], grid_ys[i], self._grid_size, self._grid_size)
            for j in xrange(9) for i in xrange(9)
        ]
        self._reset_grids()

        # selection
        self._selected_grid = None

        # solver
        self._solver = SudokuSolver()

    def run(self):

        while True:
            # events handling
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    raise SystemExit
                elif event.type == MOUSEMOTION:
                    self._handle_mouse(event)
                elif event.type == KEYDOWN:
                    self._handle_keyboard(event)

            # draw stuffs
            self._draw_background()
            self._draw_grids()
            self._draw_grid_lines()
            self._draw_help_text()

            # step
            pygame.display.update()
            self._clock.tick(FRAMERATE)

    def _handle_mouse(self, event):

        # set mose over status
        if event.type == MOUSEMOTION:
            for grid in self._grids:
                grid.status &= ~S_MOUSEOVER
                if grid.collidepoint(event.pos):
                    grid.status |= S_MOUSEOVER
                    self._selected_grid = grid

    def _handle_keyboard(self, event):

        key_name = pygame.key.name(event.key)

        if key_name in map(str, xrange(1, 10)):
            # fill grid
            self._selected_grid.number = key_name
            self._selected_grid.status |= S_FILLED
            self._selected_grid.status &= ~S_ANSWER
        elif key_name == '0':
            # clear grid
            self._selected_grid.status &= ~(S_FILLED | S_ANSWER)
            self._selected_grid.number = None
        elif event.key == K_ESCAPE:
            # quit
            pygame.quit()
            raise SystemExit
        elif event.key == K_r:
            # reset
            self._reset_grids()
        elif event.key == K_SPACE:
            # solve
            self._solve()

    def _reset_grids(self):

        for grid in self._grids:
            grid.status = S_BLANK
            grid.number = None

    def _draw_background(self):

        self._screen.fill(Color(BACKGROUND_COLOR))

    def _draw_grids(self):

        for grid in self._grids:
            if grid.status & S_FILLED:
                pygame.draw.rect(self._screen, Color(FILLED_COLOR), grid)
            if grid.status & S_MOUSEOVER:
                pygame.draw.rect(self._screen, Color(MOUSE_OVER_COLOR), grid)
            if grid.number:
                color = GRID_ANSWER_COLOR if grid.status & S_ANSWER else \
                        GRID_TEXT_COLOR

                text = self._grid_font.render(grid.number, True, Color(color))

                x = grid.center[0] - text.get_width() // 2
                y = grid.center[1] - text.get_height() // 2

                self._screen.blit(text, (x, y))

    def _draw_grid_lines(self):

        # draw thin lines
        for i, (start_pos, end_pos) in enumerate(self._vertical_lines):
            if i % 3 != 0:
                pygame.draw.line(self._screen, Color(THIN_LINE_COLOR),
                                 start_pos, end_pos, 1)
        for i, (start_pos, end_pos) in enumerate(self._horizontal_lines):
            if i % 3 != 0:
                pygame.draw.line(self._screen, Color(THIN_LINE_COLOR),
                                 start_pos, end_pos, 1)
        # draw thick lines
        for i, (start_pos, end_pos) in enumerate(self._vertical_lines):
            if i % 3 == 0:
                pygame.draw.line(self._screen, Color(THICK_LINE_COLOR),
                                 start_pos, end_pos, 2)

        for i, (start_pos, end_pos) in enumerate(self._horizontal_lines):
            if i % 3 == 0:
                pygame.draw.line(self._screen, Color(THICK_LINE_COLOR),
                                 start_pos, end_pos, 2)

    def _draw_help_text(self):

        x, y = HELP_TEXT_POS

        for line in HELP_TEXT.split('\n'):
            text = self._help_font.render(line, True, Color(HELP_TEXT_COLOR))
            self._screen.blit(text, (x, y))
            y += HELP_TEXT_Y_INCREMENT

    def _solve(self):

        s = cStringIO.StringIO()
        for grid in self._grids:
            if not grid.status & S_FILLED:
                grid.status &= ~S_ANSWER
                grid.number = None
                s.write('.')
            else:
                s.write(grid.number)
        puzzle = s.getvalue()
        matrix = self._solver.solve(puzzle)

        for row, col, val in matrix:
            grid = self._grids[row * 9 + col]
            if not grid.number:
                grid.number = str(val)
                grid.status |= S_ANSWER
예제 #7
0
example_puzzle = "010020300004005060070000004006800070000900002050017000400006050000400906008000000"
hardest_puzzle = "800000000003600000070090200050007000000045700000100030001000068008500010090000400"

from sudoku import SudokuSolver

solver = SudokuSolver(hardest_puzzle)
solver.solve()
solver.print_board()
solver.print_statistics()