# ma boucle marche pas !!!



## _remi (15 Octobre 2004)

Bonjour,

Cocoa débutant, j'essaie de développer un petit jeu qui doit générer 7 entiers différent. Faut bien débuter...
La première boucle ajoute 7 nombres aléatoires dans un tableau et la deuxieme vérifie que la valeur de chaque index soit différente, mais elle ne marche pas celle-là...
Pourtant en C# cette boucle fonctionne...




 NSMutableArray *remTableau;
  int i;
  int j;
  NSNumber *remNombre;
 remTableau = [[NSMutableArray alloc] init];

  for (i = 0; i < 7; i++)
    {
	remNombre = [[NSNumber alloc] initWithInt random() % 49) + 1];
	[remTableau addObject: remNombre];
    for (j = 0; j < 7; j++)
	   {
	     if ((i != j) && ([remTableau objectAtIndex: i] == [remTableau objectAtIndex: j]))
	        {
		    i--;
		    break;
		    }
	   }
	}


  [textField_1 setObjectValue: [remTableau objectAtIndex: 0]];
  [textField_2 setObjectValue: [remTableau objectAtIndex: 1]];
  [textField_3 setObjectValue: [remTableau objectAtIndex: 2]];
  [textField_4 setObjectValue: [remTableau objectAtIndex: 3]];
  [textField_5 setObjectValue: [remTableau objectAtIndex: 4]];
  [textField_6 setObjectValue: [remTableau objectAtIndex: 5]];
  [textField_7 setObjectValue: [remTableau objectAtIndex: 6]];


----------



## tatouille (15 Octobre 2004)

rémi rémi (roulement de R )

houhouhou je pense que tu as déjà trouvé
houhouh

(roulement de R )
rémi rémi


----------



## _remi (15 Octobre 2004)

tu es bien gentil mon petit diable mais tu peux m'en dire plus...


----------



## arnolix (15 Octobre 2004)

A première vue ce qui m'étonne c'est que ça tourne sous C#. Tu dis, si j'ai bien compris, vouloir tester ton tableau pour qu'il ne comporte pas deux éléments identiques (et non pas deux index ).

Dans ta deuxième boucle, tu parcours le tableau avec l'index j. Mais les éléments d'index j supérieur à i n'ont pas encore été créés !

De deux choses l'une : ou ton code que t'as tapé en C# est fondamentalement différent, ou bien C# accepte de tester sur des éléments encore non créés.

Te propose le code suivant :


for(i=0;i<7;i++)
{
remNombre =[....

[remTableau addObject ...

[remNombre release]  // si tu oublies de relâcher tu as une fuite de mémoire

int j =0; BOOL OK = YES ;

while (j <i && ok){     // Voila l'erreur : j ne doit pas dépasser i. On sort de la boucle si deux
                              // éléments sont égaux

  if(OK = !([rem...] == [...]) ) {      // pas la peine de tester i!=j puisqu'il est inférieur à j

    [remTableau removeObjectAtIndex:i] ; i --  // Il faut retirer l'élément indésirable !

  } ; j++ ;

};

};


----------



## tatouille (15 Octobre 2004)

int rand;
rand=random() % 20+1;


[TextField setIntValue: rand];

NSString *myString = [[NSString alloc] initWithFormat"my number is %i.", rand];

so

@implementation Foo

- (IBAction)generateid)sender
{
    int generated;
    generated = (random() % 100) + 1;
    [textField setIntValue:generated];
}

- (IBAction)seedid)sender
{
    srandom(time(NULL));
    [textField setStringValue"Generator seeded"];
}

- (unsigned short) Myrand
{

implemente une routine de random
    return 0;
}

au final plutot que de faire des boucles
fait deux tableaux et compare les


----------



## _remi (15 Octobre 2004)

arnolix a dit:
			
		

> A première vue ce qui m'étonne c'est que ça tourne sous C#. Tu dis, si j'ai bien compris, vouloir tester ton tableau pour qu'il ne comporte pas deux éléments identiques (et non pas deux index ).
> 
> Dans ta deuxième boucle, tu parcours le tableau avec l'index j. Mais les éléments d'index j supérieur à i n'ont pas encore été créés !
> 
> ...



Merci Je vais tester ton code.
le code en C#  ( il fonctionne très bien) :

private void button2_Click(object sender, System.EventArgs e)
		{
			int[] tab = new int[7];

			for(int i=0; i < 7 ; i++ )
			{
				Random Alea = new Random();

				tab_ = Alea.Next() %49 + 1;

				for(int j=0; j < 7 ; j++ )
				{
					if ((i != j) && (tab == tab[j]))
					{
						i--;
						break;
					}
				}

			}

		num1.Text = tab[0].ToString();
		num2.Text = tab[1].ToString();
		num3.Text = tab[2].ToString();
		num4.Text = tab[3].ToString();
		num5.Text = tab[4].ToString();
		num6.Text = tab[5].ToString();
		num7.Text = tab[6].ToString();

		}_


----------



## arnolix (15 Octobre 2004)

vite dit : es-tu sûr qu'il ne s'agit pas de i<j  plutôt  que j<7 dans ta deuxième boucle ?
Essaie avec i<j pour voir

ps : ai commis petite erreur sur le booléen OK.

enlève   OK = ! dans le test if,     puis entre les accolades mets OK = NO après j++


----------



## tatouille (15 Octobre 2004)

comparer un language object
avec un language pseudo object

bof


----------



## tatouille (15 Octobre 2004)

arnolix a dit:
			
		

> vite dit : es-tu sûr qu'il ne s'agit pas de i<j  plutôt  que j<7 dans ta deuxième boucle ?
> Essaie avec i<j pour voir



oui c'est i<j 
puisque le tableau final fait 6 entrées

et surtout ca  [remTableau addObject: remNombre]; non !!!!!!!!!!!!


mais je te conseille de faire une routine qui rempli un tableau
et juste de demander au tableau si il possède déjà cette clef

sinon

monmaintableau->add
et si mon tableau est plein de ses clefs uniques ont continu


----------



## _remi (15 Octobre 2004)

tatouille a dit:
			
		

> oui c'est i<j
> puisque le tableau final fait 6 entrées
> 
> et surtout ca  [remTableau addObject: remNombre]; non !!!!!!!!!!!!
> ...



Hé! Tacouille soit plus clair, je débute sur Cocoa et Objective C. Et j'ai vraiment des difficultés...


----------



## tatouille (15 Octobre 2004)

oui je me suis relu peu importe le language


routine {

boucle {

genere->rands
rempli->tmptableau

si clefs uniques dans tmptableau égal à 6
copie->clefs uniques->dansfinaltableau

sort
}

}


Cordialement tacramouille


----------



## Céroce (15 Octobre 2004)

Tu as peut être tes raisons (pédagogiques), mais pourquoi utiliser les classes NSMutableArray et NSNumber ?
Utiliser les tableaux comme tu le fais en C# est tout de même bien plus clair.


Ajoute à la fin de ta méthode 
[remTableau dealloc];

Il n'est pas nécessaire de faire des dealloc sur les NSNumber puisqu'ils appartiennent au NSMutableArray.


----------



## _remi (15 Octobre 2004)

arnolix a dit:
			
		

> vite dit : es-tu sûr qu'il ne s'agit pas de i<j  plutôt  que j<7 dans ta deuxième boucle ?
> Essaie avec i<j pour voir
> 
> ps : ai commis petite erreur sur le booléen OK.
> ...



Je suis de retour, je viens de tester ton code mais il permet d'avoir 2 valeurs identiques.

le voilà :


