Se connecter / S'enregistrer
Votre question

Visual basic: programmation d'un jeu de vie [MA QUESTION EST TOUT EN BAS]

Tags :
  • Martin
  • Programmation
Dernière réponse : dans Programmation
2 Février 2006 11:05:04

Bonjour à tous,


J'ai un projet à réaliser en visual basic. Je connais assez bien le langage de programmation (boucle, booléen...etc...) mais, mon gros problème réside dans le fait que j'ai beaucoup de mal à analyser le sujet pour le découper en une série de sous programme.

Je souhaiterais avoir un peu d'aide pour démarrer mon projet. Merci

Citation :
Le but de ce projet est de simuler un jeu de la vie. Le jeu de la vie est le plus célèbre des automates cellulaires. Il a été inventé par John Conway et popularisé dans la rubrique de Martin Gardner du magazine américain "Scientific American" d'octobre 1970.

Le jeu de la vie consiste à faire naître, vivre ou mourir des cellules. Celles-ci sont disposées sur une grille carrée. Chaque case de la grille contient une cellule. Initialement une cellule est soit "en vie" soit "morte". A chaque génération, les cellules évoluent en fonction de l’état de leurs voisines, en suivant une loi d’évolution.

Par exemple, une loi d’évolution peut être :
• Une cellule en vie meurt si elle a plus de 3 voisins morts,
• Une cellule en vie survit si elle a exactement 2 voisins en vie,
• Une cellule morte naît si elle a exactement 3 voisins en vie.
Les cases voisines d’une case donnée sont les quatre cases adjacentes, c’est-à-dire les cases ayant au moins un côté en commun.

D’autres règles d’évolution sont envisageables. Lors d’une exécution, toutes les cellules suivent la même règle d’évolution.

Vous réaliserez une application en Visual basic qui affiche à l’écran à chaque génération l’état des cellules sur la grille, ainsi que des informations sur l’évolution des populations de cellules en vie ou mortes. La grille sera initialisée en fonction du pourcentage de cellules en vie donné par l’utilisateur au lancement de l’application. Vous pourrez envisager de laisser l’utilisateur choisir une règle d’évolution parmi une liste de règles disponibles.

  1. Option Explicit
  2. Const col_max = 15
  3. Const row_max = 15
  4. Tableau_cellules(1 To col_max, 1 To row_max) As String
  5.  
  6.  
  7. Sub affich()
  8. Dim i As String
  9. Dim j As String
  10. Dim x As String
  11.  
  12. For i = 1 To col_max
  13. For j = 1 To row_max
  14.  
  15. x = cellule_hazard() 'Fais appel à une procédure qui va choisir si la cellule est morte ou vivante
  16. Call mort_ou_vie(i, j, x)
  17. Next j
  18. Next i
  19.  
  20. End Sub
  21.  
  22.  
  23. Sub mort_ou_vie(a, b, i)
  24. If i = False Then
  25. ms.Col = a
  26. ms.Row = b
  27. ms.Text = "M"
  28. Else
  29. ms.Col = a
  30. ms.Row = b
  31. ms.Text = "V"
  32.  
  33. End Sub

Voila mes premier algo. J'ai un problème pour créer une procédure (ou une fonction?) qui me sort aléatoirement une valeur (je sais que ça sera un booléen).
Je dois me servir de l'objet "ramdomize" mais je ne suis pas sur de moi pour la syntaxe.
Mon deuxième problème est la manière par laquelle j'aurai par exemple 40% de cellules vivantes au départ.

Merci de votre aide

Autres pages sur : visual basic programmation jeu vie question bas

2 Février 2006 11:53:51

salut,

pour ce qui est de la syntaxe en VB, j'utilise rarement VB.NET mais la syntaxe est la suivante :

  1. Randomize 'oui c'est tout :), ça permet d'avoir un tirage différent à chaque lancement du programme


apres pour tirer un chiffre aléatoirement avec un biais, tu peux par exemple créer une fonction du type :
(je ne t'assure pas l'exactitude la syntaxe ...)

  1. Function TirageBiaise(ByVal biais As Integer) As Boolean
  2. Dim tirage As Integer
  3. tirage = CInt(Int((100 * Rnd()) + 1)) ' Generate random value between 1 and 100
  4. if tirage<biais then
  5. return true
  6. else
  7. return false
  8. end if
  9. End Function


Avec cette fonction, si tu rentre 40 en paramètre, alors dans 40% des cas elle te renverra true (si bien sûr la distribution de Rnd est normale :) )

Attention, quand tu va analyser ton plateau pour connaître le nouvel état de cellule il faut bien que tu utilises 2 tableaux différents. Un qui contient l'état en cours et l'autre qui contient l'état modifié.
En pour tester chaque cellule, il faut commencer par tester les cas par ordre de prioirité (une cellule vivante entouré de 3 voisines est forcement entouré de 2 voisines ...)

Enfin, il faut penser à ce que tu vas faire pour les cases sur les bords du plateau.

Bon courage.
2 Février 2006 12:44:57

Merci beaucoup pour ces éléments de réponses :) 

Si j'ai bien compris, lorsque je vais faire appelle à cette fonction et que je voudrais obtenir par exemple 40% de cellule vivante, je devrais écrire:
  1. Call Function TirageBiaise(ByVal 40 As Integer)

C'est bien ça?

De plus dans mon cas, le nombre de case seront prédéfénies.
Pour un carré de 20*20 donc 400 cellules, est ce que je dois écrire:
  1. Function TirageBiaise(ByVal biais As Integer) As Boolean
  2. Dim tirage As Integer
  3. tirage = CInt(Int(((col_max*row_max) * Rnd()) + 1)) ' Generate random value between 1 and 400
  4. if tirage<biais then
  5. return true
  6. else
  7. return false
  8. end if
  9. End Function



Citation :
Enfin, il faut penser à ce que tu vas faire pour les cases sur les bords du plateau.

