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

C Discussion :

Le jeu de la vie - compr�hension des pointeurs


Sujet :

C

  1. #1
    Candidat au Club
    Homme Profil pro
    �tudiant
    Inscrit en
    D�cembre 2021
    Messages
    2
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 23
    Localisation : France, Bouches du Rh�ne (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : �tudiant

    Informations forums :
    Inscription : D�cembre 2021
    Messages : 2
    Par d�faut Le jeu de la vie - compr�hension des pointeurs
    Bonjour, je d�bute en c. je me suis int�ress� au jeu de la vie et ai trouv� un programme de ce jeu sur ce m�me site. Cependant une partie du programme m'�chappe car je ne suis pas encore tr�s � l'aise avec les pointeurs.
    Je vous remercie pour votre aide et m'excuse pour les fautes d'orthographe.
    La partie que je ne comprends pas est la fonction nb_voisin.
    Ci-dessous le code :

    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
    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>
    #define TAILLE 10
    void init_damier(int (*damier)[TAILLE][TAILLE]); //initialisation du damier
    void afficher_matrice(int (*damier)[TAILLE][TAILLE]); //affichage du damier
    int nb_voisin(int i, int j, int (*damier)[TAILLE][TAILLE]); //comptage du nombre de voisins vivants/morts
    void cel_vivante(int* cellule, int nb_voisin);  //changement des cellules en fonction du nb voisins
    void next_gen(int (*damier)[TAILLE][TAILLE]); //generation suivante
    #define VIVANTE 1
    #define MORTE 0
    int main()
    {
        int damier[TAILLE][TAILLE];
        srand(time(NULL));
        init_damier(&damier);
        afficher_matrice(&damier);
        next_gen(&damier);
        afficher_matrice(&damier);
        return 0;
    }
    void init_damier(int (*damier)[TAILLE][TAILLE])
    {
        int i, j;
        for (i = 0; i < TAILLE; ++i) {
            for (j = 0; j < TAILLE; ++j) {
                if((rand()%100) < 20) {
                    (*damier)[i][j] = VIVANTE;
                } else  {
                    (*damier)[i][j] = MORTE;
                }
            }
        }
    }
    void afficher_matrice(int (*damier)[TAILLE][TAILLE])
    {
        int i, j;
        for (i = 0; i < TAILLE; ++i) {
            for (j = 0; j < TAILLE; ++j) {
                if ((*damier)[i][j] == VIVANTE) {
                    printf("0" );
                } else {
                    printf("-" );
                }
            }
            printf("\n" );
        }
        printf("\n" );
    }
    #define MODT(i)  ((TAILLE + (i)) % TAILLE)
    int nb_voisin(int i, int j, int (*damier)[TAILLE][TAILLE])
    {
        return (*damier)[MODT(i-1)][MODT(j-1)] + (*damier)[MODT(i-1)][MODT(j)]
               + (*damier)[MODT(i-1)][MODT(j+1)] + (*damier)[MODT(i)][MODT(j-1)]
               + (*damier)[MODT(i)][MODT(j+1)] + (*damier)[MODT(i+1)][MODT(j-1)]
               + (*damier)[MODT(i+1)][MODT(j)] + (*damier)[MODT(i+1)][MODT(j+1)];
    }
    void cel_vivante(int* cellule, int nb_voisin)
    {
        if (*cellule == VIVANTE) {
            if ((nb_voisin <= 1) || (nb_voisin >=4)) {
                *cellule = MORTE;
            }
        } else {
            if (nb_voisin == 3) {
                *cellule = VIVANTE;
            }
        }
    }
    void next_gen(int (*damier)[TAILLE][TAILLE])
    {
        int i,j;
        for(i = 0; i < TAILLE; ++i) {
            for (j = 0; j < TAILLE; ++j) {
                cel_vivante(&(*damier)[i][j], nb_voisin(i,j,damier)); //on change la cellule si elle satisfait les conditions
            }
        }
    }

  2. #2
    Expert confirm�
    Homme Profil pro
    Ing�nieur d�veloppement mat�riel �lectronique
    Inscrit en
    D�cembre 2015
    Messages
    1 599
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 62
    Localisation : France, Bouches du Rh�ne (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement mat�riel �lectronique
    Secteur : High Tech - �lectronique et micro-�lectronique

    Informations forums :
    Inscription : D�cembre 2015
    Messages : 1 599
    Par d�faut
    Bonjour,
    C'est difficile d'expliquer les pointeurs � partir d'un code �crit par quelqu'un qui ne les a pas bien compris. Il y a syst�matiquement une indirection de trop dans ce code. Commen�ons par r��crire correctement la fonction.
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    #define MODT(i)  ((TAILLE + (i)) % TAILLE)
     
    int  nb_voisin( int i, int j, int const damier[][TAILLE] ) {
        return   damier[MODT(i-1)][MODT(j-1)] + damier[MODT(i-1)][j]
               + damier[MODT(i-1)][MODT(j+1)] + damier[i][MODT(j-1)]
               + damier[i][MODT(j+1)] + damier[MODT(i+1)][MODT(j-1)]
               + damier[MODT(i+1)][j] + damier[MODT(i+1)][MODT(j+1)];
    }
    Cette fonction examine les 8 cases contigu�s � la case (i,j), elle utilise le fait que VIVANTE vaut 1 et MORTE vaut 0, et donc en ajoutant ces cases on obtient bien le nombre de VIVANTEs autour de (i,j).
    Par exemple, la case � gauche est damier[i-1][j]. Mais que faire si i vaut 0, il n'y a pas de case � gauche. On est ici dans le cas o� on consid�re que la table est cyclique, et donc que la case � consid�rer � gauche est la case [TAILLE-1][j]. Pour cela il force par un modulo � rester entre 0 et TAILLE-1. la formule (TAILLE+i)%TAILLE dans la macro MODT() g�re cette conversion.

    Je n'ai pas parl� de pointeur. Pourtant damier est bien ici un pointeur. Il pointe sur le premier �l�ment d'un tableau de tableaux, et s'utilise comme s'il �tait un tableau de tableaux.

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    F�vrier 2006
    Messages
    12 841
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels
    Secteur : A�ronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : F�vrier 2006
    Messages : 12 841
    Billets dans le blog
    1
    Par d�faut
    Bonjour

    Tu ne peux pas comprendre les pointeurs sans avoir appris les pointeurs. Et tu n'apprendras pas les pointeurs en lisant un code qui est pr�sum� fait pour quelqu'un qui les connait d�j�. Apprendre les pointeurs c'est faire tes propres essais avec �ventuellement des exemples simples qui expliquent les notions de base.

    Pour comprendre les pointeurs, il faut savoir
    1. sur quels principes ils s'appuient
    2. � quoi ils servent
    3. leur syntaxe


    Sur quoi ils s'appuient: ils s'appuient sur le fait que le programme a beau �tre d�coup� en fonction, il n'y a qu'une seule grosse zone m�moire pour tout �a. Et donc m�me si une fonction n'a qu'une petite partie de cette m�moire qui lui est allou�e pour ses propres variables (variables locales � la fonction), si elle connait l'adresse d'une autre partie elle a tout � fait le droit d'aller � cette adresse voir ce qu'il y a, bien que cette autre adresse soit dans une partie de la m�moire utilis�e par une autre fonction.

    A quoi ils servent: principalement pour qu'une fonctionX puisse modifier une variable situ�e dans une fonctionY. Car m�me si la fonctionY passe la variable � la fonctionX, cette derni�re n'en re�oit qu'une copie et donc m�me si elle la modifie, elle ne modifie que la copie. Si elle veut modifier l'original, elle doit aller � l'adresse correspondant � cet original pour le modifier. Or une adresse en C se stocke dans un pointeur.
    Une autre utilit� est de pouvoir acc�der tr�s rapidement � un �l�ment [x] d'un tableau. En effet, tous les �l�ments d'un tableau se suivent en m�moire. Or l'acc�s par indice (par crochets) est long (enfin "long" du point de vue processeur mais si tu fais du C c'est parce que tu veux aller vite donc autant ne rien perdre b�tement). Or si tu places un pointeur sur ledit �l�ment, l'acc�s par pointeur est alors imm�diat. Et pour placer un pointeur sur un �l�ment X d'un tableau, suffit de le placer sur le tableau et ensuite l'incr�menter. Le C "reconnaissant" la nature "tableau" du pointeur remplacera cet incr�ment par un d�calage appropri� ce qui fait que chaque incr�ment placera le pointeur sur l'�l�ment suivant du tableau.

    La syntaxe: c'est le plus compliqu� � comprendre car celle-ci utilise l'�toile de deux fa�ons diff�rentes. Dans une d�claration, l'�toile signifie "ceci est un pointeur" tandis que dans une expression, elle signifie "la case m�moire point�e par ce pointeur". Donc si j'�cris int *pt cela signifie "pt est un pointeur" tandis qu'�crire *pt=123 signifie "� la case point�e par pt j'y mets la valeur 123".
    Mais pourquoi mettre une �toile? Puisqu'une adresse est un simple nombre, ne pourrait-on pas utiliser un simple int pour le stocker? Malheureusement non car l'�toile permet aussi de montrer autre chose: dans l'�criture int *pt, cela indique "pt est un pointeur (il va stocker une adresse)" et aussi "� cette adresse *pt il y a un int" (par opposion au fait qu'il pourrait y avoir un float, un long ou autre) ; chose qu'on ne pourrait pas avoir avec un simple int pour stocker cette adresse.

    Et enfin un exemple: une fonction qui permute 2 int.

    Code c : 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
    #include <stdio.h>
     
    // La fonction va permuter deux int
    // Elle va donc recevoir les adresses de ces variables pour pouvoir les modifier
    // Elle stockera ces adresses dans des pointeurs
    void permut(int *x, int *y) {
    	// Une variable de transfert
    	int tmp;
     
    	// On sauvegarde la valeur de la première
    	tmp=(*x);
     
    	// On place la seconde dans la première
    	*x=(*y);
     
    	// On remet la sauvegarde dans la seconde
    	*y=tmp;
    }
     
    // Test
    int main() {
    	int a=123;
    	int b=456;
     
    	// Affichage initial
    	printf("a=%d, b=%d\n", a, b);
     
    	// Permutation - On passe les adresses des variables à la fonction
    	permut(&a, &b);
     
    	// Vérification
    	printf("a=%d, b=%d\n", a, b);
    }

    Et un exemple qui montre comment on peut utiliser un pointeur pour traiter un tableau
    Code c : 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
    #include <stdio.h>
     
    // Test
    int main() {
    	int tab[]={10, 20, 30, 40, 50, -1};
    	size_t i;
     
    	// Affichage classique
    	printf("\n");
    	for (i=0; tab[i] != -1; i++)
    		printf("Tab[%hu]=%d (carré=%d)\n", i, tab[i], tab[i] * tab[i]);
    		// Quatre appels à tab[i] => quatre fois le même calcul pour se placer sur l'indice [i]
     
    	// Utilisation d'un pointeur
    	int *pt;
    	printf("\n");
    	for (pt=tab, i=0; *pt != -1; pt++, i++)
    		printf("Tab[%hu]=%d (carré=%d)\n", i, *pt, (*pt) * (*pt));
    		// Le pointeur est incrémenté une seule fois - On peut l'utiliser quatre fois cela ne coûte rien
    }
    Mon Tutoriel sur la programmation �Python�
    Mon Tutoriel sur la programmation �Shell�
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les diff�rentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

Discussions similaires

  1. besoin d'aide pour jeu d'awal�
    Par Dabech dans le forum D�buter avec Java
    R�ponses: 6
    Dernier message: 12/04/2008, 22h41
  2. Besoin d'aide jeu du morpion
    Par narcis60floyjo dans le forum G�n�ral JavaScript
    R�ponses: 2
    Dernier message: 28/02/2008, 15h14
  3. besoin d'aide sur 1 jeu :(
    Par dani_fr dans le forum Flash
    R�ponses: 3
    Dernier message: 25/05/2007, 10h13
  4. [D�butant] Besoin d'aide pour modifier un jeu
    Par stoff66 dans le forum Assembleur
    R�ponses: 9
    Dernier message: 31/08/2006, 18h24
  5. Besoin d'aide pour un projet de jeu en ligne
    Par FLEO dans le forum Projets
    R�ponses: 1
    Dernier message: 21/10/2005, 08h55

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