• 20 heures
  • {0} Facile|{1} Moyenne|{2} Difficile

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

J'ai tout compris !

Mis à jour le 21/06/2013

TP – Un jeu de Mastermind

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Vous voici donc arrivés au premier TP !
TP signifie « Travaux Pratiques ». En clair, vous allez pratiquer ce que nous venons de voir. Régulièrement, je vous ferai travailler grâce à ce genre d'exercices et vous allez vite voir que, mine de rien, vous en savez des choses.

Évidemment, je ne vous demanderai jamais rien que vous ne soyez capables de faire. Enfin pas vraiment… Il se peut que cela arrive, mais dans ce cas je vous donnerai la marche à suivre pour parvenir à la fin du TP.
Bon, vous êtes prêts ? Alors allons-y !

Instructions pour réaliser le TP

Dans ce premier programme, votre device va choisir un nombre de quatre chiffres au hasard. Vous devrez le trouver en un minimum d'essais en proposant des nombres de quatre chiffres. Pour chaque proposition, le nombre de chiffres bien placés sera indiqué. Le résultat attendu se trouve à la figure suivante.

Le rendu attendu de notre Mastermind

Pour parvenir à ce résultat, vous devrez :

  1. définir une application basée sur le modèle Single View Application ;

  2. créer l'interface de l'application dans Interface Builder ;

  3. relier les éléments de l'interface au code Objective-C ;

  4. tirer au hasard un nombre de quatre chiffres ;

  5. afficher le clavier lorsque le joueur clique dans la zone de saisie et l'effacer lorsqu'il valide sa saisie en appuyant sur Retour ;

  6. écrire les instructions nécessaires pour comparer les nombres proposés par le joueur et le nombre à découvrir et afficher un message en conséquence.

Normalement, seule l'étape 4 devrait vous poser un problème. Les autres ont déjà été vues ; si vous avez le moindre problème avec, n'hésitez pas à lire les chapitres précédents correspondants.

Pour tirer un nombre aléatoire, nous utiliserons la fonction arc4random(), qui renvoie un nombre aléatoire compris entre 0 et 4 294 967 295. Sauf que nous voulons un nombre de 4 chiffres, donc compris entre 1000 et 9999. Bref, on en est loin. Nous allons donc devoir ruser, grâce au modulo. Regardez le code suivant :

arc4random() % 9000 + 1000;

arc4random() % 9000 renvoie un nombre compris entre 0 et 8999. En lui ajoutant 1000, le nombre est compris entre 1000 et 9999.

L'affichage du clavier est automatique lorsque le joueur clique dans la zone de saisie. Par contre, ce sera à vous de faire disparaître le clavier lorsque le joueur validera la saisie en appuyant sur la touche Retour. Cette action sera accomplie en appelant la méthode resignFirstResponder de la classe sender.

Je suis sûr que vous êtes pressés de commencer. Imaginez un peu, votre première application ! Alors, n'attendez plus, commencez dès maintenant. Et soyez assurés que je ne serai pas loin de vous. Si vous avez une difficulté quelconque, reportez-vous à la correction qui suit. J'ai détaillé chaque étape de façon à ce qu'aucun blocage ne vous empêche d'arriver au bout du TP. Cependant, il est tout à fait normal de passer un long moment à réfléchir à ce que vous devez faire. Vous pouvez même vous aider d'une feuille blanche et d'un stylo en mettant par écrit vos idées.

Correction

J'espère que vous n'avez pas eu trop de problèmes dans ce TP. Voici ma correction, dans laquelle je passe en revue tous les points qui auraient pu « coincer ».

Création de l'application

Dans Xcode, sélectionnez Create a new Xcode project dans la boîte de dialogue affichée au lancement du programme. Si aucune boîte de dialogue n'est affichée, lancez la commande New/New project dans le menu File. Dans la boîte de dialogue Choose a template for your new project, choisissez Single View Application puis cliquez sur Next. Donnez le nom mastermind à l'application, tapez test dans la zone de texte Company Identifier, cochez la case Use Storyboard et cliquez sur Next. Choisissez un dossier pour stocker l'application et validez en cliquant sur Create.
Au bout de quelques instants, le squelette de l'application est créé.