Je sens que ça va aussi me poser des problème :-( :-(
Contenus similaires
Pas de réponse à votre question ? Demandez !
a b L Programmation
2 Février 2006 13:03:47

Pour le bord du tableau, comme pour un démineur, tu peux ajouter une colone à gauche et à droite, et une ligne en haut et en bas supplémentaire.
Ces cases seront interdites pour les déplacements, mais pour faire les tests autour d'une cellule, c'est plus facile à faire, car il n'y a pas de cas particulier.
2 Février 2006 13:48:06

Citation :
Si j'ai bien compris, lorsque je vais faire appelle à cette fonction et que je voudrais obtenir par exemple 40% de cellule vivante, je devrais écrire:

  1. Call Function TirageBiaise(ByVal 40 As Integer)


C'est bien ça?

heu non, il me semble que tu devras faire :

  1. Dim res as Boolean
  2. res=TirageBiaise(40)


Citation :

De plus dans mon cas, le nombre de case seront prédéfénies.
Pour un carré de 20*20 donc 400 cellules, est ce que je dois écrire:

  1. ...
  2. tirage = CInt(Int(((col_max*row_max) * Rnd()) + 1)) ' Generate random value between 1 and 400


non non, en fait le 100 permet de donner un rapport en pourcentage.
La formule que je t'ai donné te permet d'avoir statistiquement des tirages au pourcentage défini, mais pas surement.
Si tu veux un tirage sûr alors il faut tirer des valeurs avec retirage en cas de doublon, jusqu'à obtention de ton pourcentage.

Pour les cases sur les bords, y'a un truc sympa à faire , c'est considérer que grossierement ton plateau est une sphère. Donc une case complètement à gauche a une voisine sur la même ligne complètement à droite.

2 Février 2006 14:49:37

J'ai apporté quelques modifications:

  1. Option Explicit
  2. Const n = 40
  3. Au préalable, le nombre de case correspondant à 40% de mon tableau sera calculé:


  1. Pourcentage_cell_vie = (((col_max * row_max) / n) / 100)

=40% des cases de mon carré
Ensuite, je ferais appelle à la fonction:
  1. Dim res as Boolean
  2. res=TirageBiaise(Pourcentage_cell_vie)

  1. Function TirageBiaise(ByVal biais As Integer) As Boolean
  2. Dim tirage As Integer
  3. Dim V_ou_M As Boolean
  4. tirage = CInt(Int((100 * Rnd()) + 1)) ' Generate random value between 1 and 100
  5. If tirage <= biais Then 'Inférieur ou égal à 40%
  6. V_ou_M = True
  7.  
  8. Else
  9. V_ou_M = False
  10. End If
  11. biais = V_ou_M 'Car la fonction doit renvoyer une valeur "true" ou "false"
  12. End Function


Vous en pensez quoi?

(désolé si je fais des erreurs conne, je suis loin d'être un expert...)
2 Février 2006 16:00:20

juste je reprécise ce que j'ai dit, la fonction TirageBiaise de garantie que statistiquement tu auras un remplissage de "biais"% (je sais pas pourquoi je l'ai appelé comme ça cet argument ...).

Il te manque un
  1. Return biais
à la fin de ta fonction TirageBiaise

[edit]heu non pas un return biais, biais est un Integer et V_ou_M est un booléen. Il te manque un
  1. return V_ou_M
2 Février 2006 16:41:00

Je le place de cette façon?

  1. Function TirageBiaise(ByVal biais As Integer) As Boolean
  2. Dim tirage As Integer
  3. Dim V_ou_M As Boolean
  4. tirage = CInt(Int((100 * Rnd()) + 1)) ' Generate random value between 1 and 100
  5. If tirage <= biais Then 'Inférieur ou égal à 40%
  6. V_ou_M = True
  7.  
  8. Else
  9. V_ou_M = False
  10. End If
  11.  
  12. return V_ou_M
  13.  
  14. biais = V_ou_M 'Car la fonction doit renvoyer une valeur "true" ou "false"
  15. End Function


En tout cas, merci de ton aide :-)
2 Février 2006 16:48:31

oui, sauf que tu supprimes ton
  1. biais = V_ou_M
à la fin de ta fonction.

Sinon en fait je pense qu'il y a une meilleur solution.
C'est d'initialiser ton tableau avec le nombre exact de case que tu veux.

Tu définis ta constante du nombre de case (cas simple d'un tableau non dynamique)
  1. Const nCell = 400


Tu définis la fonction d'init :
  1. Function initPlateau(ByVal nbVivant As Integer, ByRef plateau As Array)
  2. Randomize()
  3. Dim i As Integer
  4. Dim cell As Integer
  5.  
  6. For i = 0 To nCell - 1
  7. plateau(i) = False 'tu vides ton tableau
  8. Next
  9. i = 0
  10.  
  11. 'tu rajoutes des cellules vivantes aléatoirement jusqu'au nombre voulu
  12. While i < nbVivant
  13. cell = CInt(Int(Rnd() * nCell ) + 1)
  14. If plateau(cell) = False Then
  15. plateau(cell) = True
  16. i = i + 1
  17. End If
  18. End While
  19. End Function


tu appelles ta fonction quelque part initialisant ton tableau :
  1. Dim tableau(nCell) As Boolean
  2. initPlateau(200, tableau)


Mais bon ce ne sont que des pistes.

Bon courage.
2 Février 2006 17:10:54

Citation :
Mais bon ce ne sont que des pistes.

Pas mal du tout! Je vais tester cette approche!

En fait, mon second tableau aura par défaut que des valeurs "false".
Le placement des cellules vivante sera bien effectué dans un tableau à deux dimensions?
2 Février 2006 17:49:02

disons que c'était une méthode avec un seul vecteur et après tu pouvais jouer avec les indices pour te créer un tableau.
Mais VB te propose les tableaux, alors tu peux également tout faire en 2D :

tu déclares :
  1. Const nLine = 20
  2. Const nRow = 20


tu crées une fonction init en 2D
  1. Function initPlateau2D(ByVal nbVivant As Integer, ByRef plateau As Array)
  2. Randomize()
  3. Dim i, j As Integer
  4. Dim row, line As Integer
  5. For i = 0 To nRow - 1
  6. For j = 0 To nLine - 1
  7. plateau(i, j) = False
  8. Next
  9. Next
  10. i = 0
  11.  
  12. While i < nbVivant
  13. row = CInt(Int(Rnd() * nRow) + 1)
  14. line = CInt(Int(Rnd() * nLine) + 1)
  15. If plateau(line - 1, row - 1) = False Then
  16. plateau(line - 1, row - 1) = True
  17. i = i + 1
  18. End If
  19. End While
  20. End Function


et tu appelles ta fonction avec un tableau en 2D
  1. Dim tableau2D(nRow - 1, nLine - 1) As Boolean
  2. initPlateau2D(10, tableau2D)


Sur ce je me rentre moi :-D
3 Février 2006 19:33:03

Il y a quelque chose que je n'arrive pas à comprendre:
Je n'arrivais pas à afficher des trucs dans mon tableau (élément MSflexgrid) alors j'ai fais une mini procédure qui me met une valeur dans chaque case afin de trouver la bonne syntaxe.

  1. Option Explicit
  2. Const col_max = 15
  3. Const row_max = 15
  4. Dim Tableau_cellules(1 To col_max, 1 To row_max)
  5.  
  6.  
  7. Sub remp1(ms As MSFlexGrid)
  8. Dim i As Integer
  9. Dim j As Integer
  10.  
  11.  
  12. For i = 1 To col_max
  13. For j = 1 To row_max
  14. Tableau_cellules(i, j) = ((i + j) * 2)
  15. ms.Col = i - 1
  16. ms.Row = j - 1
  17. ms.Text = Tableau_cellules(i, j)
  18.  
  19. Next j
  20.  
  21. Next i
  22.  
  23. End Sub

Voila la procedure qui appelle "remp1":
  1. Private Sub Command5_Click()
  2. Call remp1(MSFlexGrid1)
  3. End Sub



Au départ, j'avais mis:
ms.col = i
ms.row = j
Et mon programme (je devrais pas mettre une fonction à la place?) bugé, j'ai regardé la valeur des variables "i" et "j" et j'ai du mettre (i - 1) et (j - 1) mais je n'arrive pas à comprendre pourquoi.
3 Février 2006 22:56:52

je pense simplement que l'objet MSFlexgrid doit être appelé en commençant à l'indice 0 (comme n'importe quel tableau dans la plupart des langages).
Donc si tu as déclaré ton composant MSFlexgrid comme ayant col_max colonnes alors les indices colonnes de composant irons de 0 à (col_max-1) (ce qui fait bien col_max indices, et idem pour row_max)

Donc ton programme devait planté quand tu arrivais à l'indice i=col_max ou j=row_max.

Citation :
je devrais pas mettre une fonction à la place?

J'ai pas compris?
3 Février 2006 23:17:44

C'était bien ça! L'objet Msflexgrid commence à 0, je n'y avais pas pensé du tout... Quel con...
Citation :
J'ai pas compris?

Est ce que je dois mettre "Sub remp1(ms As MSFlexGrid)"
ou
"Function remp1(ms As MSFlexGrid)"

J'ai du mal à faire la distinction.
Si j'ai bien compris: ce sous programme ne renvoit aucune valeur, il rempli un tableau donc c'est une procédure et c'est "sub" que je dois mettre? C'est ça?
3 Février 2006 23:34:12

heu ... honnêtement j'en sais rien.

Voilà ce qui est dit dans la doc MSDN :
Citation :
Une procédure Sub, à l'instar d'une procédure Function, est une procédure distincte qui peut prendre en charge des arguments et exécuter une série d'instructions. Toutefois, contrairement à une procédure Function, qui retourne une valeur, une procédure Sub ne peut pas être utilisée dans une expression


Donc d'après eux, la seule différence est que la procédure ne renvoit pas d'argument ... mais comme il est possible d'appeler une fonction avec un call je ne vois pas vraiment l'interêt.

Sur certains site, ils parlent de différence de performances qui seraient meilleurs avec les Sub ...

En tout cas il y a certaintement un interêt à Sub sur function puisque la méthode new (entre autre) d'une Form , généré automatiquement sous VS.NET est déclarée en tant que sub et non en tant que function.

Je laisse la place aux spécialistes en VB pour le choix. :-D
a b L Programmation
4 Février 2006 00:16:04

J'ai pas tout lu
A la base des langages procéduraux (comme le pascal), il faut distinguer les procédures des fonctions (le C ne faisant pas de distinction car une procédure est une fonction retournant void).
D'un point de vue conceptuel, le Sub est l'éxécution d'un code qui par exemple fait appel à un périphérique, alors qu'une fonction est plus un calcul qui ne toucherait pas ou peu un périphérique.
Mais bon je suis surpris que ça existe encore, comme avec le vieux QBasic :-D
4 Février 2006 09:49:34

Merci :-D

J'ai une autre petite question: j'ai un tableau à deux dimensions:


  1. Dim Tableau_cellules(1 To col_max, 1 To row_max)

Comment puis je faire pour que les valeurs présentes dans chaque case soient mélangés dans le même tableau?
a b L Programmation
4 Février 2006 10:12:03

Tu boucles sur tous les élément du tableau, et pour chaque élément, tu faits une permutation avec une case choisie aléatoirement entre la case courante (comprise) et la fin du tableau.
4 Février 2006 13:57:42

WEp! J'ai réussi avec une autre approche!

J'ai un autre problème:
Je n'arrive pas à mettre les bonnes variables: a chaque fois, j'ai le message d'erreur...

[RESOLU]
4 Février 2006 21:40:23

  1. Option Explicit
  2. Const Longmax = 10
  3. Dim Tableau_cellules(1 To Longmax, 1 To Longmax) As String
  4. Dim Tvie(1 To Longmax, 1 To Longmax) As Boolean
  5. Const nbCellV = 20
  6.  
  7. Private Sub Command2_Click()
  8. Call InitTV(Tvie())
  9. Call InitTabcell(MSFlexGrid1)
  10. Call hazard2(Tvie())
  11. End Sub
  12.  
  13.  
  14. Sub InitTabcell(ms2 As MSFlexGrid)
  15. Dim i As Integer
  16. Dim j As Integer
  17.  
  18. For i = 1 To Longmax
  19. For j = 1 To Longmax
  20. Tableau_cellules(i, j) = ""
  21. ms2.Col = i - 1
  22. ms2.Row = j - 1
  23. ms2.Text = Tableau_cellules(i, j)
  24. Next j
  25. Next i
  26. End Sub
  27.  
  28.  
  29. Private Sub Command6_Click()
  30. Call initJeu(nbCellV, Tvie()) 'Fais appel à une procédure qui va choisir si la cellule est morte ou vivante
  31. End Sub
  32.  
  33.  
  34. Sub InitTV(tvi() As Boolean)
  35. Dim i As Integer
  36. Dim j As Integer
  37.  
  38. For i = 1 To Longmax
  39. For j = 1 To Longmax
  40. tvi(i, j) = False
  41. Next j
  42. Next i
  43. End Sub
  44.  
  45.  
  46. Sub hazard2(tvi() As Boolean)
  47. Dim MaVal As Integer
  48. Dim MaVal2 As Integer
  49. Dim i As Integer
  50.  
  51. For i = 1 To nbCellV
  52. ligne1:
  53. Randomize ' Initialise le générateur de hazard
  54. MaVal = CInt(Int((Longmax * Rnd()) + 1))
  55. MaVal2 = CInt(Int((Longmax * Rnd()) + 1))
  56. If tvi(MaVal, MaVal2) = True Then
  57. GoTo ligne1
  58. Else
  59. tvi(MaVal, MaVal2) = True
  60. End If
  61. Next i
  62. End Sub
  63.  
  64.  
  65. Private Sub Command1_Click()
  66. Call debut_cycle(MSFlexGrid1)
  67. End Sub
  68.  
  69.  
  70. Sub debut_cycle(ms As MSFlexGrid)
  71. Dim i As Integer
  72. Dim j As Integer
  73.  
  74. For i = 1 To Longmax
  75. For j = 1 To Longmax
  76. Call mort_ou_vie(i, j, ms, Tvie())
  77. Next j
  78. Next i
  79. End Sub
  80.  
  81.  
  82. Function mort_ou_vie(a As Integer, b As Integer, ms1 As MSFlexGrid, tvi() As Boolean)
  83. For a = 1 To Longmax
  84. For b = 1 To Longmax
  85.  
  86. If tvi(a, b) = False Then
  87. Tableau_cellules(a, b) = "M"
  88. ms1.Col = a - 1
  89. ms1.Row = b - 1
  90. ms1.Text = Tableau_cellules(a, b)
  91.  
  92. Else
  93. Tableau_cellules(a, b) = "V"
  94. ms1.Col = a - 1
  95. ms1.Row = b - 1
  96. ms1.Text = Tableau_cellules(a, b)
  97.  
  98. End If
  99. Next b
  100. Next a
  101. End Function

Ce code me permet d'afficher dans un tableau et de façon aléatoire 100 cellules: 20 sont vivantes("V") et 80 sont mortes ("M").
Le programme fonctionne, il n'y a pas de problème.(Merci à tous ceux qui m'ont aidé)

Je souhaiterais avoir quelques renseignements concernant l'interface graphique:
- quel est le nom du truc qui me permet d'avoir des cellules carrés (les redimentionner)
- comment puisse faire pour que la cellule soit colorié en verte à la place de "V" (vivante) et rouge pour "M" (morte)?

Merci
Tom's guide dans le monde
  • Allemagne
  • Italie
  • Irlande
  • Royaume Uni
  • Etats Unis
Suivre Tom's Guide
Inscrivez-vous à la Newsletter
  • ajouter à twitter
  • ajouter à facebook
  • ajouter un flux RSS