TP : recopier un mot afficher dans un label

Oui : pour résumer : variable et fonction dans le viewController, le reste dans les fonctions

Dernier point : retirer le mot qui a été affiché de la liste. POur cela, j’essaie de récupérer son index en modifiant la fonction : (j’imagine que c’est encore un problème de portée de variable)

func tirerMotAuHasard(_ liste:[String]) -> String {
    
    let index = Int(arc4random_uniform(UInt32(liste.count)))
    
    return liste[index]
}

Mais ensuite j’ai une erreur avec le code qui supprime le mot de la liste que j’ai placé dans le validationBouton :

A nouveau, la portée des variables:
tu as ta fonction “tirerMotAuHasard”:

func tirerMotAuHasard(_ liste:[String]) -> String {
    let index = Int(arc4random_uniform(UInt32(liste.count)))
    return liste[index]
}

dans laquelle tu définis une variable:

        let index = // ...

donc cette variable “index” n’existe que dans cette méthode là, et donc dans ta fonction “validationButton”, il ne connait pas cette variable

Swift possède une fonction magique permettant de copier le contenu d’un tableau en éliminant certains éléments : filter. Comme son nom l’indique c’est un filtre intelligent. On peut paramétrer les conditions d’acceptation du filtrage.

L’exemple suivant crée une copie du tableau liste, sauf le mot « cc »

let liste = ["aa", "bb", "cc", "dd", "ee »]

let listeCopie = liste.filter { $0 != « cc »)

Pour supprimer un élément directement dans la liste, il faut en créer une copie filtrée et l’affecter à elle-même.

var liste = ["aa", "bb", "cc", "dd", "ee »]

liste = liste.filter { $0 != « bb »)

Attention, la liste doit être définie avec un var pour pouvoir être modifié, sinon Xcode vas crier.

Un petit exemple que je viens de tester (Xcode 8 et Swift 3).

import UIKit

class ViewController: UIViewController {
    
    var liste = ["aa", "bb", "cc", "dd", "ee"]

    override func viewDidLoad() {
        super.viewDidLoad()
        
        print ("Avant : ", liste)
        let mot = "bb"
        liste = liste.filter { $0 != mot }
        print ("Aprés : ", liste)
    }

}

Cela donne ça :

Avant :  ["aa", "bb", "cc", "dd", "ee"]
Aprés :  ["aa", "cc", "dd", "ee »]

filter { $0 != « bb ») signifie recopie tous les éléments du tableau dont le contenu est différent de « bb ».


filter et remove(at:) sont des procédés destructifs retirant l’information de la liste. Il y a moyen de faire un tirage aléatoire sur une liste, sans la détruire, tout en précisant que les tirages sont uniques. Mais c’est plus complexe à coder.


Le nombre d’éléments dans la liste diminuant à chaque question, n’oublie pas d’ajouter un test sur la taille du tableau avant chaque tirage aléatoire, pour éviter les problèmes quand il sera vide !

2 « J'aime »

@Alexandre Je voyais bien le problème venir…

@Draken Je vais tacher d’utiliser cette fonction.

Merci à tous les 2

Encore merci pour votre aide précieuse ; je viens de terminer mon Tp avec quelque chose de fonctionnel :

import UIKit

class ViewController: UIViewController {
var liste = [“boire”, “ou”, “conduire”, “il”, “faut”, “choisir”]
var motAuHasard = “”

func tirerMotAuHasard(_ liste:[String]) -> String {
    return liste[Int(arc4random_uniform(UInt32(liste.count)))]
}


@IBOutlet weak var randomWordLabel: UILabel!
@IBOutlet weak var userTextField: UITextField!
@IBAction func validationButton(_ sender: Any) {
    
        if userTextField.text == motAuHasard {
        userTextField.text = ""
        responseSystemLabel.text = "Bravo, c'est correct !"
        
            if liste.count != 0 {
                motAuHasard = tirerMotAuHasard(liste)
                liste = liste.filter {$0 != motAuHasard} //permet de retirer l'élément de la liste
                randomWordLabel.text = motAuHasard}
    } else {
        responseSystemLabel.text = "Attention, tu te trompes !"
            
    }
    if liste.count == 0 {
        randomWordLabel.text = ""
        responseSystemLabel.text = "Tu as terminé la liste"
    }
}

@IBOutlet weak var responseSystemLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    
    motAuHasard = tirerMotAuHasard(liste)
    liste = liste.filter { $0 != motAuHasard}
    randomWordLabel.text = motAuHasard

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

Prochaine étape : faire un joli affichage …

Oui. Je vais avancer un peu dans le cours en gardant ça sous le coude.
Je pense aussi à d’autres améliorations à tester comme un compte à rebours pour donner une réponse ; ou un affichage du nombre de mots restants dans la liste…

1 « J'aime »

Tu devrais jeter à nouveau un oeil au livre sur les bases de la programmation.
Je vois que tu y es inscrit mais je ne sais pas si tu déjà pris le temps de le lire.
Ne te laisse pas bloquer par le fait que les exemples soient en C#, les problèmes que tu as rencontrés ici sont tous abordés dans ce livre. Regarde par exemples les notions de portée des variables dans le livre.

En effet, j’avais un peu abandonné le livre… Je vais me replonger dedans.