Définition de l'interface

Sous le dossier mastermind, cliquez sur l'entrée mainStoryboard.storyboard dans la barre de navigation (volet gauche de l'application). Une interface désespérément vide est affichée dans la partie droite de la fenêtre (figure suivante). Rassurez-vous, nous allons très vite la remplir.

L'interface est vide

Dans la partie supérieure droite de la fenêtre (c'est-à-dire dans la barre d'outils), au-dessus du libellé View, cliquez sur l'icône Hide or Show the utilities (1) et cliquez sur l'icône Show the Object Library (2) pour faire apparaître la bibliothèque, comme indiqué à la figure suivante.

Il faut afficher la librairie d'objets

Ajoutez deux Label, un Text Field, un Text View et un Round Rect Button à l'interface, puis redimensionnez-les pour obtenir une disposition semblable à la figure suivante.

Disposition des objets de l'application

Double-cliquez tour à tour sur les différents contrôles et insérez le texte spécifié dans le tableau suivant :

Contrôle

Texte

Premier Label

Saurez-vous trouver le nombre de quatre chiffres que j'ai choisi ?

Deuxième Label

Tentez votre chance

Text View

Round Rect Button

Choisir un autre nombre

Le texte saisi dans le premier Label est trop long. Comment l'afficher sur deux lignes ?

Si nécessaire, cliquez sur l'icône Show the Attributes inspector dans la partie supérieure du volet gauche. Si vous cliquez sur le Label, ses caractéristiques apparaissent dans le volet de l'inspecteur, comme sur la figure suivante. Sélectionnez Word Wrap dans la liste déroulante Line Breaks, tapez 2 dans la zone de texte Lines et redimensionnez le contrôle pour obtenir l'effet recherché.

Il faut afficher le texte sur deux lignes

Pour supprimer le texte proposé par défaut dans le contrôle TextView, cliquez dessus dans Interface Builder, sélectionnez le texte dans la zone Text du volet de l'inspecteur, appuyez sur la touche Suppr, puis sur la touche Entrée du clavier.

Suppression du texte par défaut
Pour afficher un clavier numérique

Liaison des contrôles au code

Cachez la zone d'utilitaires en cliquant sur l'icône Hide or show the Utilities (1) et affichez le code ViewController.h en cliquant sur l'icône Show the Assistant editor (2), comme montré à la figure suivante.

Il est temps d'afficher le code de l'application

Vous allez maintenant relier les contrôles de l'interface au code.

Contrôle-glissez-déposez tour à tour les contrôles Text Field et Text View de l'interface jusqu'au volet de code. Donnez le nom saisie au Text Field, et le nom resultats au Text View.

Si vous avez suivi mes indications, le fichier ViewController.h doit maintenant ressembler à ceci :

#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UITextField *saisie;
@property (weak, nonatomic) IBOutlet UITextView *resultats;
@end

Pour terminer les liaisons, vous devez définir une action pour le contrôle Round Rect Button. Contrôle-glissez-déposez ce contrôle juste avant l'instruction @end. Au relâchement du bouton gauche de la souris, sélectionnez Action dans la zone Connection, tapez autrenombre dans la zone de texte Name et cliquez sur Connect (figure suivante).

Définition d'une action pour le contrôle Round Rect Button

La ligne suivante est ajoutée au code :

- (IBAction)autrenombre:(id)sender;

Sauvegardez votre projet avec la commande Save dans le menu File.
Juste histoire de souffler un peu, vous pouvez cliquer sur l'icône Run dans la barre d'outils et savourer votre travail. Le résultat affiché devrait être semblable à la figure suivante.

Voici à quoi ressemble l'application pour le moment

Cliquez sur Stop pour revenir à la dure réalité : vous devez maintenant écrire le code qui donnera vie à l'application !

Avant de commencer, cliquez sur ViewController.h dans le volet de navigation et définissez la variable d'instance nombreChoisi de type int pour mémoriser le nombre choisi par le device. Le fichier d'en-têtes doit maintenant ressembler à ceci :

