Mon code ferme Excel
Bonjour,
Je suis en train de coder le jeu du Taquin en vba. Seulement, une fois lancé, excel ne repond plus.
Je vous met ici mon code:
Option Explicit
Sub jeuduTaquin_vba()
Dim Taquin(3, 3) As Variant
Dim continuer As Boolean
Dim x As Single
Dim case_vide_ligne As Integer
Dim case_vide_colonne As Integer
Dim ligne As Integer
Dim Nb As Integer
Dim colonne As Integer
Dim coup As Integer
Dim verification As Integer
Dim verification_ligne As Integer
Dim verification_colonne As Integer
Dim entree As Integer
Dim entree_ligne As Integer
Dim entree_colonne As Integer
Dim ind1 As Integer
Dim ind2 As Integer
Call MsgBox("Vous allez entrer dans le jeu du taquin dont le but est de résoudre un damier 3x3 aux valeurs aléatoires en un damier aux valeurs qui se suivent. Pour y arriver, vous avez une case vide, vous ne pouvez donc que déplacer une case adjacente à la case vide dans cette dernière. Le damier gagnant est comme suit")
Call MsgBox("la case comportant le 0 etant la case vide")
continuer = True
For ind1 = 1 To 3
For ind2 = 1 To 3
Taquin(ind1, ind2) = 0
Next
Next
entree = 0
entree_ligne = 1
entree_colonne = 1
Do While entree <= 8
Nb = Int(1 + 7 * Rnd(x))
If (Nb <> Taquin(1, 1)) And (Nb <> Taquin(1, 2)) And (Nb <> Taquin(1, 3)) And (Nb <> Taquin(2, 1)) And (Nb <> Taquin(2, 2)) And (Nb <> Taquin(2, 3)) And (Nb <> Taquin(3, 1)) And (Nb <> Taquin(3, 2)) And (Nb <> Taquin(3, 3)) Then
Taquin(entree_ligne, entree_colonne) = Nb
Cells(entree_ligne, entree_colonne).Value = Taquin(entree_ligne, entree_colonne)
entree = entree + 1
If entree_colonne = 3 Then
entree_colonne = 1
entree_ligne = entree_ligne + 1
End If
entree_colonne = entree_colonne + 1
End If
Loop
case_vide_ligne = 3
case_vide_colonne = 3
Do While continuer = True
Call MsgBox(Taquin(1, 1), Taquin(1, 2), Taquin(1, 3))
Call MsgBox(Taquin(2, 1), Taquin(2, 2), Taquin(2, 3))
Call MsgBox(Taquin(3, 1), Taquin(3, 2), Taquin(3, 3))
ligne = InputBox("entrer la ligne de la case a deplacer dans la case vide")
colonne = InputBox("entrer la colonne de la case a deplacer dans la case vide")
If (((case_vide_ligne = ligne) And (case_vide_colonne = colonne + 1)) Or ((case_vide_ligne = ligne) And (case_vide_colonne = colonne - 1)) Or ((case_vide_ligne = ligne + 1) And (case_vide_colonne = colonne)) Or ((case_vide_ligne = ligne - 1) And (case_vide_colonne = colonne))) Then
Taquin(case_vide_ligne, case_vide_colonne) = Taquin(ligne, colonne)
Taquin(ligne, colonne) = 0
case_vide_ligne = ligne
case_vide_colonne = colonne
coup = coup + 1
Else
Call MsgBox("la ligne et la colonne saisie ne correspondent pas a une case adjacente a la case vide")
End If
verification = 1
For verification_ligne = 1 To 3
For verification_colonne = 1 To 3
If Taquin(verification_ligne, verification_colonne) = verification Then
verification = verification + 1
End If
Next
Next
If verification = 8 Then
Call MsgBox("FELICITATIONS VOUS AVEZ COMPLETEZ LE JEU EN", coup, "COUPS")
continuer = False
End If
Loop
End SubA savoir que le problème se trouve dans la boucle Do While entree<=8 .
En esperant avoir une réponse,
VicKing
Bonsoir VicKing,
Je te confirme, ton code tourne en rond
Do While entree <= 8
' Nb ne varie jamais,car X n'a pas de valeur initiale
Nb = Int(1 + 7 * Rnd(x))
'Ce test est toujours passé
If (Nb <> Taquin(1, 1)) And (Nb <> Taquin(1, 2)) And (Nb <> Taquin(1, 3)) And (Nb <> Taquin(2, 1)) And (Nb <> Taquin(2, 2)) And (Nb <> Taquin(2, 3)) And (Nb <> Taquin(3, 1)) And (Nb <> Taquin(3, 2)) And (Nb <> Taquin(3, 3)) Then
Taquin(entree_ligne, entree_colonne) = Nb
Cells(entree_ligne, entree_colonne).Value = Taquin(entree_ligne, entree_colonne)
entree = entree + 1
If entree_colonne = 3 Then
entree_colonne = 1
entree_ligne = entree_ligne + 1
End If
entree_colonne = entree_colonne + 1
' Et donc à ce niveau entree n'a pas évolué
End If
Loop@+
Salut,
Sympa le jeu du taquin je m'en souvenais plus de celui la, cela me donne envie d'en faire un aussi ^^
Quand ton code plante tu peux tester en mode Pas à Pas (F8)
Sinon en plus de la réponse de BrunoM45:
- Ton tableau Taquin est mal initialisé je pense:
D'ailleurs on voit qu'il est en 4x4 alors que tu mets 3x3 dans ton énoncé, de base excel travaille en base 0, si tu veux rester sur le même code et avoir un tableau 3x3 il te faut déclarer spécifiquement en début de module
Option Base 1- Ton
Nb = Int(1 + 7 * Rnd(x))vaudra toujours la même chose vu que ton X ne change pas (et que c'est ta seed), regarde la doc pour des exemples d'utilisation (tu surlignes "Rnd" dans ton code et tu appuis sur F1)
- tu veux afficher la grille via le code
Call MsgBox(Taquin(1, 1), Taquin(1, 2), Taquin(1, 3))
Call MsgBox(Taquin(2, 1), Taquin(2, 2), Taquin(2, 3))
Call MsgBox(Taquin(3, 1), Taquin(3, 2), Taquin(3, 3))nan?
d'une part cela ne donnera pas du tout l'effet voulu car tu ne respectes pas la syntaxe du MsgBox:
MsgBox(prompt[, buttons] [, title] [, helpfile, context])
par exemple si tu l'affiches après ta boucle qui mets des "0" partout le premier msgbox donne:
Et surtout ce n'est pas sexy et lisible ^^, il te faut afficher toute les lignes dans un seul msgbox
D'autres remarque générales:
- A noter que le taquin se joue en 4x4 de base et pas 3x3
- Attention si tu remplis en RND, certaines configuration n'ont pas de solution possible (sur 4x4 en tout cas mais j'imagine que le 3x3 à surement ce genre de cas)
- Mets des commentaires et indente ton code vindiou
- au vu de ton code et de tes soucis, il te faut tester et vérifier ce que tu utilises au fur et a mesure et pas seulement à la fin
Courage
ECG
Bonjour,
Un grand merci a vous deux !
Pour info, c'est mon mini-projet de ma matière d'algorithmique. Et c'est bien en 3x3 que j'ai besoin de le faire. J'ai déjà codé en C le jeu du taquin mais ils me demandent en vba
Aussi, entre temps j'ai changer ma méthode de présentation de la grille, plutot que de le faire dans la boucle de dialogue (comme avant et comme en C) j'ai afficher dans les cellules A1:C3 et ça fonctionne
Mais maintenant, je n'arrive jamais à entrer dans cette boucle if
If (((case_vide_ligne = ligne) And (case_vide_colonne = colonne + 1)) Or ((case_vide_ligne = ligne) And (case_vide_colonne = colonne - 1)) Or ((case_vide_ligne = ligne + 1) And (case_vide_colonne = colonne)) Or ((case_vide_ligne = ligne - 1) And (case_vide_colonne = colonne))) Then
Taquin(case_vide_ligne, case_vide_colonne) = Taquin(ligne, colonne)
Taquin(ligne, colonne) = 0
case_vide_ligne = ligne
case_vide_colonne = colonne
coup = coup + 1
Else
Call MsgBox("la ligne et la colonne saisie ne correspondent pas a une case adjacente a la case vide")
End If Pourtant case_vide_ligne et colonne sont bien enoncés au début à 3...
C c'est mieux
mets ton fichier ou ton code car la comme ça dur de voir ce que tu as refais comme code au final
le voici
C'est bon j'ai trouvé mon erreur, j'ai mal initialisé mes variables.
je les ai initialisé comme en C alors qu'en vba il faut ajouter As Integer a chaque fois.
C'est pas grave, maintenant il marche parfaitement !
Merci à vous !
VicKing
Salut,
je les ai initialisé comme en C alors qu'en vba il faut ajouter As Integer a chaque fois.
si tu mets pas de type, excel les prends en comptes comme Variant donc en general le code fonctionne quand même, cela prend juste plus de place mémoire il me semble
Attention quand tu déclares dans ton code
Dim Taquin(3, 3), a, b,etc, entree_colonne As Integertu as que entree_colonne qui est déclaré en Integer, le reste est en variant, il te faudrait faire
Dim Taquin(3, 3) As Integer, a As Integer, b As Integer,etcet heureusement ici car Taquin(3,3) n'est pas un Integer mais un tableau ^^
C'est pas grave, maintenant il marche parfaitement !
je viens de tester et dès le premier essai j'ai une erreur:
la case en ligne 2 colonne 3 est bien adjacente à celle vide pourtant
Si tu annules les 2 msgbox cela fait planter ton jeu:
d'ailleurs et si on y mets du textes et pas un chiffres tu as regardé ce que cela donne? ou si on mets rien? ^^
Il faut que tu prennes l'habitude de tester tous les mauvais cas de figures qui peuvent se présenter, c'est chiant et long des fois mais nécessaire ^^
Si tu es en classe info cela sera une bonne habitude
Pour ton msgbox du début, regarde sur le net pour faire un retour à la ligne, cela sera vraiment plus sympa d'avoir:
Juste à noter qu'avec ton RND ici tout se passe bien car ton tableau est petit mais attention tu pourrais avoir des soucis sur d'autres situations (car ici tu refais un rnd tant que tu tombes sur un chiffre que tu n'as pas encore eu, avec pas de chance cela peut prendre un temps infinis
Par exemple par curiosité j'ai rajouté un compteur "NB_ITERATION" dans ta boucle, cela indique donc le nombre de fois qu'on a du faire une boucle de RND:
J'ai fais quelques matière de prog à l'école et en général les professeurs aimait bien voir les évolutions/faiblesse du code (par exemple le RND qui peut boucler énormément mais vu la petite taille du tableau c'est un temps imperceptible donc acceptable mais au moins tu en as conscience) et aussi c'est une bonne pratique de réfléchir à son programme en général de cette façon.
Par exemple:
- si je veux quitter en cours de jeu je fais comment? tu as un bouton pour?
- si je sors et je veux reprendre ma partie en cours je fais comment?
- si j'y connais rien à excel VBA, je lance comment ton jeu?
Après tu dois réfléchir aussi en général en informatique à:
- encapsuler/rendre générique ton code le plus possible (ce qui te permet de faire des tests unitaire aussi au passage beaucoup plus facilement et mieux identifier les soucis),
- et maintenable (avec des commentaires, des fonctions qui fonctionnent quelque soit tes données entrées)
Par exemple rapidement ton
Do While entree < 8qui reprends donc ton nombre de case -1 de la valeur 0 pourrais être écrite de la façon suivante
Do While entree < (UBound(Taquin, 1) * UBound(Taquin, 2) - 1)ainsi si demain tu passes en 4x4 cette partie du code est toujours vrais, tu vas sur 4*4-1 = 15 cases
à ta place je ferais encore un peu d'update avant de livrer ton projet mais c'est à toi de voir^^
Salut,
oui tu as raison, de toute manière j'ai encore du temps devant moi. Mais si je demande à chaque étape s'il veut sortir, ca va le géner pour jouer.
Ou sinon il faudrait que je mette un nombre particulier (si il initialise ligne et colonne par 0, je le fais sortir du jeu, en le prévenant avant de commencer le jeu). Je vais faire ça...
Pour le nb d'itérations, c'est hyper intéressant btw. Mais en fait c'est le 8 le pb, c'est le plus chiant à avoir, donc plus il arrive tardivement, plus il y a de nb d'itérations.
Pour remédier ce pb, j'avais penser, à plutot que donner des valeurs aléatoires, je pourrais faire un mélange de ma grille. C'est-a-dire que je commence avec ma grille juste et avec une boucle for (et des nb saisies aléatoirement entre 1 et 3), je pourrais mélanger ma grille en echangeant donc au hasard ma grille. je vais tester ca plus tard....
après, ma consigne est bien de faire fonctionner pour une grille 3x3, mais pourquoi pas essayer de le généraliser...
Pour le retour à la ligne, j'ai trouvé et je l'ai ajouté à qqs endroits de mon code.
Pour la sauvegarde de la partie, pour le moment, c'est impossible pour moi (ma matière d'algo c'est la première proposé par mon école donc pour le moment on a pas vu ça....
Merci,
A+
oui tu as raison, de toute manière j'ai encore du temps devant moi. Mais si je demande à chaque étape s'il veut sortir, ca va le géner pour jouer.
Je pense aussi yes
Ou sinon il faudrait que je mette un nombre particulier (si il initialise ligne et colonne par 0, je le fais sortir du jeu, en le prévenant avant de commencer le jeu). Je vais faire ça...
C'est une solution
Après tu as beaucoup d'argument
MsgBox (prompt, [ buttons, ] [ title, ] [ helpfile, context ])de la lecture au pire https://docs.microsoft.com/fr-fr/office/vba/language/reference/user-interface-help/msgbox-function
Surtout par exemple l'argument Buttons qui m'a l'air intéressant... je te laisse tester dans vba
Et dans la documentation il y a un exemple très intéressant avec la variable
Response , cela pourrait peut être te convenir
Pour le nb d'itérations, c'est hyper intéressant btw. Mais en fait c'est le 8 le pb, c'est le plus chiant à avoir, donc plus il arrive tardivement, plus il y a de nb d'itérations.
Pour remédier ce pb, j'avais penser, à plutot que donner des valeurs aléatoires, je pourrais faire un mélange de ma grille. C'est-a-dire que je commence avec ma grille juste et avec une boucle for (et des nb saisies aléatoirement entre 1 et 3), je pourrais mélanger ma grille en echangeant donc au hasard ma grille. je vais tester ca plus tard....
Vu que je fais aussi un taquin (tu m'as donné envie de tester ^^), personnellement même si un full rnd au final fonctionne comme on a vu je suis quand même parti sur une solution plus propre
Tout comme un tirage au sort sans remise en jeu:
- je fait une liste/array de mes valeurs à tirer au sort (de 1 à 9 ou 0 à 8 par exemple)
- je tire en rnd parmi le nombre de valeur restante
- je retire cette valeur de l'array et je la mets dans la première case de mon taquin
- je recommence pour remplir toute la grille
un exemple sur 3 valeurs
ma liste contient: 7 4 8
je tire au hasard un chiffre entre 1 et 3 (mon nombre de valeur restants dans ma liste étant de 3)
cela me sors 2, soit la valeur 4, je la retire et je la mets dans ma première case de mon taquin
ma liste contient: 7 8
je tire au hasard un chiffre entre 1 et 2 (mon nombre de valeur restants dans ma liste étant de 2)
cela me sors 1, soit la valeur 7, je la retire et je la mets dans ma première case de mon taquin
il reste qu'une valeur (le 8), je la mets dans la dernière case de mon taquin
après, ma consigne est bien de faire fonctionner pour une grille 3x3, mais pourquoi pas essayer de le généraliser...
C'est facultatif et "more than expected" en effet, te casse pas trop la tête
De toute façon on le découvre tous un jour ou l'autre, quand on change une variable de son programme et que plus rien ne va car on a tout mis en dur... on commence à réfléchir pour être générique et ne plus se faire avoir
Pour le retour à la ligne, j'ai trouvé et je l'ai ajouté à qqs endroits de mon code.
En général l'aide/documentation ou google sont la pour t'aider, il est toujours bon de regarder les exemples ou voir les arguments que les fonctions demandent
A force d'utiliser des fonctions pour la même chose on oublie ce qu'elles peuvent faire au total ^^, il est bon d'être curieux en informatique (et surtout un autre jour tu te diras peut-être "ah mais j'ai lu un truc sur cette fonction qui peut servir à faire ce que je cherche pratiquement" )
Pour la sauvegarde de la partie, pour le moment, c'est impossible pour moi (ma matière d'algo c'est la première proposé par mon école donc pour le moment on a pas vu ça...
Pas de soucis surtout en VBA
au final en 3x3 le nombre de grille faisable reste limité mais en 4x4 il y en a 10 461 394 944 000 d'après le wiki pouah !