Bonjour à tous,
je vous présente un petit programme que je viens de développer et qui a été une bonne occasion pour me remettre à Python et apprendre Tkinter
c'est un programme qui permet d'entrer un tableau sudoku puis d'afficher la solution
au final, le fichier se compose de deux fichiers, un gère la résolution du sudoku, l'autre gère l'interface
tout d'abord le fichier fcts_sudoku.py
#!/usr/bin/env python
#-*- coding:utf-8 -*-
"""
Programme Sudoku
fait le 11/10/2014
Python 2.7.6
"""
import numpy as np
#import time
# ============================================================================
# Classes
# ============================================================================
class Sudoku():
"""
Permet de définir et résoudre un sudoku
"""
def __init__(self, data):
"""
initialise le sudoku
"""
self.tableau = data # tableau initiale - celui à résoudre
self.solution = np.zeros((9, 9)) # initialisation - tableau solution
self.iteration = 0 # nb d'itérations avant résultat final
# self.solve()
def __repr__(self):
"""
permet d'affichier le tableau initiale et la solution
"""
print "\nTableau initiale\n"
affiche_tab(self.tableau)
print "\nSolution\n"
affiche_tab(self.solution)
print "\nNb d'itérations :", self.iteration
return ""
def ligne(self, i):
"""
liste des nb dans une ligne
"""
return self.solution[i, :]
def colonne(self, j):
"""
liste des nb dans une colonne
"""
return self.solution[:, j]
def pos_carre(self, i, j):
"""
retourne la position d'un sous tableau sudoku
"""
return 3*(i//3), 3*(j//3)
def carre(self, i, j):
"""
retourne l'ensemble de nb d'un sous tableau
"""
pos_i, pos_j = self.pos_carre(i, j)
sous_tableau = self.solution[pos_i:pos_i+3, pos_j:pos_j+3]
return sous_tableau
def presence_valeur(self, i, j, val):
"""
test booleen pour savoir si un chiffre est déjà dans le tableau
"""
return (val in self.ligne(i)) \
or (val in self.colonne(j)) \
or (val in self.carre(i, j))
def case_vide(self, i, j):
"""
test pour savoir si la case est rempli ou non
"""
return self.tableau[i, j] == 0
def avance(self, i, j, val):
"""
détermine les indices de la case suivante pour la recherche
"""
# on avance
j = j+1
val = 1
if j > 9:
i = i+1
j = 1
return i, j, val
def recule(self, i, j, val):
"""
détermine les indices de la case précédente pour la recherche
"""
# on recule
j = j-1
if j < 0:
j = 8
i = i-1
# on efface la valeur precedente
# puis on teste la valeur suivante
val = self.solution[i, j]+1
if self.case_vide(i, j):
self.solution[i, j] = 0
else:
i, j, val = self.recule(i, j, val)
return i, j, val
def deplacement(self, i, j, val):
"""
gère le suivi de la case de recherche
"""
if val < 10:
# print "en avant"
return self.avance(i, j, val)
else:
# print "en arrière"
return self.recule(i, j, val)
def solve(self):
"""
resolution récursive du sudoku
ne gère pas les sudoku sans solution
"""
self.solution = np.copy(self.tableau)
# on parcours tout le self.tableau
i = 0
while i < 9:
j = 0
val = 1
while j < 9:
# on teste toutes les valeurs
if self.case_vide(i, j) and val < 10:
if self.presence_valeur(i, j, val):
val = val+1
else:
self.solution[i, j] = val
self.iteration = self.iteration + 1
# affiche_tab(self.solution)
# time.sleep(0.1)
i, j, val = self.deplacement(i, j, val)
else:
i, j, val = self.deplacement(i, j, val)
i = i + 1
# ============================================================================
# Fonctions
# ============================================================================
def affiche_tab(tableau):
"""
affiche le sudoku en console
"""
i, j = 0, 0
for i in range(9):
if i%3 == 0:
print "-------------------------"
for j in range(9):
if j%3 == 0:
print "|",
if tableau[i, j] == 0:
print "_",
else:
print tableau[i, j],
print "|"
print "-------------------------"
# ============================================================================
# Programme
# ============================================================================
if __name__ == '__main__':
# tab_inconnu = [[0,0,0,0,0,0,0,0,0],
# [0,0,0,0,0,0,0,0,0],
# [0,0,0,0,0,0,0,0,0],
# [0,0,0,0,0,0,0,0,0],
# [0,0,0,0,0,0,0,0,0],
# [0,0,0,0,0,0,0,0,0],
# [0,0,0,0,0,0,0,0,0],
# [0,0,0,0,0,0,0,0,0],
# [0,0,0,0,0,0,0,0,0]]
# tab_inconnu = [[3,0,0,0,7,6,8,0,0],
# [0,6,5,0,4,3,0,7,0],
# [9,0,0,8,0,0,0,0,3],
# [0,0,2,6,0,0,0,8,0],
# [0,3,9,0,8,0,2,6,0],
# [0,8,0,0,0,7,5,0,0],
# [5,0,0,0,0,2,0,0,7],
# [0,4,0,7,1,0,9,5,0],
# [0,0,6,5,9,0,0,0,8]]
tab_inconnu = [[0,2,0,1,0,0,0,0,0],
[0,0,5,0,2,0,4,0,0],
[1,3,0,0,4,8,0,0,0],
[0,6,0,0,8,0,0,0,1],
[0,1,0,2,0,4,0,9,0],
[4,0,0,0,7,0,0,2,0],
[0,0,0,8,9,0,0,5,2],
[0,0,9,0,1,0,6,0,0],
[0,0,0,0,0,6,0,7,0]]
tab_inconnu = np.array(tab_inconnu)
mSudok = Sudoku(tab_inconnu)
# start_time = time.time()
mSudok.solve()
# elapsed_time = time.time() - start_time
print mSudok
# print elapsed_time
puis le fichier Jeu.py
#!/usr/bin/env python
#-*- coding:utf-8 -*-
"""
Résoud des sudokus - interface
Python 2.7.6
"""
from fcts_sudoku import Sudoku
import Tkinter
import numpy as np
# ============================================================================
# Classes
# ============================================================================
class Interface():
"""
Définit l'interface du jeu sudoku
"""
def __init__(self):
"""
initialisation
"""
# fenetre
self.fenetre=Tkinter.Tk()
self.fenetre.title("Résolveur de Sudoku")
self.fenetre.wm_attributes("-topmost", 1) # toujours au dessus
# boutons
self.bResoudre=Tkinter.Button(self.fenetre, text = 'Résoudre', command = self.fResoudre)
self.bResoudre.grid(column=0,row=10,columnspan=3)
self.bRelancer=Tkinter.Button(self.fenetre, text = 'Nouveau', command = self.fNouveau)
self.bRelancer.grid(column=3,row=10,columnspan=3)
self.bQuitter=Tkinter.Button(self.fenetre, text = 'Quitter', command = self.fQuitter )
self.bQuitter.grid(column=6,row=10,columnspan=3)
# creation des 9x9 cases
self.fcreation_entree()
def start(self):
"""
lance le jeu
"""
self.fenetre.mainloop()
def fcreation_entree(self):
"""
initialisation des entrees (Entry) et ajout a la fenetre
"""
self.entree = []
for i in range(9):
self.entree+=[[]]
for j in range(9):
self.entree[i]+=[Tkinter.StringVar()]
for i in range(9):
for j in range(9):
Tkinter.Entry(self.fenetre, textvariable = self.entree[i][j],width=3,font="18",justify='center').grid(column=i,row=j)
self.entree[i][j].set( "")
def fQuitter(self):
"""
quitter l'application
"""
self.fenetre.destroy()
return
def fResoudre(self):
"""
résoud le sudoku et affiche la solution
ne gère pas les sudoku sans solution
"""
# on recupere les valeurs
tableau = np.zeros((9, 9))
for i in range(9):
for j in range(9):
val=self.entree[i][j].get()
if isValid(val):
val=int(val)
else:
val=0
tableau[i,j]=val
# on resoud le sudoku
mSudok = Sudoku(tableau)
mSudok.solve()
# on affiche la solution
for i in range(9):
for j in range(9):
self.entree[i][j].set( str(int(mSudok.solution[i, j])))
return
def fNouveau(self):
"""
on reinitialise le tableau d'entrees (Entry)
"""
for i in range(9):
for j in range(9):
self.entree[i][j].set( "")
return
# ============================================================================
# Fonctions
# ============================================================================
def isValid(val):
"""
test la valeur dans les cases
- vrai si nombre entier entre 1 et 10
- faux sinon
"""
try:
val=int(val)
if val>0 and val<10:
return True
else:
return False
except:
return False
# ============================================================================
# Programme
# ============================================================================
if __name__ == '__main__':
Jeu=Interface()
Jeu.start()
pour lancer le jeu, il suffit de lancer le fichier Jeu.py
-- soit en ligne de commande
python Jeu.py
-- soit en interface graphique,
clic droit sur le fichier Jeu.py > Propriétés > Permissions > Autoriser ce fichier à être exécuté ...
tout fonctionne bien, par contre je ne gère par les sudokus sans solution, l'interface peut être améliorée... je pense que je vais en rester là
si vous avez des critiques sur ma manière de programmer, je suis intéressé, étant plutôt autodidacte en programmation et python