@interface ViewController : UIViewController
{
int nombreChoisi;
}
@property (weak, nonatomic) IBOutlet UITextField *saisie;
@property (weak, nonatomic) IBOutlet UITextView *resultats;
- (IBAction)autrenombre:(id)sender;
@end

Je vous sens vraiment impatients de faire fonctionner l'application. Alors, passons sans plus attendre à l'écriture du code.

Écriture du code

Si nécessaire, affichez la zone de navigation en cliquant sur l'icône Hide or show the Navigator, dans la partie droite de la barre d'outils, au-dessus du libellé View.
Cliquez sur mastermindViewController.m dans la zone de navigation. Le code généré par Xcode est de taille respectable. Il contient les différentes méthodes utilisées par l'application :

//Pour une meilleure lisibilité, j'ai supprimé les commentaires ajoutés automatiquement au début du fichier par Xcode
#import "ViewController.h"
@implementation ViewController
@synthesize saisie;
@synthesize resultats;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setSaisie:nil];
[self setResultats:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (IBAction)autrenombre:(id)sender {
}
@end

En examinant les dernières lignes, vous reconnaissez certainement la partie déclarative liée à l'action sur le contrôle Round Rect Button :

- (IBAction)autrenombre:(id)sender {
}

Quelques lignes plus haut, la méthode viewDidLoad va vous permettre d'initialiser l'application :

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}

Mais pourquoi serait-il nécessaire d'initialiser l'application me direz-vous ? Eh bien… pour choisir le nombre à découvrir !

Tirage aléatoire du nombre à découvrir

Ajoutez la ligne que nous avons vue plus haut, après [super viewDidLoad]; :

nombreChoisi = arc4random() % 9000 + 1000;

L'application sait maintenant tirer au hasard un nombre compris entre 1000 et 9999.

Traitement suite à la proposition d'un nombre

Lorsque le joueur a saisi un nombre de quatre chiffres, il appuie sur la touche Return pour valider la saisie. Le clavier doit alors disparaître de l'écran et le nombre entré doit être comparé au nombre à découvrir.
Pour ce faire, il est nécessaire de capturer l'événement « appui sur la touche Return » et de le relier à une méthode afin d'effectuer les traitements nécessaires.
Dans un premier temps, commencez par définir la méthode saisieReturn dans le fichier d'en-têtes. Cliquez sur ViewController.h dans le volet de navigation et entrez cette ligne, juste au-dessus du @end final :

- (IBAction)saisieReturn :(id)sender;

Le fichier d'en-têtes doit maintenant ressembler à ceci :

#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
{
int nombreChoisi;
}
@property (weak, nonatomic) IBOutlet UITextField *saisie;
@property (weak, nonatomic) IBOutlet UITextView *resultats;
- (IBAction)autrenombre:(id)sender;
- (IBAction)saisieReturn :(id)sender;
@end

Pour écrire le code qui efface le clavier de l'écran, cliquez sur ViewController.m dans le volet de navigation et définissez la méthode saisieReturn comme suit :

-(IBAction)saisieReturn:(id)sender
{
[sender resignFirstResponder];
}

La méthode resignFirstResponder efface le clavier. C'est aussi simple que cela !

N'essayez pas d'exécuter l'application : vous devez auparavant relier l'événement « appui sur la touche Retour » à la méthode saisieReturn.

Pour cela, sélectionnez l'entrée MainStoryboard.storyboard dans la zone de navigation, affichez le volet des utilitaires en cliquant sur Hide or show the Utilities dans la barre d'outils, puis cliquez sur Show the Connections inspector, dans la partie supérieure. Cliquez sur le contrôle Text Field dans la zone d'édition pour le sélectionner. Sous Sent Events, repérez le rond à droite de l'événement Did End On Exit et déplacez-le sur l'icône View Controller, dans la partie inférieure de la zone d'édition. Au relâchement du bouton gauche de la souris, deux choix vous sont proposés : autreNombre et saisieReturn (figure suivante). Cliquez sur saisieReturn. Ainsi, la méthode saisieReturn sera exécutée lorsque l'utilisateur appuiera sur la touche Return du téléphone.

