def ens_cell0(grid, reverse=False): """ return all cells with a value equal at 0 or if reverse is True, return all cells with a value different at 0 :param grid: a sudoku grid :type grid: grid :param reverse: (optional) defaults set to False. If True, return the reverse of a normal using :type reverse: bool :return: a list of all cell with a value at 0 if reverse is True and the reverse if not :rtype: list of cells :UC: none :Examples: >>> grid = sudoku_grid.make_grid() >>> len(ens_cell0(grid)) 81 >>> len(ens_cell0(grid,reverse=True)) 0 """ cell_list = list() for ind_line in range(9): for cell in sudoku_grid.get_line(grid, ind_line): if cells.get_cellvalue(cell) == '0' and not reverse: cell_list.append(cell) if reverse and cells.get_cellvalue(cell) != '0': cell_list.append(cell) return cell_list
def is_solved(grid): """ say if grid is a resolved grid :param grid: a sudoku's grid :type grid: grid :return: True if it's resolved and False if not :rtype: bool :UC: none """ for ind_line in range(9): cell_list = sudoku_grid.get_line(grid, ind_line) if len(set(cells.get_cellvalue(cell) for cell in cell_list)) != 9: return False for ind_col in range(9): cell_list = sudoku_grid.get_colomn(grid, ind_col) if len(set(cells.get_cellvalue(cell) for cell in cell_list)) != 9: return False for ind_square in range(9): cell_list = sudoku_grid.get_square(grid, ind_square) if len(set(cells.get_cellvalue(cell) for cell in cell_list)) != 9: return False return True
def __correction(button_grid): """ This function manage the correction of values enter by the user. """ global grid, string if not len(sudoku_solver.ens_cell0(grid, reverse=True)): showerror("ERROR", "Open a grid...") return None try: sudoku_solver.search_sol(sudoku_grid.make_grid(string), background=True) except: showerror("ERROR", "It's impossible to solve your grid") return None try: sol = sudoku_solver.ens_sol.pop() except: showwarning("WARNING", "There is no solution find for your grid") return None solved_grid = sudoku_grid.make_grid(sol) wrong_cells_list = list() for ind_line in range(9): for ind_col in range(9): cell = sudoku_grid.get_cell(grid, ind_line, ind_col) value = cells.get_cellvalue(cell) if int(value): solved_cell = sudoku_grid.get_cell(solved_grid, ind_line, ind_col) solved_value = cells.get_cellvalue(solved_cell) button = sudoku_grid.get_cell(button_grid, ind_line, ind_col) if value != solved_value and button["state"] == "normal": button.config(bg="red") wrong_cells_list += [(cell, (ind_line, ind_col), solved_value, button)] if len(wrong_cells_list): boolean = askyesno( "Corrected", "Do you want that the algorithm corrected your errors?") if boolean: for saved_tuple in wrong_cells_list: cell = saved_tuple[0] ind_line, ind_col = saved_tuple[1][0], saved_tuple[1][1] solved_value = saved_tuple[2] button = saved_tuple[3] cells.set_cellvalue(cell, solved_value) __redraw(button_grid, ind_line, ind_col, solver=True) button.config(bg="green") else: showinfo("Corrected", "All cell's values are checked.")
def __save(): """ This function save your sudoku grid. """ global grid, string save_value = list() for ind_line in range(9): save_value.insert(ind_line, list()) for ind_col in range(9): cell = sudoku_grid.get_cell(grid, ind_line, ind_col) value = cells.get_cellvalue(cell) save_value[ind_line].insert( ind_col, { "value": value, "computer value": string[ind_col + 9 * ind_line] == value and int(value) }) stream = tkfdial.asksaveasfile(mode="wb", title="Save", filetypes=[("GRD", ".grd")], defaultextension=".grd") if stream: my_pickle = pickle.Pickler(stream) my_pickle.dump(save_value) stream.close() showinfo("Save", "You have saved your sudoku grid")
def __write_grid(button_grid, var, root): """ This function write a grid with th edifficulty choosen by the user. """ global string, grid import random difficultys_list = ["easy", "medium", "hard", "fiendish"] if var.get() == 4: with open("data/sudoku17.bdd", "r") as stream: string = random.choice(stream.readlines())[:81] else: temp = ["", ""] while temp[0] != difficultys_list[var.get()]: with open("data/sudokus.bdd", "r") as stream: temp = random.choice(stream.readlines()).split(":") string = temp[-1][:81] grid = sudoku_grid.make_grid(string) for ind_line in range(9): for ind_col in range(9): __redraw(button_grid, ind_line, ind_col) cell = sudoku_grid.get_cell(grid, ind_line, ind_col) button = sudoku_grid.get_cell(button_grid, ind_line, ind_col) if int(cells.get_cellvalue(cell)): button.config(state="disabled") else: button.config(state="normal") root.destroy()
def print_grid(grid): """ print the sudoku's grid :param grid: a sudoku's grid :type grid: grid :return: None :rtype: NoneType :Action: print the grid :UC: none :Examples: >>> grid = make_grid(val_test) >>> print_grid(grid) +-------+-------+-------+ | . 1 2 | 3 4 5 | 6 7 8 | | . 1 2 | 3 4 5 | 6 7 8 | | . 1 2 | 3 4 5 | 6 7 8 | +-------+-------+-------+ | . 1 2 | 3 4 5 | 6 7 8 | | . 1 2 | 3 4 5 | 6 7 8 | | . 1 2 | 3 4 5 | 6 7 8 | +-------+-------+-------+ | . 1 2 | 3 4 5 | 6 7 8 | | . 1 2 | 3 4 5 | 6 7 8 | | . 1 2 | 3 4 5 | 6 7 8 | +-------+-------+-------+ """ print('+' + '-------+' * 3) for l1 in range(3): for l2 in range(3): print('|', end='') for c1 in range(3): for c2 in range(3): if cells.get_cellvalue( get_cell(grid, l1 * 3 + l2, c1 * 3 + c2)) == '0': print(' .', end='') else: print(' ' + cells.get_cellvalue( get_cell(grid, l1 * 3 + l2, c1 * 3 + c2)), end='') print(' |', end='') print() print('+' + '-------+' * 3)
def __RAZ(button_grid): """ This funciton redraws the board with all cell's values at '0'. :param button_grid: the board of buttons :type button_grid: list of list of ``button`` """ global grid for ind_line in range(9): for ind_col in range(9): cell = sudoku_grid.get_cell(grid,ind_line,ind_col) if int(cells.get_cellvalue(cell)): cells.set_cellvalue(cell,'0') __redraw(button_grid,ind_line,ind_col)
def remove(grid): """ print a random grid with removing cells from grid with one solution :param grid: a sudoku grid :type grid: grid :return: the string of a random sudoku's grid with removed cells :rtype: str :UC: none """ global ens_sol cell_list = ens_cell0(grid, reverse=True) if len( cell_list ) <= 17: #il est impossible d'avoir une grille de sudoku avec moins de 17 remplies si l'on veut avoir une unique solution ens_sol = set() #on réinitialise les variables globales compt_rec = 0 father = "SUDO" sol_way = list() return sudoku_grid.grid2string(grid) else: cell = cell_list[random.randint( 1, len(cell_list) - 1 )] #on récupère une cellule au hasard dans l'ensemble des cellules non vides value = cells.get_cellvalue(cell) cells.set_cellvalue(cell, '0') string = sudoku_grid.grid2string( grid ) #le fait de faire cette transformation nous permet de faire une mise à jour des valeurs hipothétiques search_sol(sudoku_grid.make_grid(string), background=True) if len(ens_sol) == 1: ens_sol = set() #on réinitialise les variables globales compt_rec = 0 father = "SUDO" sol_way = list() return remove(sudoku_grid.make_grid(string)) else: ens_sol = set() #on réinitialise les variables globales compt_rec = 0 father = "SUDO" sol_way = list() cells.set_cellvalue(cell, value) return sudoku_grid.grid2string(grid)
def not_solved(grid): """ say if it's impossible to find solution of the sudoku's grid :param grid: a sudoku's grid :type grid: grid :return: True if it's impossible to find solution and False if not :rtype: bool :UC: none """ for i in range(9): for cell in sudoku_grid.get_line(grid, i): if cells.get_cellvalue( cell) == '0' and not cells.get_cellhipo(cell): return True #renvoie True si une cellules ne possède aucune valeur hipothetic et que sa valeur est 0 return False
def __redraw(button_grid, ind_line, ind_col, solver=False): """ This function draws the board. Position ind_line and ind_col are used to test which number icon has to be drawn. It's also manage it must to create a finished popup with solver. """ global grid button = sudoku_grid.get_cell(button_grid, ind_line, ind_col) cell = sudoku_grid.get_cell(grid, ind_line, ind_col) value = cells.get_cellvalue(cell) button.config(image=img[int(value)]) if sudoku_solver.is_solved(grid) and not len( sudoku_solver.ens_cell0(grid)): __disabled_grid(button_grid) if not solver: showinfo("CONGRATULATIONS", "You have finished the sudoku")
def __redraw(button_grid,ind_line,ind_col): """ This function draws the board. Position ind_line and ind_col are used to test which number icon has to be drawn. :param button_grid: the board of buttons :type button_grid: list of list of ``button`` :param ind_line: the line of the cell :type ind_line: int :param ind_col: the column of the cell :type ind_col: int """ global grid button = sudoku_grid.get_cell(button_grid,ind_line,ind_col) cell = sudoku_grid.get_cell(grid,ind_line,ind_col) value = cells.get_cellvalue(cell) button.config(image=img[int(value)])
def grid2string(grid): """ return the string from the grid :param grid: a grid of sudoku :type grid: grid :return: a srting of values from the sudoku :rtype: str :UC: none :Examples: >>> string = "490001007000045030382600050003070401800902005907030600030006529020850000500700013" >>> grid = make_grid(string) >>> grid2string(grid) == string True """ string = '' for ind_line in range(9): for cell in get_line(grid, ind_line): string += cells.get_cellvalue( cell ) #on cherche à reconstruire la chaîne de caractères correspondante à la grille que l'on donne return string
def create(string='0'*81): """ this function creates the graphical board from a solver. It also launches the event loop. Thus, this is the only function to run to have a functional graphical board. :param string: the sudoku :type string: str :return: None :rtype: NoneType """ global img,win,grid,recursion_check,image_check,remove_check,talkative_check,start_button,enter_button grid = sudoku_grid.make_grid(string) win = tk.Tk() win.title('Sudoku Solver') iconpath = os.path.join(os.path.dirname(os.path.abspath(__file__)), "icons") img = [ tk.PhotoImage(file=os.path.join(iconpath, "0.gif")), tk.PhotoImage(file=os.path.join(iconpath, "1.gif")), tk.PhotoImage(file=os.path.join(iconpath, "2.gif")), tk.PhotoImage(file=os.path.join(iconpath, "3.gif")), tk.PhotoImage(file=os.path.join(iconpath, "4.gif")), tk.PhotoImage(file=os.path.join(iconpath, "5.gif")), tk.PhotoImage(file=os.path.join(iconpath, "6.gif")), tk.PhotoImage(file=os.path.join(iconpath, "7.gif")), tk.PhotoImage(file=os.path.join(iconpath, "8.gif")), tk.PhotoImage(file=os.path.join(iconpath, "9.gif")) ] button_grid = list() grid_frame = tk.Frame(win,bd=1.5,bg="black") grid_frame.grid(column=0,row=0,columnspan=9,rowspan=9,padx=3,pady=3) for ind_line in range(9): button_grid.insert(ind_line,[]) for ind_col in range(9): cell = sudoku_grid.get_cell(grid, ind_line, ind_col) value = cells.get_cellvalue(cell) button = tk.Button(grid_frame, padx=0, pady=0, width=30, height=30, image=img[int(value)]) button.grid(column=ind_col, row=ind_line) button_grid[ind_line].insert(ind_col, button) button.config(command=partial(__change,button_grid,ind_line,ind_col)) for ind_square in range(9): button_list = sudoku_grid.get_square(button_grid,ind_square) for button in button_list: if ind_square%2: button.config(bg="grey") else: button.config(bg="white") options_frame = tk.Frame(win) options_frame.grid(column=9,row=0,rowspan=10) text = tk.Label(options_frame,text = "options:",font = "bold 16 italic") text.grid(row = 1,pady=10) image_var = tk.IntVar() image_check = tk.Checkbutton(options_frame,text = "arbre",variable = image_var) image_check.grid(row = 2,sticky="nw",padx=2,pady=5) remove_var = tk.IntVar() remove_check = tk.Checkbutton(options_frame,text = "remove",variable = remove_var) remove_check.grid(row = 3,sticky="nw",padx=2,pady=5) talkative_var = tk.IntVar() talkative_check = tk.Checkbutton(options_frame,text = "talkative",variable = talkative_var) talkative_check.grid(row = 4,sticky="nw",padx=2,pady=5) recursion_var = tk.IntVar() recursion_check = tk.Checkbutton(options_frame,text = "recursion",variable = recursion_var) recursion_check.grid(row = 5,sticky="nw",padx=2,pady=5) enter_button = tk.Button(options_frame, text = "Write a grid") enter_button.grid(row = 6,padx=2,pady=30) enter_button.config(bd=2,command = partial(__popup,button_grid)) image = tk.PhotoImage(file = 'icons/help-icon.png') can = tk.Canvas(options_frame,width = 40,height = 40) item = can.create_image(24,24,image = image) can.grid(row = 7) can.bind("<Button-1>",help_option) start_button = tk.Button(win, text="run") start_button.grid(column=1,row=9,pady=5) start_button.config(bd=2,command = partial(__run,button_grid,rec=recursion_var,img=image_var,rm=remove_var,t=talkative_var)) raz_button = tk.Button(win, text="RAZ") raz_button.grid(column=4,row=9) raz_button.config(bd=2,command = partial(__RAZ,button_grid)) quit_button = tk.Button(win, text="exit") quit_button.grid(column=7,row=9) quit_button.config(bd=2,command = back) win.mainloop()