def testCase(self): G = [[1, 0, 3, 0], [3, 0, 1, 2], [4, 0, 2, 3], [2, 0, 4, 1]] g = main.grille() g.importGrille(G, 2, 2) self.assertEqual(g[0][1].possibilites, [1, 2, 3, 4]) self.assertEqual(g[3][3].possibilites, []) self.assertEqual(g[0][1].bloc_ap, 0) self.assertEqual(g[3][3].bloc_ap, 3) self.assertEqual(g[0][1].colonne_ap, 1) self.assertEqual(g[3][3].ligne_ap, 3)
def testSelectGrille(self): G = [[1, 0, 3, 0], [3, 0, 1, 2], [4, 0, 2, 3], [2, 0, 4, 1]] g = main.grille() g.importGrille(G, 2, 2) self.assertEqual([i.sol for i in g.bloc(1)], [3, 0, 1, 2]) self.assertEqual([i.sol for i in g.bloc(3)], [2, 3, 4, 1]) self.assertEqual([i.sol for i in g.ligne(2)], [4, 0, 2, 3]) self.assertEqual([i.sol for i in g.ligne(0)], [1, 0, 3, 0]) self.assertEqual([i.sol for i in g.colonne(3)], [0, 2, 3, 1]) self.assertEqual([i.sol for i in g.colonne(1)], [0, 0, 0, 0])
def testSolv(self): G = [[1, 0, 3, 0], [3, 0, 1, 2], [4, 0, 2, 3], [2, 0, 4, 1]] S = [[1, 2, 3, 4], [3, 4, 1, 2], [4, 1, 2, 3], [2, 3, 4, 1]] g1 = main.grille() g2 = main.grille() s = main.grille() g1.importGrille(G, 2, 2) g2.importGrille(G, 2, 2) s.importGrille(S, 2, 2) solv1 = Backtrack(g1) solv2 = SolvFunc(g2) solv1.solve() solv2.solve() self.assertTrue(g1.compare(s)) self.assertTrue(g2.compare(s)) A = [[3, 4, 0, 2, 0, 6], [6, 0, 0, 0, 4, 3], [1, 2, 3, 6, 5, 0], [0, 0, 6, 3, 2, 0], [5, 6, 0, 4, 3, 2], [2, 3, 4, 1, 6, 0]] S2 = [[3, 4, 5, 2, 1, 6], [6, 1, 2, 5, 4, 3], [1, 2, 3, 6, 5, 4], [4, 5, 6, 3, 2, 1], [5, 6, 1, 4, 3, 2], [2, 3, 4, 1, 6, 5]] a1 = main.grille() a2 = main.grille() s2 = main.grille() a1.importGrille(A, 3, 2) a2.importGrille(A, 3, 2) s2.importGrille(S2, 3, 2) solv3 = Backtrack(a1) solv4 = SolvFunc(a2) solv3.solve() solv4.solve() self.assertTrue(a1.compare(s2)) self.assertTrue(a2.compare(s2))
def testSolverFunctions(self): G = [[1, 0, 3, 0], [3, 0, 1, 2], [4, 0, 2, 3], [2, 0, 4, 1]] C = [[1, 0, 3, 0], [3, 0, 1, 2], [4, 1, 2, 3], [2, 0, 4, 1]] g1 = main.grille() c = main.grille() g1.importGrille(G, 2, 2) c.importGrille(C, 2, 2) solv = SolvFunc(g1) solv.celib(g1.ligne(0)) solv.celib(g1.ligne(2)) solv.sol(g1.ligne(2)) self.assertEqual(g1[0][1].possibilites, [2, 4]) self.assertTrue(g1.compare(c)) g2 = main.grille() g2.importGrille(G, 2, 2) solv = SolvFunc(g2) solv.remove_pos(g2.ligne(0)) self.assertEqual(g2[0][1].possibilites, [2, 4]) g3 = main.grille() g3.importGrille(G, 2, 2) solv = SolvFunc(g3) solv.candidat_bloque(g3[0][1]) self.assertEqual(g3[0][1].possibilites, [2, 4])
def solveClick(self): """Traduit la grille rentrée par l'utilisateur en grille, la résout et fait afficher la solution""" grille_ihm = [] # on rentre tous les nombres dans une liste for i in range(x * y): row = [] for j in range(x * y): item = self.tableWidget.item(i, j) if item is None: item = 0 else: item = item.text() if item not in [str(i) for i in range(0, x * y + 1)]: item = 0 row.append(int(item)) grille_ihm.append(row[:]) grille_backend = main.grille() grille_backend.importGrille( grille_ihm, x, y) # on crée la grille correspondante pour pouvoir la résoudre solver = SolvFunc(grille_backend) solver.solve() self.showSolution(grille_backend)
def generate(self): lvl = self.level XX = self.x YY = self.y n = XX * YY l = [] lcolonnes = [] #nbtry = 0 Gbase = grille() gbase = [] for i in range(n): l.append(i + 1) """gorigine = [[1, 2, 3, 4, 5, 6, 7, 8, 9], [4, 5, 6, 7, 8, 9, 1, 2, 3], [7, 8, 9, 1, 2, 3, 4, 5, 6], [2, 3, 4, 5, 6, 7, 8, 9, 1], [3, 4, 5, 6, 7, 8, 9, 1, 2], [5, 6, 7, 8, 9, 1, 2, 3, 4], [6, 7, 8, 9, 1, 2, 3, 4, 5], [8, 9, 1, 2, 3, 4, 5, 6, 7], [9, 1, 2, 3, 4, 5, 6, 7, 8]] """ # Création de la grille complète de base depart = random.choice( l) #prend au hasard un chiffre pour le placer en haut à gauche for i in range(n): lignebase = [] for j in range(n): if ( depart + j + i % YY * XX + i // YY ) % n == 0: # génère à partir du chiffre de départ une grille cconstruite de la même manière que gorigine en commentaire ligne 34 lignebase.append( n ) # en travaillant modulo n on remplace les 0 par n pour générer la grille pleine else: lignebase.append((depart + j + i % YY * XX + i // YY) % n) gbase.append(lignebase) # Création de la grille complète mélangée lN = range(n) lXX = range(XX) lYY = range(YY) for i in range(n): lcolonnes.append([]) for i in range(10): a, b = random.choice(lN), random.choice( lYY ) # on choisit "a" un numéro de ligne et "b" un indice compris entre 0 et le (nombre de ligne par zone)-1 exemple pour un 3*3 b appartient a [0,1,2] gbase[a], gbase[a // YY * YY + b] = gbase[a // YY * YY + b], gbase[ a] # on échange les lignes d'indice "a" avec la ligne dont l'indice à l'intérieur de la zone de "a" et "b" for i in range(1): a, b = random.choice(lN), random.choice( lXX) # même opération avec les colonnes for j in range(n): gbase[j][a], gbase[j][a // XX * XX + b] = gbase[j][a // XX * XX + b], gbase[j][a] # Création de la grille avec trous nbtrous = 0 Ltrous = [] sauvegarde = 0 c = 0 d = 0 e = 0 f = 0 Lindices = range(n) if self.level == 1: nbtrous = int( (n**1.5) ) # on détermine un nombre de trous en fonction du niveau de difficulté souhaité # pour le niveau un on aura par exemple 4 trous pour 16 cases pour un 2*2 et 27 trous pour 81 cases pour un 3*3 cpt = 0 flag = True while cpt < nbtrous: c, d = random.choice(Lindices), random.choice( Lindices ) # je choisis au hasard un couple de coordonnées pour mettre un trou while [c, d] in Ltrous: c, d = random.choice(Lindices), random.choice( Lindices ) # cette boucle s'assure que l'on ne troue pas la grille deux fois au même endroit sauvegarde = gbase[c][d] gbase[c][d] = 0 try: Gbase = grille() solution = SolvFunc( Gbase.importGrille(gbase, XX, YY) ) # on vérifie à chaque fois si la grille est toujours soluble, sinon on remet le terme enlevé et on reprend un nouveau trou except ValueError: flag = False gbase[c][d] = sauvegarde pass """for i in range(10): # cette partie en commentaire avait pour but de vérifier l'unicité de la solution, mais étant donné le fait que l'on Gbase = grille() # teste les solutions toujours avec le même solveur, qui résoud toujours avec la même logique, il nous renvoie toujours une seule solution. SolvFunc(Gbase.importGrille(gbase, XX, YY)) # mais comme notre solveur se base sur des techniques "à la main" utilisées par des êtres humains, lors de la résolution d'un sudoku on remplie Gsolution=Gbase.copy() # case si et seulement si on est certain qu'il ne reste qu'une unique possibilité, partant de ce principe le solveur devrait être incapable if SolvFunc(Gbase.importGrille(gbase, XX, YY))==solution: # de résoudre le problème s'il y avait plusieur solution. Ce qui n'était pas du tout le cas avec le backtracking flag=flag and True else: flag=flag and False""" if flag == True: cpt += 1 else: flag = True Gfin = grille() Gfin.importGrille(gbase, XX, YY) # je génère la grille et la retourne return Gfin