IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PyQt Python Discussion :

Coquille vide pour un sudoku


Sujet :

PyQt Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut Coquille vide pour un sudoku
    Bonsoir,
    non, non je ne me lance pas dans un concours d'haïku.

    Est-ce que quelqu'un a dans ses codes une coquille vide pour afficher
    une grille de type Sudoku ? Pour la résolution, pas de souci j'ai un code.

    Dans le cas contraire, j'essaierais de trouver un peu de temps pour le
    faire mais c'est un peu compliqué côté temps pour moi en ce moment.

  2. #2
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour rambc,

    Sur le web, j'ai au moins trouvé ça: http://lionel.textmalaysia.com/sudok...l#.UK3Dm9fQvwM.

    Si ça ne te convient pas et si tu n'as pas d'autres réponses, je te proposerais un échange: je te fabrique ta coquille, et tu me passes tes codes de résolution. La coquille, en PyQt4, ne devrait pas être très compliquée en utilisant QTableWidget, et la structure de données sous forme de liste de listes du genre matrice devrait permettre la recherche récursive dans un arbre.

    Il y a une dizaine d'années, je m'étais amusé à coder les algorithmes de résolution en... Lisp (="Lots of Insipid and Stupid Parentheses" ), y compris dans les cas complexes nécessitant des retours en arrière sur des tentatives infructueuses. C'était très amusant à faire, et ça marchait très bien (en console). C'est également intéressant de savoir fabriquer des grilles de sudoku à résoudre selon différents niveaux de complexité.

  3. #3
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Merci pour le lien.

    Côté résolution, rien de bien original. J'ai des idées pour la création de
    grilles. C'est dans le cadre d'une formation dans l'Éducation Nationale.

    Je mettrais le code final en ligne en Mars normalement (trop peu de
    temps libre cette année). Si d'ici là je ne t'ai pas contacté, relances-moi.

    Citation Envoyé par tyrtamos Voir le message
    Lisp ="Lots of Insipid and Stupid Parentheses"
    J'aime beaucoup !

  4. #4
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Comment pourrait-on faire pour obtenir les fonctionnalités suivantes visibles dans cette page et cette autre ?
    1. Chaque case non renseignée se remplira par un simple clic dessus puis une saisie au clavier.
    2. Chaque case non renseignée pourra, ou non, afficher des possibilités (toutes ou justes certaines).
    3. Chacune des possibilités affichées dans une case pourra avoir une petite mise en forme spécifique : encadrement et couleur de fond.
    4. J'aimerais dessiner des cercles et des traits par dessus la grille pour aider le joueur ou indiquer une résolution pas à pas.

    Mes questions sont de pures questions de mise en forme car j'ai presque fini mon "solveur" à quelques détails près.

    PS : le lien donné ci-dessus semble mort...

  5. #5
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour rambc,

    Je n'ai pas le temps pour l'instant de te terminer la coquille, je suis assez pris jusqu'à 1/2 mars.

    Cependant, je peux te confirmer que tout ce que tu souhaites est parfaitement réalisable. Voilà quelques éléments de principe:

    Grille utilisée: QTableWidget.

    Petit code de base pour créer la grille 9x9:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    from __future__ import division
    # Python 2.7
     
    import sys
    from copy import deepcopy
    from PyQt4 import QtCore, QtGui
     
    #############################################################################
    class Fenetre(QtGui.QWidget):
     
        # =======================================================================
        def __init__(self, parent=None):
            super(Fenetre, self).__init__(parent)
     
            # crée la grille 9x9
            self.table = QtGui.QTableWidget(self)
            self.nbrow, self.nbcol = 9, 9
            self.table.setRowCount(self.nbrow)
            self.table.setColumnCount(self.nbcol)
     
            # cache les entêtes horizontale et verticale
            self.table.horizontalHeader().hide()
            self.table.verticalHeader().hide()
     
            # définit les cases carrées 50 pixels x 50 pixels
            for row in xrange(0, self.nbrow):
                self.table.setRowHeight(row, 50)
                for col in xrange(0, self.nbcol):
                    self.table.setColumnWidth(col, 50)
     
            # remplit la grille avec des QTableWidgetItem
            for row in xrange(0, self.nbrow):
                for col in xrange(0, self.nbcol):
                    item = QtGui.QTableWidgetItem()
                    item.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
                    self.table.setItem(row, col, item)
     
            # définit la police de caractère par défaut de la table 
            font = QtGui.QFont()
            font.setFamily(u"DejaVu Sans")
            font.setPointSize(16)
            self.table.setFont(font)
     
            # taille de la fenêtre
            self.resize(53*9, 53*9)
     
            # positionne la table dans la fenêtre
            posit = QtGui.QGridLayout()
            posit.addWidget(self.table, 0, 0)
            self.setLayout(posit)
     
            # grille de base
            self.g0 =  [[0,0,0,0,2,0,9,0,1],
                        [0,0,0,0,0,0,0,0,3],
                        [0,8,0,3,0,0,4,5,0],
                        [0,4,7,0,0,5,0,8,0],
                        [0,0,0,0,0,0,0,0,0],
                        [0,2,0,9,0,0,7,4,0],
                        [0,9,5,0,0,2,0,3,0],
                        [6,0,0,0,0,8,0,0,0],
                        [7,0,4,0,6,0,0,0,0]]
     
            # intégre le delegate pour lignes en gras et les cases en couleur
            #self.delegate = MonDelegate(self.table)
            #self.table.setItemDelegate(self.delegate)
     
            # redessine les lignes en gras et les cases de couleur
            #self.delegate.grilleinit(self.g0)
     
            # initialise la grille courante
            self.g = deepcopy(self.g0)
     
            # affiche la grille courante
            self.affiche(self.g)
     
            # place le focus
            self.table.setFocus()
            self.table.setCurrentCell(0, 0)
     
        # =======================================================================
        def affiche(self, g):
     
            for row in xrange(0, len(g[0])):
                for col in xrange(0, len(g)):
                    if g[row][col]==0:
                        self.table.item(row, col).setText(u"")
                        self.table.item(row, col).setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable)
                    else:
                        self.table.item(row, col).setText(unicode(g[row][col]))
                        self.table.item(row, col).setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
     
            couleur = QtGui.QColor(160, 255, 160, 255) # vert clair
            self.table.item(2, 4).setBackgroundColor(couleur)
     
            couleur = QtGui.QColor(255, 160, 160, 255) # rouge clair
            self.table.item(6, 3).setBackgroundColor(couleur)
     
    #############################################################################
    if __name__ == "__main__":
        app = QtGui.QApplication(sys.argv)
        fen = Fenetre()
        fen.show()
        sys.exit(app.exec_())
    Cela donne déjà une grille complète, mais il reste à dessiner les lignes en gras pour séparer visuellement les groupes de cases 3x3. On peut aussi mettre les cases de départ ayant des chiffres en couleur (ici, en gris).

    Pour faire ça, je n'ai pas trouvé plus simple que de sous-classer QItemDelegate, et de surcharger sa méthode paint. Voilà comment on peut faire ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    #############################################################################
    def couleurcase(painter, option, couleur):
        """met le fond de la case dans la couleur demandée"""
        r = option.rect
        x, y, w, h = r.x()+1, r.y()+1, r.width()-2, r.height()-2
        if isinstance(couleur, (str, unicode)):
            coul = QtGui.QColor(couleur)
        elif isinstance(couleur, (list, tuple)):
            if len(couleur) == 3:
                r, g, b = couleur
                t = 255
            else:
                r, g, b, t = couleur
            coul = QtGui.QColor(r, g, b, t)
        painter.fillRect(x, y, w, h, coul)
     
    #############################################################################
    def bordurecase(painter, option, ligne):
        """met en gras la bordure d'une case d'un QTableWidget dans le paint d'un 
           delegate: ligne 'h'=haute, 'g'=gauche, 'd'=droite, 'b'=basse
        """
        r = option.rect
        x, y, w, h = r.x(), r.y(), r.width(), r.height()
        if ligne=='h':
            x1, y1, x2, y2 = x, y, x+w, y
        elif ligne=='d':
            x1, y1, x2, y2 = x+w, y, x+w, y+h
        elif ligne=='b':
            x1, y1, x2, y2 = x+w, y+h, x, y+h
        elif ligne=='g':
            x1, y1, x2, y2 = x, y+h, x, y
        else:
            return
        pen = QtGui.QPen()
        pen.setWidth(2)
        painter.setPen(pen)
        painter.drawLine(x1, y1, x2, y2)
     
    #############################################################################
    class MonDelegate(QtGui.QItemDelegate):
     
        #========================================================================
        def __init__(self, parent=None):
            super(MonDelegate, self).__init__(parent)
     
        #========================================================================
        def grilleinit(self, g):
            self.g0 = g
     
        #========================================================================
        def paint(self, painter, option, index):    
            """appelé case par case pour en dessiner le contenu"""        
     
     
            row, col = index.row(), index.column() 
            if row==0 or row==3 or row==6:
                if col in[0,3,6]:
                    bordurecase(painter, option, 'g')
                    bordurecase(painter, option, 'h')
                elif col==8:
                    bordurecase(painter, option, 'd')
                    bordurecase(painter, option, 'h')
                else:
                    bordurecase(painter, option, 'h')
            elif row in [1,2,4,5,7]:
                if col in [0,3,6]:
                    bordurecase(painter, option, 'g')
                elif col==8:
                    bordurecase(painter, option, 'd')
            elif row==8:
                if col in[0,3,6]:
                    bordurecase(painter, option, 'g')
                    bordurecase(painter, option, 'b')
                elif col==8:
                    bordurecase(painter, option, 'd')
                    bordurecase(painter, option, 'b')
                else:
                    bordurecase(painter, option, 'b')    
     
            # mettre la couleur souhaitée dans les cases de départ ayant un numéro 
            if self.g0[row][col]!=0:
                couleurcase(painter, option, [200,200,200])
     
            QtGui.QItemDelegate.paint(self, painter, option, index)
    Et dans la classe Fenetre, on fait à l'initialisation (les lignes y sont déjà, il suffit de les dé-commenter):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            # intégre le delegate pour lignes en gras et les cases en couleur
            self.delegate = MonDelegate(self.table)
            self.table.setItemDelegate(self.delegate)
     
            # redessine les lignes en gras et les cases de couleur
            self.delegate.grilleinit(self.g0)
    Et voilà ce que ça donne:



    Les cases grises qui ont un chiffre au départ sont sélectionnables, mais en lecture seule.

    La case bleue est la case qui a le focus.

    J'ai mis à titre d'exemple des cases roses et vertes pour remplacer les dessins fournis (rond vert et croix rouge) parce que c'est plus simple à programmer. Si ça ne va pas, on peut trouver autre chose.

    Pour le reste:

    Il est possible de mettre dans une case en tout petit les chiffres permis, il suffit de placer à la volée un QTextEdit au lieu du QTableWidgetItem, et d'écrite en "richtext", c'est à dire en html (syntaxe réduite cependant). Ce ne sera peut-être pas facile à mettre au point, mais ça marchera. Et puisqu'il s'agit de html, on devrait pouvoir mettre une image en option.

    Voilà le départ! Pour le reste, il faudra attendre un peu...

    A+

  6. #6
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Merci,
    cela fait un bon départ. Je vais étudier cela. Va juste falloir que je me remette à PyQt.

    Un grand merci.

    PS : je posterais ici mes avancés, s'il y en a...

Discussions similaires

  1. Coquille vide pour un snake
    Par rambc dans le forum PyQt
    Réponses: 7
    Dernier message: 19/03/2013, 13h59
  2. Sélection d'une valeur vide pour un select
    Par Tiaps dans le forum Struts 1
    Réponses: 2
    Dernier message: 30/06/2006, 10h20
  3. [Tableaux] Tableau valeur vide pour une clé
    Par hisy dans le forum Langage
    Réponses: 3
    Dernier message: 17/01/2006, 11h49
  4. Réponses: 4
    Dernier message: 12/09/2005, 09h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo