Programmer le jeu The Genius Square sur Python

Signaler
-
Messages postés
13932
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 janvier 2021
-
Bonjour,

Pour un projet en cours, je dois programmer le jeu The Genius Square (si vous ne connaissez pas, voici un lien qui explique le principe du jeu : https://www.philibertnet.com/fr/the-happy-puzzle-company/76246-the-genius-square-732068459932.html#tab-features

J'ai programmé le plateau de jeu et le placement aléatoire des "bloqueurs" selon le lancer des 7 dés correspondant à ceux du jeu.
J'ai également programmé une fonction qui permet de placer une pièce sur le plateau dans un espace disponible(qui tient compte des bloqueurs et des pièces déjà placées) ainsi qu'une fonction capable de déplacer une pièce déjà placée à sa position possible suivante.

Pour expliciter, je peux placer la pièce n°1 puis la n°2 et si je n'ai pas de place disponible pour la n°2, je peux déplacer la n°1 à un autre endroit afin de réessayer de placer la 2 (je ne sais pas si je suis suffisamment claire, dites moi si vous avez besoin de plus de détails ^^)

Mon problème est le suivant : j'essaie maintenant de programmer la fonction résolution() capable de résoudre le puzzle en entier et les combinaisons que j'ai essayé ne permettent jamais de placer les 9 pièces (il en manque toujours une).
Mon raisonnement est le suivant : je lui demande de placer toutes les pièces dans un certain ordre et si la pièce n°k n'est pas placée, on remonte à la pièce n°k-1 pour la déplacer et ensuite réessayer avec la k.
Le souci, c'est qu'en faisant ça, il arrive que la pièce k-1 soit carrément enlevée du plateau (ce qui permet de placer la pièce k car de la place se libère).
J'ai essayé de demander à remonter à la pièce k-2 puis ainsi de suite mais il existe toujours une faille dans le programme qui permet de laisser une pièce de côté.

Voici le début de la fonction :

def resolution():
placer_bloqueurs(tirage_7des()) #Place les 7 bloqueurs sur le plateau de jeu
n = 0 #nombre de pièces placées
attribution_positions_possibles() #Fonction qui collecte les listes de toutes les positions possibles pour chaque pièce en début de jeu
for k in range(len(ORDRE_DES_PIECES)): #Parcourt la liste des pièces selon l'ordre dans lequel les placer
placer(ORDRE_DES_PIECES[k]) #Place chaque pièce une par une
if resolu(): #Si le puzzle est résolu = toutes les pièces sont placées
break
print('Terminé !')
if verifier_piece_placee(ORDRE_DES_PIECES[k]) : #Rajoute +1 au compteur à chaque fois qu'une pièce est placée
n = n+1
if n<9: #Dans le cas où toutes les pièces ne sont pas encore placées


Et c'est là que je souhaite rajouter les commandes pour gérer la situation dans le cas où une pièce n'a pas été placée par manque de place

7 réponses

Messages postés
853
Date d'inscription
lundi 23 mars 2020
Statut
Membre
Dernière intervention
17 janvier 2021
96
Bonjour ximista,

Il faudrait que tu ré affiches ton code avec les balises de code Python pour plus de clarté
mode d'emploi:
https://codes-sources.commentcamarche.net/faq/11288-les-balises-de-code

Visuellement, ça doit ressembler à ceci (avec la coloration syntaxique) :

def test():
    print('test')

test()
ah oui pardon, merci ! ^^
Voilà :

def resolution():
    placer_bloqueurs(tirage_7des()) #Place les 7 bloqueurs sur le plateau de jeu
    n = 0 #nombre de pièces placées
    attribution_positions_possibles() #Fonction qui collecte les listes de toutes les positions possibles pour chaque pièce en début de jeu
    for k in range(len(ORDRE_DES_PIECES)): #Parcourt la liste des pièces selon l'ordre dans lequel les placer
        placer(ORDRE_DES_PIECES[k]) #Place chaque pièce une par une
        if resolu(): #Si le puzzle est résolu = toutes les pièces sont placées
            break
            print('Terminé !')
        if verifier_piece_placee(ORDRE_DES_PIECES[k]) : #Rajoute +1 au compteur à chaque fois qu'une pièce est placée
            n = n+1
        if n<9: #Dans le cas où toutes les pièces ne sont pas encore placées
Messages postés
13932
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 janvier 2021
784
deux défauts du programme:
- il ne faut certainement pas faire ainsi une boucle for
- tu mélanges un peu n et k
Messages postés
853
Date d'inscription
lundi 23 mars 2020
Statut
Membre
Dernière intervention
17 janvier 2021
96
Bonjour Ximista,

D'après ce que je comprends des règles du jeu:

_ on a un tableau de 6x6 = 36 cases
_ on lance 7 dés qui indiquent les cases où placer les 7 pions bloqueurs
(il reste donc 29 cases libres)
_ on a des formes de couleurs qui sont des assemblages de cubes et qui ressemblent
à des L, ou des T, ou des I
_ il faut les placer dans les cases restantes, je ne pense pas qu'il y ait un ordre pour les
positionner, il faut simplement s'arranger pour que tout rentre dans les cases vides

Dans ton code, on ne voit pas comment tu "modélises" avec des variables les différentes
formes des pions et comment tu testes si une forme donnée (un L, par exemple)
rentre à un certain endroit du tableau ...
Effectivement ce sont bien les règles du jeu !
En réel, les pièces peuvent être placées n'importe comment mais j'ai choisi de les placer dans un certain ordre (d'abord les plus encombrantes) afin de faciliter la programmation.

Le code complet est beaucoup plus long, je n'ai mis ici que la fonction qui me pose problème pour simplifier !
Le plateau est modélisé par une matrice 6x6 et chaque pièce par une matrice. Par exemple, la pièce carrée de dimension 2x2 est modélisée par une matrice 2x2 [[1,1],
[1,1]]
pour les pièces avec une forme particulière, on place des 0 dans les espaces vides.
Ex : [[7,0], (pièce en Z)
[7,7],
[0,7]]

J'ai créé plusieurs fonctions auxiliaires qui permettent de vérifier si une pièce peut être placée à un endroit et si oui, qui peuvent la placer à cet endroit. Ces fonctions testent également les différentes orientations possibles pour chaque pièce. Je ne sais pas s'il est utile que je montre ces fonctions ?
>
Messages postés
13932
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 janvier 2021

Le code je l'ai trouvé dans la description de cette vidéo : https://www.youtube.com/watch?v=QzJo-Oj0X3A&t=917s
Le "using the force" est en fait juste une référence à la force dans Star Wars x)
Malheureusement, je ne crois pas qu'il existe de réelle "stratégie" pour ce jeu si ce n'est de tester tout un par un.
Si tu comprends son code, est-ce que tu pourrais m'expliquer quelle en est la logique parce que j'ai l'impression que quelque chose m'échappe.

Pour ta proposition, j'ai déjà deux fonctions qui permettent de placer et déplacer la pièce (je ne sais pas si ca change quelque chose de les séparer ?)
Cependant, si je suis ta logique de ne créer qu'une seule fonction qui prend en argument une pièce, je ne comprends pas comment tu te retrouves avec ce test : "if not trouver_place3(nplaces+1):" puisque là, tu mets en argument un nombre (issu d'un compteur) et non pas une pièce
Messages postés
13932
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 janvier 2021
784 > Ximista
le nombre est le numéro de la pièce.
Messages postés
13932
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 janvier 2021
784 > Ximista
qu'as-tu essayé pour mettre en place ma proposition?
>
Messages postés
13932
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 janvier 2021

J'ai tenté ceci :

def resolution(): 
    placer_bloqueurs(tirage_7des()) #Place les bloqueurs
    pieces_placees = 0 #nombre de pièces placées
    L = [] #Liste composée des listes des positions possibles pour chaque pièce en début de partie
    for a in ORDRE_DES_PIECES:
        for b in range(9):
            b = attribution_positions_possibles(a) 
            L.append(b)
    k = ORDRE_DES_PIECES[0]
    l = 0
    while pieces_placees < 9:
        if not verifier_piece_placee(k):
            placer(k,L[l])
            if not verifier_piece_placee(k):
                k = ORDRE_DES_PIECES[l-1]
            else:
                pieces_placees = pieces_placees + 1
                k = ORDRE_DES_PIECES[l+1]

def placer(piece,A):
    """Permet de placer la pièce ou de la déplacer si elle est déjà sur le plateau"""
    k=0
    m=0
    if verifier_piece_placee(piece): #Cas où l'on souhaite déplacer une pièce déjà placée
        for i in rotation_piece(piece):
            if A == []:
                m=m+1
                continue
            else:
                effacer(piece)
                print(m)
                A[m].pop(0)
                print(A)
                coloriage_coordonnees(i,recuperation_coordonnees(i),A[m][0])
                break
    else: #Cas où on place la pièce la 1ère fois
        for j in rotation_piece(piece):
            if verifier_piece_placee(j):
                break
            else:
                for l in  positions_possibles(recuperation_coordonnees(j),j): #on parcourt les positions possibles de la pièce dans sa j-ième orientation possible
                    if len(positions_possibles(recuperation_coordonnees(j),j)) == 0:
                        k=k+1 #Ajoute +1 à chaque fois qu'il n'existe pas de place disponible pour une orientation
                        continue
                    else:
                        coloriage_coordonnees(j,recuperation_coordonnees(j),l)
                        return(M)
    if not verifier_piece_placee(piece):
        return(False)


La fonction attribution_positions_possibles(piece) prend en argument une pièce donnée à laquelle elle attribue la liste de toutes ses positions possibles en début de partie quelle que soit son orientation.

Le programme tourne encore dans le vide
Messages postés
13932
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 janvier 2021
784 > Ximista
quelques erreurs, pour commencer:
- partout, tes noms de variables ne signifient rien
- évite d'utiliser les mêmes noms dans différentes fonctions
- dans resolution(), ta variable l est en trop, essaie sans.
- dans resolution(), change de nom pour la variable k, et assigne-là une seule fois, au bon endroit.
- dans resolution(), à quoi sert le test en ligne 12? que se passe-t'il si verifier_piece_placee() retourne vrai?
- dans resolution(), pourquoi ne pas tester la valeur retournée par placer(), au lieu d'appeler à nouveau verifier_piece_placee?
- je m'inquiète de ce que je vois en ligne 32: qu'y fais-tu?
Messages postés
853
Date d'inscription
lundi 23 mars 2020
Statut
Membre
Dernière intervention
17 janvier 2021
96
Bah non, si tu maitrise cette partie-là ....

Le truc c'est plutôt de trouver le bon algorithme pour placer toutes les pièces

J'avoue que la façon dont tu procèdes ne me parait pas claire

et que je n'ai pas encore réfléchi à tout ça ....
Messages postés
853
Date d'inscription
lundi 23 mars 2020
Statut
Membre
Dernière intervention
17 janvier 2021
96
Messages postés
13932
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
18 janvier 2021
784
tu écris "je peux placer la pièce n°1 puis la n°2 et si je n'ai pas de place disponible pour la n°2, je peux déplacer la n°1 à un autre endroit afin de réessayer de placer la 2"

que fais-tu si tu as de la place disponible pour la pièce 2?