Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Sudoku generator and solver in python

I am making a sudoku generator and solver project in Python for a school project and I ran into a couple of errors. The code itself does not have any mistakes, but the implementation is incorrect, so I’m stuck.

Here is the code:

    from tkinter import *
    import random
    
    class SudokuBoard:
        def __init__(self, master):
            self.master = master
            self.master.title("Sudoku Board")
            self.create_board()
            self.create_buttons()
            self.board = [[0 for _ in range(9)] for _ in range(9)]
    
        def create_board(self):
            self.cells = {}
            for i in range(9):
                for j in range(9):
                    if (i in (0, 1, 2, 6, 7, 8) and j in (3, 4, 5)) or (i in (3, 4, 5) and j in (0, 1, 2, 6, 7, 8)):
                        color = "#d9d9d9"
                    else:
                        color = "white"
                    self.cells[(i, j)] = Label(self.master, width=4, height=2, font=("Helvetica", 20), bg=color, relief="raised")
                    self.cells[(i, j)].grid(row=i, column=j)
    
        def create_buttons(self):
            self.generate_button = Button(self.master, text="Generate", font=("Helvetica", 16), command=self.generate_board)
            self.generate_button.grid(row=10, column=1, columnspan=3, padx=5, pady=5)
    
            self.solve_button = Button(self.master, text="Solve", font=("Helvetica", 16), command=self.solve_board)
            self.solve_button.grid(row=10, column=3, columnspan=3, padx=5, pady=5)
    
            self.reset_button = Button(self.master, text="Reset", font=("Helvetica", 16), command=self.reset_board)
            self.reset_button.grid(row=10, column=6, columnspan=3, padx=5, pady=5)
    
        def generate_board(self):
            # Generate a solvable Sudoku board
            while not self.solve_board():
                pass
            self.remove_numbers()  # Remove some numbers to create a puzzle
            self.update_cells()
    
        def reset_board(self):
            # Reset the board to all zeros
            self.board = [[0 for _ in range(9)] for _ in range(9)]
    
        cells_to_remove = 50  # class-level variable
    
        def remove_numbers(self):
            # Remove numbers from the board to create a puzzle
            cells_removed = 0
            while cells_removed < self.cells_to_remove:
                row = random.randint(0, 8)
                col = random.randint(0, 8)
                if self.board[row][col] != 0:
                    self.board[row][col] = 0
                    cells_removed += 1
    
    
        def solve_board(self):
            # Solve the Sudoku board using backtracking
            def find_empty():
                for i in range(9):
                    for j in range(9):
                        if self.board[i][j] == 0:
                            return (i, j)
                return None
    
            def is_valid(num, pos):
                # Check if num is valid in the given position
                # Check row
                for i in range(9):
                    if self.board[pos[0]][i] == num and pos[1] != i:
                        return False
                # Check column
                for i in range(9):
                    if self.board[i][pos[1]] == num and pos[0] != i:
                        return False
                # Check 3x3 square
                box_x = pos[1] // 3
                box_y = pos[0] // 3
                for i in range(box_y * 3, box_y * 3 + 3):
                    for j in range(box_x * 3, box_x * 3 + 3):
                        if self.board[i][j] == num and (i, j) != pos:
                            return False
                return True
    
            def solve():
                empty = find_empty()
                if not empty:
                    return True
                else:
                    row, col = empty
                    for num in range(1, 10):
                        if is_valid(num, (row, col)):
                            self.board[row][col] = num
                            if solve():
                                return True
                            self.board[row][col] = 0
                    return False
    
            return solve()
    
        def update_cells(self):
            # Update the cells with the current board values
            for i in range(9):
                for j in range(9):
                    if self.board[i][j] != 0:
                        self.cells[(i, j)].config(text=self.board[i][j], fg="black")
                    else:
                        self.cells[(i, j)].config(text="", fg="black")
    
    root = Tk()
    sudoku_board = SudokuBoard(root)
    root.mainloop()

I feel like there is a problem with the "remove numbers" function, the "solve board" function and the solve function but I can’t identify the problem so I can fix it.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

You have any ideas?

>Solution :

You forgot to "refresh" the cells (by calling update_cells) after calling solve_board or reset_board, so the GUI was not updated. Fix:

from tkinter import *
import random

class SudokuBoard:
    def __init__(self, master):
        self.master = master
        self.master.title("Sudoku Board")
        self.create_board()
        self.create_buttons()
        self.board = [[0 for _ in range(9)] for _ in range(9)]

    def create_board(self):
        self.cells = {}
        for i in range(9):
            for j in range(9):
                if (i in (0, 1, 2, 6, 7, 8) and j in (3, 4, 5)) or (i in (3, 4, 5) and j in (0, 1, 2, 6, 7, 8)):
                    color = "#d9d9d9"
                else:
                    color = "white"
                self.cells[(i, j)] = Label(self.master, width=4, height=2, font=("Helvetica", 20), bg=color, relief="raised")
                self.cells[(i, j)].grid(row=i, column=j)

    def create_buttons(self):
        self.generate_button = Button(self.master, text="Generate", font=("Helvetica", 16), command=self.generate_board)
        self.generate_button.grid(row=10, column=1, columnspan=3, padx=5, pady=5)

        self.solve_button = Button(self.master, text="Solve", font=("Helvetica", 16), command=self.solve_board)
        self.solve_button.grid(row=10, column=3, columnspan=3, padx=5, pady=5)

        self.reset_button = Button(self.master, text="Reset", font=("Helvetica", 16), command=self.reset_board)
        self.reset_button.grid(row=10, column=6, columnspan=3, padx=5, pady=5)

    def generate_board(self):
        # Generate a solvable Sudoku board
        while not self.solve_board():
            pass
        self.remove_numbers()  # Remove some numbers to create a puzzle
        self.update_cells()

    def reset_board(self):
        # Reset the board to all zeros
        self.board = [[0 for _ in range(9)] for _ in range(9)]
        self.update_cells()

    cells_to_remove = 50  # class-level variable

    def remove_numbers(self):
        # Remove numbers from the board to create a puzzle
        cells_removed = 0
        while cells_removed < self.cells_to_remove:
            row = random.randint(0, 8)
            col = random.randint(0, 8)
            if self.board[row][col] != 0:
                self.board[row][col] = 0
                cells_removed += 1


    def solve_board(self):
        # Solve the Sudoku board using backtracking
        def find_empty():
            for i in range(9):
                for j in range(9):
                    if self.board[i][j] == 0:
                        return (i, j)
            return None

        def is_valid(num, pos):
            # Check if num is valid in the given position
            # Check row
            for i in range(9):
                if self.board[pos[0]][i] == num and pos[1] != i:
                    return False
            # Check column
            for i in range(9):
                if self.board[i][pos[1]] == num and pos[0] != i:
                    return False
            # Check 3x3 square
            box_x = pos[1] // 3
            box_y = pos[0] // 3
            for i in range(box_y * 3, box_y * 3 + 3):
                for j in range(box_x * 3, box_x * 3 + 3):
                    if self.board[i][j] == num and (i, j) != pos:
                        return False
            return True

        def solve():
            empty = find_empty()
            if not empty:
                return True
            else:
                row, col = empty
                for num in range(1, 10):
                    if is_valid(num, (row, col)):
                        self.board[row][col] = num
                        if solve():
                            return True
                        self.board[row][col] = 0
                return False

        value = solve()
        self.update_cells()
        return value

    def update_cells(self):
        # Update the cells with the current board values
        for i in range(9):
            for j in range(9):
                if self.board[i][j] != 0:
                    self.cells[(i, j)].config(text=self.board[i][j], fg="black")
                else:
                    self.cells[(i, j)].config(text="", fg="black")

root = Tk()
sudoku_board = SudokuBoard(root)
root.mainloop()
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading