Exercice : Générer un code de 4 nombres aléatoires, différentes

Fermé
WhiteTiger851 Messages postés 26 Date d'inscription jeudi 30 août 2012 Statut Membre Dernière intervention 13 avril 2017 - Modifié le 13 avril 2017 à 16:27
Dalfab Messages postés 706 Date d'inscription dimanche 7 février 2016 Statut Membre Dernière intervention 2 novembre 2023 - 14 avril 2017 à 17:04
Bonjour,

Je sais comment générer un code 4 nombres aléatoires :

<ital>#include <stdio.h>
#include <time.h>
#define TAILLE 4
#define NB_VALEURS 10

void CodeAlea(int tab[],int taille){
    int i,j;
    srand(time(NULL));
    for(i=0;i<taille;i++){
        tab[i] = rand()%(NB_VALEURS);
        printf("%d ", tab[i]);
    }}

int main() {
     int code[TAILLE];
     CodeAlea(code,TAILLE);
     return 0;
}</ital> 


Mais, comment avoir un code avec des nombres différents ?
J'ai essayé de faire ça :

int i,j,l=0;
    srand(time(NULL));
<bold>/*Génération du code de 4 nombres*/</bold>
    for(i=0;i<taille;i++){
        tab[i] = rand()%(NB_VALEURS);}
<bold>/*Parcours du tableau*/</bold>
    for(i=l;i<(taille-1);i++){
        for(j=l+1;j<taille;j++){
            if(tab[i] == tab[j]){
                tab[j] = rand()%(NB_VALEURS); <bold>/*On redonne une valeur à tab[j]*/</bold>
                l=0; <bold>/*On parcours le tableau depuis le début*/</bold>
            }}}
<bold>/*Affichage du code*/</bold>
    for(i=0;i<taille;i++){
        printf("%d ",tab[i]);
    }}


Mais, ça ne fonctionne pas. Pouvez-vous m'aidez ?
Merci

4 réponses

proglib Messages postés 9 Date d'inscription vendredi 24 mars 2017 Statut Membre Dernière intervention 14 avril 2017 2
13 avril 2017 à 16:00
Test
for(nb nombre => 4fois){
	bool tmp = false;
	do{
		//générer un nombre rand
	
		//Boucle pour test si le nombre est dans le tableau
			//si oui on fait rien
	
			//si non on passe tmp = true et on ajoute le nombre dans le tableau à la case n correspondant à n itération du for


	}while(!tmp);
}



1
WhiteTiger851 Messages postés 26 Date d'inscription jeudi 30 août 2012 Statut Membre Dernière intervention 13 avril 2017
Modifié le 13 avril 2017 à 16:38
Ok
0
WhiteTiger851 Messages postés 26 Date d'inscription jeudi 30 août 2012 Statut Membre Dernière intervention 13 avril 2017
Modifié le 13 avril 2017 à 17:26
Je pense avoir réussi. J'ai effectué plusieurs tests et il semblerait que j'ai des valeurs différentes à chaque test.
J'ai un peu modifié votre programme.
Voici ce que j'ai fait :

void Code(int tab[],int taille){
    int i,j,tmp=0;
    srand(time(NULL));
    int nb = rand()%(NB_VALEURS);
    tab[0] = nb;
    for(i=1;i<taille;i++){
        while(!tmp){
            nb = rand()%(NB_VALEURS);
            for(j=0;j<i;j++){
                if(nb != tab[j]){
                    tmp = 1;
                }else{
                    tmp = 0;
                    j=i;
                }
            }
            if(tmp==1){
                tab[i] = nb;
            }
        }
        tmp = 0;
    }
    for(i=0;i<taille;i++){
        printf("%d ",tab[i]);
    }
}


Merci de votre aide
0
[Dal] Messages postés 6200 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 7 janvier 2025 1 097
Modifié le 13 avril 2017 à 19:25
cela devrait marcher, même si on peut faire plus simple.

autrement, pour faire original, tu pourrais utiliser strchr() accessible par string.h...

http://www.cplusplus.com/reference/cstring/strchr/

... vu que tes nombres sont compris de 0 à 9, et qu'ils tiennent dans un char, tu pourrais mettre un petit "twist" dans ton code et les stocker dans une chaîne C (un tableau de 5 char terminé par '\0'), en générant des nombres aléatoires tirés sur le range des codes ASCII des chiffres, et ton code tiendrait en quelques lignes et pourrait même être plus approprié si, en fait, tu veux juste utiliser ces numéros pour afficher le code à 4 chiffres :-D


Dal
0
[Dal] Messages postés 6200 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 7 janvier 2025 1 097
Modifié le 13 avril 2017 à 20:01
comme cela :

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

int main(void) {
  char code[5] = "XXXX";
  char ch;
  int n = 0;

  srand(time(NULL));
  while (code[n++]) {
      while (strchr(code, ch = rand() % 10 + '0'))
          ; /* ensure ch is not found in code */
      code[n-1] = ch;
  }
  printf("Code = %s\n", code);

  return 0;
}