- (IBAction)generateid)sender
{
  NSMutableArray *remTableau;
  int i = 0;
  int j = 0;
  NSNumber *remNombre;

  NSAutoreleasePool *pool = [[ NSAutoreleasePool alloc] init];

  remTableau = [[NSMutableArray alloc] init];

  for (i; i < 7; i++)
    {
	remNombre = [[NSNumber alloc] initWithInt random() % 49) + 1];
	[remTableau addObject: remNombre];
	[remNombre release];
	 BOOL ok = YES;
	while (j < i && ok)
	    {
		if ([remTableau objectAtIndex: i] == [remTableau objectAtIndex: j])
		    {
			[remTableau removeObjectAtIndex: i];
			}
		j++;
		ok = NO;
	    }
	}


----------



## arnolix (15 Octobre 2004)

>Céroce

Justement en utilisant des classes comme NSMutableARRay et compagnie on mets des garde-fous qu'il ne semble pas y avoir avec des tab[] et consorts. tu fais tab[10000000] sans problème, mais le résultat est plus que douteux à l'execution. Par contre avec un NSMutableArray...
Autre truc  : tu veux envoyer un message whatTimeIsItPlease à tous tes objets d'un NSArray. Tape :
[montableau makeObjectsPerformSelectorselector(whatTimeIsItPlease)]
(A condition que tes objets y répondent) . Je trouve ca supercool, mais c'est peut-être une question de gout


----------



## arnolix (15 Octobre 2004)

Le pointeur j doit être remis à 0, ainsi que ok, à chaque nouveau élément nouvel élément introduit par la boucle for (i...   Le ok est avant j++, pas après

Voila ce que je taperai. Mais ne l'ai pas vérifié encore

- (IBAction)generateid)sender
{
NSMutableArray *remTableau;



NSNumber *remNombre;

NSAutoreleasePool *pool = [[ NSAutoreleasePool alloc] init];

remTableau = [[NSMutableArray alloc] init];
int i ; int j;BOOL ok ;
for (i=0; i < 7; i++)
{
remNombre = [[NSNumber alloc] initWithInt random() % 49) + 1];
[remTableau addObject: remNombre];
[remNombre release];
 j = 0; ok = YES;
while (j < i && ok)
{
if ([remTableau objectAtIndex: i] == [remTableau objectAtIndex: j])
{
[remTableau removeObjectAtIndex: i];ok = NO;
}
j++;

}
}


----------



## _remi (15 Octobre 2004)

arnolix a dit:
			
		

> Le pointeur j doit être remis à 0, ainsi que ok, à chaque nouveau élément nouvel élément introduit par la boucle for (i...   Le ok est avant j++, pas après
> 
> Voila ce que je taperai. Mais ne l'ai pas vérifié encore
> 
> }




Non marche toujours pas...


----------



## arnolix (15 Octobre 2004)

Ton tableau remTableau doit être alloué en dehors de ta méthode generate:.  Tout ce qui y est déclaré est perdu au retour. C'est dans main{} que tu place :  remTableau = [NSMutableArray new] et NSAutoRelease...


----------



## _remi (15 Octobre 2004)

cette méthode est dans une classe si je j'alloue mon instance de tableau ailleurs elle ne marche..


----------



## arnolix (15 Octobre 2004)

Alors tu ajoutes une méthode accesseur   -(nsmutablearray*)montableau  à la classe principale qui le contient. Sinon c'est impossible !


----------



## _remi (16 Octobre 2004)

Merci pour tous tes conseils, mais je ne comprend pas: le tableau fonctionne bien grâce à la boucle et s'affiche avec des valeurs aléatoires dans les NSTextField. C'est la deuxième condition avec un for ou un while qui ne marche pas, il peut avoir deux valeurs égales (voir la capture). J'ai donc procédé par étape et je me suis aperçu que même ce code marche pas:
int varTest;
for (i = 0; i < 7; i++)
{
 remNombre = [[NSNumber alloc] initWith'Int' random() % 49) + 1];
