Merci @anthonyfassler1 (du bout des lèvres, sans aucune sincérité)
Reprise des émissions, donc :
L’automate est une classe, pour les raisons expliqués plus haut. Je ne comprend toujours pas pourquoi il est impossible d’utiliser un délai dans une Struct, alors que ça marche dans une class !
Enfin bon, ce n’est pas la peine de s’attarder sur ce genre de détails. D’ici 15 jours, Apple doit nous donner la version suivante de SwiftUI, qui devrais remettre pas mal de choses à plat.
import SwiftUI
enum EtatAutomate: String {
case indetermine = "Indeterminé"
case parametrage = "Paramétrage"
case tourJoueur = "Tour Joueur"
case tourIA = "Tour IA"
case joueurGagnant = "Joueur Gagnant"
case IAGagnant = "Joueur Perdant"
case pasDeGagnant = "Pas de Gagnant"
case finDujeu = "Fin du Jeu"
case reset = "Reset"
}
// struct Automate {
class Automate : ObservableObject {
@Published var damier = Damier(nbLignes: 3, nbColonnes: 3)
@Published var interfaceActive = false
@Published var opaciteDamier = 1.0
private var ia = IA()
var etatCourant = EtatAutomate.indetermine
init() {
activer(etat: .parametrage)
}
}
extension Automate {
func activer(etat: EtatAutomate) {
switch etat {
case .indetermine:
break
case .parametrage:
opaciteDamier = 0.1
interfaceActive = false
break
case .tourJoueur:
opaciteDamier = 1.0
interfaceActive = true
break
case .tourIA:
opaciteDamier = 1.0
interfaceActive = false
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.ia.jouerTour(damier: &self.damier)
self.activer(etat: .tourJoueur)
}
case .joueurGagnant:
opaciteDamier = 1.0
interfaceActive = false
break
case .IAGagnant:
opaciteDamier = 1.0
interfaceActive = false
break
case .reset:
// interfaceActive = false
// compteurIA = 0
// compteurJoueur = 0
break
case .pasDeGagnant:
opaciteDamier = 1.0
interfaceActive = false
break
case .finDujeu:
interfaceActive = false
break
}
etatCourant = etat
}
}
L’IA est une struct. Elle n’utilise pas de Binding, mais l’opérateur inout qui fait la même chose.
import SwiftUI
struct IA {
func jouerTour(damier : inout Damier) {
if let index = damier.rechercheCaseVide() {
damier.changerCase(index: index, contenu: .ia)
}
}
}
Normalement les variables envoyées comme paramètres d’une fonction sont juste des copies des valeurs initiales, ne pouvant être modifiés.
Si une variable (un tableau ici) est déclarée en inout, la fonction travaille sur une copie, comme d’habitude. Mais quand le système sort de la fonction, les données originales sont effacés et remplacés par la copie modifiée !
Le fonctionnement est le suivant :
- création d’une copie locale du Damier
- recherche d’une case vide (c’est l’algorithme utilisé dans la démo de GitHub)
- marquage de la Case avec l’attribut .ia dans la copie
- Effacement du Damier original et remplacement par la copie de travail. Le damier étant stocké dans une variable @Published de la classe, SwiftUI avertis le reste du système, qu’il y a eu une modification du modéle, et qu’il faut redessiner le contenu de l’écran.
Voila, je crois que je n’ai rien oublié. A noter qu’il n’y a aucun @Binding, nul part dans le code. J’ai pas mal galèré avec les différents opérateurs de Binding ce WE, surtout les initialisations et franchement ça me gave. C’est très bien pour les choses simples, mais c’est horrible dans les cas particuliers. J’espère que le prochain SwiftUI vas simplifier tout ça.
Des questions ?