le plus long, c'est de taper les #include ;-D ... la taille du tableau est gérée toute seule par le premier while, qui vérifie si on arrive au caractère NULL de la chaîne C, qui est donc alors complète. La chaîne elle même est initialisée avec 4 char quelconques de façon à ce que le caractère NULL se trouve en 5ème et dernière position (fait tout seul à la déclaration), ces char étant écrasés au fur et à mesure. Cela permet de mettre de l'intelligence dans les données, qui autrement devrait se retrouver sous forme de code.

Bien sûr, c'est du code acrobatique, et je doute qu'il plaise à un enseignant (c'est d'ailleurs pourquoi je le poste même s'il s'agit d'un exercice que tu dois faire), mais j'avais envie de faire ma proof of concept là pour illustrer ma remarque ;-)


Dal

P.S. : à propos de #include, tu avais omis
#include <stdlib.h>
dans ton code posté initialement (qui est nécessaire à srand et rand)
0
[Dal] Messages postés 6200 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 7 janvier 2025 1 097
14 avril 2017 à 13:47
hop, un petit changement : on peut faire l'incrémentation postfixe de
n
avant de boucler, plutôt qu'au test, pour éviter la soustraction :

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

int main(void) {
  char code[5] = "XXXX";
  char ch;
  int n = 0;

  srand(time(NULL));
  while (code[n]) {
      while (strchr(code, ch = rand() % 10 + '0'))
          ;       /* ensure ch is not found in code */
      code[n++] = ch; /* store it, then increment n */
  }
  printf("Code = %s\n", code);

  return 0;
}

Dal
0
Dalfab Messages postés 706 Date d'inscription dimanche 7 février 2016 Statut Membre Dernière intervention 2 novembre 2023 101
14 avril 2017 à 10:22
Non, il subsiste une erreur dans ton code.
A la fin de la boucle, tu regardes si tmp vaut 1 ou 0. Or tu initialises tmp à chaque tour, donc ton test ne vérifie que le fait que la dernière vérification est bonne. Il y a donc des lignes en trop!
void Code(int tab[],int taille){
    srand(time(NULL));
    for( int i = 0  ;  i < taille  ;  ++i ) {
        int nb = rand() % (NB_VALEURS);
        int j;
        for ( int j = 0  ;  j < i  ;  ++j ) { // comparer aux precedents
            if ( nb == tab[j] ) // deja choisi
                break;          // inutile de continuer
        }
        if ( j == i )           // tous on passe le test avec brio
            tab[i] = nb;
        else     // ce nb ne vas pas, essayer un autre
            --i; // astuce => le prochain sera le même indice : on refait
    }
}
0
[Dal] Messages postés 6200 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 7 janvier 2025 1 097
Modifié le 14 avril 2017 à 11:17
donc ton test ne vérifie que le fait que la dernière vérification est bonne.

Je ne pense pas.

    for(i=1;i<taille;i++){
        while(!tmp){
            nb = rand()%(NB_VALEURS);
            for(j=0;j<i;j++){
                if(nb != tab[j]){
                    tmp = 1;
                }else{
                    tmp = 0;
                    j=i;
                }
            }
            if(tmp==1){
                tab[i] = nb;
            }
        }
        tmp = 0;
    }

"tmp" est mis à "faux" dans le while dès qu'une répétition est trouvée, et on sort de la boucle "for j" pour retenter le tirage sans ajouter ce chiffre, comme la vérification est faite par itération chiffre par chiffre, on teste effectivement toutes les positions.

"tmp" est forcé à "vrai" dans le while s'il n'y a pas de répétition, le test étant fait pour chaque chiffre, pas que pour le dernier. Donc, pour que "tmp" vaille "vrai" à la fin de la boucle "for j", et vu que les deux branches du if sont alternatives et exclusives, il faut qu'il n'y ait eu aucun chiffre répété depuis l'index 0 jusqu'à l'index courant i.

le
tmp = 0;
est correctement mis dehors du while avant d'attaquer la prochaine position de chiffre à tirer, pour que le while soit exécuté à la prochaine itération de "for i".

.. je peux me tromper, mais je n'arrive pas à imaginer un cas où la vérification échouerait.

Il y a donc des lignes en trop!

oui :-)


Dal
0
Dalfab Messages postés 706 Date d'inscription dimanche 7 février 2016 Statut Membre Dernière intervention 2 novembre 2023 101 > [Dal] Messages postés 6200 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 7 janvier 2025
Modifié le 14 avril 2017 à 11:52
Pardon, j'avais loupé la ligne j=i qui force la sortie dans le cas où il y a valeurs égales.
Ton code est donc 'longuement' ok.
0
[Dal] Messages postés 6200 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 7 janvier 2025 1 097
14 avril 2017 à 13:26
ce n'est pas le mien, c'est celui de WhiteTiger851 (l'OP).

le mien est là https://forums.commentcamarche.net/forum/affich-34521511-exercice-generer-un-code-de-4-nombres-aleatoires-differentes#5 avec 2 boucles while tenant sur 4 lignes :-)


Dal
0
Dalfab Messages postés 706 Date d'inscription dimanche 7 février 2016 Statut Membre Dernière intervention 2 novembre 2023 101 > [Dal] Messages postés 6200 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 7 janvier 2025
14 avril 2017 à 17:04
En effet, on doit donc avoir 3 codes corrects, et plus ou moins longs
0