[remTableau addObject: remNombre];
[remNombre release];
if (i < 7){    // j'ai testé plusieurs conditions avec des if dans des for pour incrémenter un entier rien ne s'affiche!!
varTest +=  5;
 }
[monTexField setIntValue: varTest]; // ce NStextField ne fonctionne que si je déactive les 7 autres et encore pas toujours enfin des trucs complètement aléatoires...
Peut-être que mon .nib est corrompu ou XCode 1,5 ne fonction pas sur un G3 BB scsi ou est il buggé?

enfin laisse tomber et merci...


----------



## Céroce (16 Octobre 2004)

arnolix a dit:
			
		

> >Céroce
> 
> Justement en utilisant des classes comme NSMutableARRay et compagnie on mets des garde-fous qu'il ne semble pas y avoir avec des tab[] et consorts. tu fais tab[10000000] sans problème, mais le résultat est plus que douteux à l'execution. Par contre avec un NSMutableArray...
> Autre truc  : tu veux envoyer un message whatTimeIsItPlease à tous tes objets d'un NSArray. Tape :
> ...



Non, c'est pas une question de goût, c'est une question de lisibilité (regarde, le programme en C# est bien plus lisible) et de PERFORMANCES.

Créer des objets (allocation dynamique) et leur envoyer des messages prend beaucoup plus de temps que de réserver un simple tableau (sur la pile, d'où l'impossibilité de réserver 40 000 000 d'octets). Je ne dénigre pas l'utilité des NSArray pour autant.
Les langages basés sur le C (comme ObjC) restent proches de la machine. Ça présente des avantages (vitesse, compacité) mais aussi de grandes responsabilités sur le développeur.


----------



## Didier Guillion (16 Octobre 2004)

Bonjour,

Oui, et on se pose la question si la syntaxe d'Objectice C (ou autre C sharp) est encore "humaine".

Personnellement, je prefere une syntaxe C pure et dure bien verbeuse et abondamment commentée.

Cordialement


----------



## Céroce (16 Octobre 2004)

Une programme qui marche:



- (IBAction)genererid)sender
{
    int 	nombre;
    int 	nombres[NOMBRES_A_GENERER];
    int 	compteurNombres;
    int		compteurDeja;
    BOOL	dejaDansTableau;

    // Le premier nombre est forcément absent du tableau
    nombres[0] = (random() % 49) + 1;

    // Pour les autres nombres
    for(compteurNombres = 0; compteurNombres < NOMBRES_A_GENERER; compteurNombres++)
    {
        do
        {
            nombre = (random() % 49) + 1;

            dejaDansTableau = NO;
            for(compteurDeja = 0; compteurDeja < compteurNombres; compteurDeja++)
            {
                if(nombres[compteurDeja] == nombre)
                {
                    dejaDansTableau = YES;
                    break;
                }        
            }
        } while (dejaDansTableau == YES);

        // On a trouvé un nouveau nombre; on le stocke
        nombres[compteurNombres] = nombre;
    }

    // Affichage
    [champ1 setIntValue:nombres[0]];
    [champ2 setIntValue:nombres[1]];
    [champ3 setIntValue:nombres[2]];
    [champ4 setIntValue:nombres[3]];
    [champ5 setIntValue:nombres[4]];
    [champ6 setIntValue:nombres[5]];
    [champ7 setIntValue:nombres[6]];
}


----------



## _remi (16 Octobre 2004)

Céroce a dit:
			
		

> Non, c'est pas une question de goût, c'est une question de lisibilité (regarde, le programme en C# est bien plus lisible) et de PERFORMANCES.
> 
> Créer des objets (allocation dynamique) et leur envoyer des messages prend beaucoup plus de temps que de réserver un simple tableau (sur la pile, d'où l'impossibilité de réserver 40 000 000 d'octets). Je ne dénigre pas l'utilité des NSArray pour autant.
> Les langages basés sur le C (comme ObjC) restent proches de la machine. Ça présente des avantages (vitesse, compacité) mais aussi de grandes responsabilités sur le développeur.



Pourtant en C# j'initialise bien un objet avec le constructeur:  int[] tab = new int[7];
seulement en C# la condition: if ((i != j) && (tab_ == tab[j])) fonctionne.

 alors que en ObjectiveCocoa: if( (i != j) && ([remTableau objectAtIndex: j] == [remTableau objectAtIndex: i])) non._


----------



## _remi (16 Octobre 2004)

< Cérose:

Merci j'allais abandonner la comparaison des objets dans le tableau pour l'écrire en C. Je préfère la syntaxe par point, la gestion de la memoire et les espaces nommés du C# sans remettre en cause l'efficacité de l'ObjectiveCocoa, je m'intéresse à ces langages par curiosité je développe surtout des produits multimédia sur IShell...


----------



## tatouille (16 Octobre 2004)

ne laisse pas tomber 

mais 

1/ utilises des tableaux simples au lieu de mutable ca ne te sert à rien

2 / une comparaison lineaire est toujours mieux que recursive


3/ print ta sortie dans tes 2 boucles et tu vas comprendre ce que t'a dit arnolix


----------



## arnolix (16 Octobre 2004)

Bon en y regardant de plus près il y a un truc qui m'a échappé c'est le test :

[remTableau objectAtIndex: i] == [remTableau objectAtIndex: j]


C'est une erreur classique, en fait [remTableau objectAtIndex: i] renvoit l'adresse de l'objet qui se trouve à l'index i du tableau, et non pas la valeur de l'objet (ici un nombre). Avec ca tu testes donc si deux objets sont distincts ou non physiquement, mais qui peuvent en fait avoir des champs égaux (des jumeaux en quelque sorte).

Il faut utiliser la méthode -isEqual: qui appelle la méthode -description pour comparer leur contenu.

Par exemple, tape quelque part dans ton code, et consulte ta console lors de l'éxecution :

NSLog(@"[remTableau objectAtIndex: i] = %d",[remTableau objectAtIndex: i])

ainsi que :

NSLog(@"[[remTableau objectAtIndex: i] description] = %@",[[remTableau objectAtIndex: i] description])

Tu verras alors la différence

Pour un test correct, ca devrait donner :

[[remTableau objectAtIndex: i] isEqual:[remTableau objectAtIndex: j]]

Essaie le. 

PS : suis pas trop dispo en ce moment. Mes réponses tarderont peut-être


----------



## arnolix (16 Octobre 2004)

>céroce et guillon


Suis pas un défenseur de Obj-C et de sa syntaxe qui devient lourdingue.

Sauf que le problème de -remy c'est *d'utiliser correctement  le framework cocoa* .

Son truc de fabriquer des tableaux, on le fait comme on veut.

L'avantage de cocoa c'est de disposer, pour un tableau par exemple, de fonctionnalités poussées sans avoir à les implémenter soi-même. Mais ce au prix de la vélocité.

C'est au dévellopeur de faire ces choix. Et c'est tant mieux.


----------



## _remi (16 Octobre 2004)

arnolix a dit:
			
		

> Bon en y regardant de plus près il y a un truc qui m'a échappé c'est le test :
> 
> 
> Pour un test correct, ca devrait donner :
> ...



désolé mais je crois que la syntaxe n'est pas bonne... il me dit qu'il y a une erreur avant isEqual.

mais Bon week-end


----------



## _remi (16 Octobre 2004)

Céroce a dit:
			
		

> Une programme qui marche
> 
> // Le premier nombre est forcément absent du tableau
> nombres[0] = (random() % 49) + 1;
> ...




mais non pourquoi ?
il marche très bien sans cette ligne...
merci, tant pis pour cocoa...


----------



## Céroce (17 Octobre 2004)

En effet.
C'est une optimisation et le programme me paraît plus clair ainsi.
Là, c'est une affaire de goût pour le coup.


----------