Deux choix sont proposés : autreNombre et saisieReturn

Vous pouvez maintenant exécuter l'application et vérifier que l'appui sur la touche Return dissimule le clavier.

Il est temps maintenant d'écrire le code relatif au traitement du nombre choisi par le joueur.
Cliquez sur ViewController.m dans la zone de navigation et complétez la méthode saisieReturn comme suit :

-(IBAction)saisieReturn:(id)sender
{
[sender resignFirstResponder];
int bienPlace = 0;
int charIndex; //Index de boucle pour parcourir tous les caractères des chaînes à comparer
unichar testChar1, testChar2; //Les caractères à comparer : testChar1 dans le nombre proposé, testChar2 dans le nombre à trouver
for (charIndex = 0; charIndex < 4; charIndex++)
{
testChar1 = [saisie.text characterAtIndex:charIndex];
testChar2 = [[NSString stringWithFormat:@"%d", nombreChoisi] characterAtIndex:charIndex];
if (testChar1 == testChar2)
bienPlace++;
}
resultats.text = [NSString stringWithFormat:@"%@%@%d%@%@", saisie.text, @" : Bien placés : ", bienPlace, @"\r", resultats.text];
if (bienPlace == 4)
resultats.text = [NSString stringWithFormat:@"%@%d", @"Bravo, le résultat était ", nombreChoisi];
}

Examinons un peu ce code ensemble.

Comme il a été dit précédemment, la ligne 3 supprime le clavier de l'écran. Jusque-là, tout va bien !

Le bloc d'instructions suivant (lignes 4 à 13) compare le nombre entré par le joueur au nombre à découvrir. Les premières lignes déclarent plusieurs variables :

  • la variable entière bienPlace est définie et initialisée à 0 :

  • int bienPlace = 0;

  • la variable entière charIndex est définie mais non initialisée :

  • int charIndex;

  • il en va de même pour les variables unichartestChar1 et testChar2 :

  • unichar testChar1, testChar2;

La comparaison des quatre chiffres se fait dans une boucle for, en utilisant la variable charIndex comme index de boucle :

for (charIndex = 0; charIndex < 4; charIndex++)

À l'intérieur de la boucle, la première instruction s'intéresse à la saisie du joueur. Elle isole le caractère d'index charIndex et le stocke dans la variable unichar testChar1 :

testChar1 = [saisie.text characterAtIndex:charIndex];

La deuxième instruction fait de même, mais sur le nombre tiré aléatoirement. L'instruction est plus complexe, car le nombre choisi aléatoirement est un int et non un NSString. Il est donc nécessaire de le convertir en NSString avant de procéder à l'extraction :

testChar2 = [[NSString stringWithFormat:@"%d", nombreChoisi] characterAtIndex:charIndex];

Le premier message convertit l'int nombreChoisi en un NSString :

[NSString stringWithFormat:@"%d", nombreChoisi]

On extrait de l'objet ainsi obtenu le caractère qui se trouve à l'emplacement charIndex (characterAtIndex:charIndex) et on mémorise ce caractère dans la variable testChar2 (testChar2 =).

Il ne reste plus qu'à comparer testChar1 à testChar2 et à incrémenter la variable bienPlace si ces deux variables sont égales :

if (testChar1 == testChar2)
bienPlace++;

Une fois que les quatre chiffres ont été testés, il faut afficher le résultat dans le contrôle TextView. C'est le rôle de l'instruction suivante :

resultats.text = [NSString stringWithFormat:@"%@%@%d%@%@", saisie.text, @" : Bien placés : ", bienPlace, @"\r", resultats.text];

On utilise pour cela une chaîne formatée ([NSString stringWithFormat: …]). Examinons le format de la chaîne affichée :

%@%@%d%@%@

