Playgrounds moi pas connaître ! Je préfère travailler avec le simulateur.
Ton code est un peu étrange. Tu crées une variable globale, que tu modifie ensuite dans le corps d’une fonction. L’idée de la programmation objet est d’isoler au maximum les choses, les unes des autres.
J’ai téléchargé le livre de MB pour voir ce qu’il demande, mais je n’ai pas trouvé. Je présume que le but est d’afficher un rectangle comme ça :
*****
* *
* *
* *
*****
J’ai utilisé ton code, qui me donne ça :
(ligne)
** * * *
** * * *
** * * *
** * * *
Je crois que tu as oublié un caractère dans le premier print().
print("(ligne)")
C’est mieux comme ça :
print("\(ligne)")
A noter, qu’on peut utiliser une formulation plus simple, pour afficher le contenu d’une variable. Il suffit d’écrire :
print (ligne)
J’en reviens à ton code. Le résultat est encore loin d’être parfait :
** * * *
** * * *
** * * *
** * * *
** * * *
Tu utilises la méthode String.insert() pour ajouter un caractère à la fin d’une String.
Le code déclare une chaîne ne contenant qu’un caractère “" et lui ajoute successivement un "” et un " ", d’où l’aspect un peu étrange :
** * * * *
Ce serait plus esthétique en inversant l’ordre des ajouts. Avec un " " et un “*”, tu aurais :
* * * * *
Je te propose une variante, utilisant l’opérateur “+” et la méthode String(repeat:)
pour créer une chaîne en répétant n fois le même caractère.
func dessinerUnCarre(taille: Int) {
let lignePleine = String(repeating: "*", count: taille)
let ligneVide = "*" + String(repeating: " ", count: taille-2) + "*"
print (lignePleine)
for _ in 2...taille {
print (ligneVide)
}
print (lignePleine)
}
Elle est entièrement autonome, utilisant ces propres variables pour faire des manipulations de caractères. Par rapport au reste de l’application c’est une boîte noire opaque remplissant une fonction précise.
Résultat :
*****
* *
* *
* *
* *
*****
Voici la variante pour faire la même chose avec un caractère quelconque :
func dessinerUnCarre(taille: Int, char:String) {
let lignePleine = String(repeating: char, count: taille)
let ligneVide = char + String(repeating: " ", count: taille-2) + char
print (lignePleine)
for _ in 2...taille {
print (ligneVide)
}
print (lignePleine)
}
Avec le caractère “X” :
XXXXX
X X
X X
X X
X X
XXXXX
Pour en revenir à ton code, il y a TROIS problèmes :
UN :
Tu as utilisé une syntaxe bizarroïde pour l’instruction insert.
choixCharacter.insert("(\choixCharacter)", at: choixCharacter.endIndex)
Xcode en perd son latin. Il ne comprend pas pourquoi tu as ajouté tous ces symboles inutiles devant et derrière le nom de la variable. Il faut écrire :
choixCharacter.insert(choixCharacter, at: choixCharacter.endIndex)
DEUX :
choixCharacter est un paramètre de la fonction. TOUS les paramètres sont sensés être constants. Pourtant tu tentes de modifier sa valeur dans ton code. C’est pourquoi Xcode t’insulte avec le message “Cannot use mutating member on immutable value: ‘choixCharacter’ is a ‘let’ constant”.
Si tu veux modifier le contenu d’un paramètre d’une fonction, tu doit en créer une copie mutable (pouvant être modifié - déclaration avec var).
Ceci dit, je ne vois pas l’intérêt de faire ça ici. Pour résoudre ton problème, il suffit de créer une variable temporaire et d’écrire dedans.
var ligne = ""
TROIS :
La fonction insert() permet d’insérer un caractère à la fin d’un String
func insert(_ newElement: Character, at i: String.Index)
Selon le contexte “*” peut être considéré comme un caractère ou une String courte d’un seul caractère. Quand tu tapes :
ligne.insert("*", at: ligne.endIndex)
Xcode, connaissant la syntaxe de insert, comprend que “*” est un caractère et l’utilise comme tel.
Dans la seconde fonction, choixCharacter est un String (paramètre de la fonction), mais il est transmis à insert() à la place d’un Character. Xcode n’apprécie pas et hurle … Pour le calmer, il faut caster (transformer) le String en Character.
let maString = "z"
let char = Character(maString)
Voici une version modifiée de ton code, corrigeant les 3 problèmes :
func dessinerUnCarre2(taille: Int, choixCharacter:String) {
//on définit la longueur d'une ligne selon la taille du carré
var ligne = choixCharacter + " "
func ligneDeCaracteres() {
for _ in 2...taille {
ligne.insert(Character(choixCharacter), at: ligne.endIndex)
ligne.insert(" ", at: ligne.endIndex)
}
print(ligne)
}
//on imprime le nombre de lignes correspondant à la taille du carré
ligneDeCaracteres()
for _ in 2...taille {
print(ligne)
}
}
Résultat avec la lettre “O” :
O O O O O
O O O O O
O O O O O
O O O O O
O O O O O
On peut aussi écrire la fonction de manière à lui transmettre directement un Character au lieu d’une String.
func dessinerUnCarre2(taille: Int, choixCharacter:Character) {
//on définit la longueur d'une ligne selon la taille du carré
var ligne = String(choixCharacter) + " "
func ligneDeCaracteres() {
for _ in 2...taille {
ligne.insert(choixCharacter, at: ligne.endIndex)
ligne.insert(" ", at: ligne.endIndex)
}
print(ligne)
}
//on imprime le nombre de lignes correspondant à la taille du carré
ligneDeCaracteres()
for _ in 2...taille {
print(ligne)
}
}