En comptant le nombre de %, vous pouvez facilement déduire que cette chaîne est composée de cinq éléments. De gauche à droite, deux chaînes (%@), un nombre décimal (%d) et deux chaînes (%@). Ces éléments sont les suivants :

  • la valeur saisie par le joueur, saisie.text ;

  • le texte « Bien placés : » ;

  • la valeur décimale bienPlace, convertie en une chaîne de caractères ;

  • un saut de ligne \r ;

  • les différentes informations précédemment affichées dans le contrôle TextView.

La dernière instruction teste si la partie est terminée :

if (bienPlace == 4)
resultats.text = [NSString stringWithFormat:@"%@%d", @"Bravo, le résultat était ", nombreChoisi];

Si le nombre de caractères bien placés est égal à 4 (if (bienPlace == 4)), cela signifie que le nombre entré est égal au nombre à découvrir. Dans ce cas, un message est affiché dans le contrôle TextView resultats (resultats.text =). Ici encore, nous utilisons une chaîne formatée ([NSString stringWithFormat: …]). Comme vous pouvez le voir, le texte affiché est composé d'une chaîne et d'un nombre entier : le texte « Bravo, le résultat était », suivi du nombre à découvrir.

Tirage aléatoire d'un autre nombre

Pour terminer ce programme, il reste à écrire le code relatif à l'appui sur le bouton Choisir un autre nombre. Rassurez-vous, cette tâche vous paraîtra on ne peut plus simple après ce que vous venez de vivre !
L'entrée ViewController.m étant sélectionnée dans le volet de navigation, déplacez-vous dans la partie inférieure du code et complétez la méthode autrenombre comme suit :

- (IBAction)autrenombre:(id)sender
{
nombreChoisi = arc4random() % 9000 + 1000;
resultats.text = [NSString stringWithFormat:@"%@", @"J'ai choisi un nouveau nombre\r"];
}

La première instruction est identique à celle qui a déjà été utilisée pour tirer un nombre aléatoire. Elle choisit un nombre compris entre 1000 et 9999 et le stocke dans la composante text de l'objet label nombreChoisi :

nombreChoisi = arc4random() % 9000 + 1000;

La deuxième instruction affiche le message « J'ai choisi un nouveau nombre » dans le contrôle TextView :

resultats.text = [NSString stringWithFormat:@"%@", @"J'ai choisi un nouveau nombre\r"];

L'application est entièrement fonctionnelle. Cliquez sur Run et amusez-vous bien !

Le code complet

Je vous mets ici le code complet de l'application.

ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
{
int nombreChoisi;
}
@property (weak, nonatomic) IBOutlet UITextField *saisie;
@property (weak, nonatomic) IBOutlet UITextView *resultats;
- (IBAction)autrenombre:(id)sender;
- (IBAction)saisieReturn :(id)sender;
@end
ViewController.m
#import "ViewController.h"
@implementation ViewController
@synthesize saisie;
@synthesize resultats;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
nombreChoisi = arc4random() % 9000 + 1000;
}
- (void)viewDidUnload
{
[self setSaisie:nil];
[self setResultats:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (IBAction)autrenombre:(id)sender
{
nombreChoisi = arc4random() % 9000 + 1000;
resultats.text = [NSString stringWithFormat:@"%@", @"J'ai choisi un nouveau nombre\r"];
}
-(IBAction)saisieReturn:(id)sender
{
[sender resignFirstResponder];
int bienPlace = 0;
int charIndex;
unichar testChar1, testChar2;
for (charIndex = 0; charIndex < 4; charIndex++)
{
testChar1 = [saisie.text characterAtIndex:charIndex];
testChar2 = [[NSString stringWithFormat:@"%d", nombreChoisi] characterAtIndex:charIndex];
if (testChar1 == testChar2)
bienPlace++;
}
resultats.text = [NSString stringWithFormat:@"%@%@%d%@%@", saisie.text, @" : Bien placés : ", bienPlace, @"\r", resultats.text];
if (bienPlace == 4)
resultats.text = [NSString stringWithFormat:@"%@%d", @"Bravo, le résultat était ", nombreChoisi];
}
@end
Exemple de certificat de réussite
Exemple de certificat de réussite