using CoreLibrary.Core; using CoreLibrary.Events; using CoreLibrary.Joueurs; using CoreLibrary.Regles; namespace CoreLibrary { /// /// Représente une partie de jeu. /// public class Partie { public IRegles Regles { get; private set; } private readonly List joueurs = new List(); private readonly List plateaux = new List(); private int? courant; /// /// Événement déclenché lorsqu'il est nécessaire de d'ajouter un joueur. /// public event EventHandler? DemanderNom; /// /// Événement déclenché lorsqu'il est nécessaire d'ajouter un joueur. /// public event EventHandler? AjouterJoueur; /// /// Événement déclenché lorsqu'une partie commence. /// public event EventHandler? DebutPartie; /// /// Événement déclenché lorsqu'un nouveau tour commence. /// public event EventHandler? NouveauTour; /// /// Événement déclenché lorsqu'un code est ajouté. /// public event EventHandler? AjouterCode; /// /// Événement déclenché lorsque la main est passée au joueur suivant. /// public event EventHandler? PasserMain; /// /// Événement déclenché lorsque la partie est terminée. /// public event EventHandler? PartieTerminee; /// /// Méthode pour déclencher l'événement de demande du nom d'un joueur. /// /// Le numéro du joueur à ajouter /// La classe dans laquelle le nom doit être défini private void QuandDemanderNom(int numero, JoueurBuilder joueurBuilder) => DemanderNom?.Invoke(this, new DemanderNomEventArgs(numero, joueurBuilder)); /// /// Méthode pour déclencher l'événement d'ajout d'un joueur. /// /// Le joueur à ajouter. private void QuandAjouterJoueur(Joueur joueur) => AjouterJoueur?.Invoke(this, new AjouterJoueurEventArgs(joueur)); /// /// Méthode pour déclencher l'événement du début d'un partie. /// private void QuandDebutPartie() => DebutPartie?.Invoke(this, new DebutPartieEventArgs()); /// /// Méthode pour déclencher l'événement d'un nouveau tour. /// /// Le joueur dont c'est le tour. /// Le numéro du tour. /// Le code dans lequel il faut ajouter les jetons. /// La grille de jeu. /// Les indicateurs de jeu. private void QuandNouveauTour(Joueur joueur, int tour, Code code, IEnumerable> grille, IEnumerable> indicateurs) => NouveauTour?.Invoke(this, new NouveauTourEventArgs(joueur, tour, code, grille, indicateurs)); /// /// Méthode pour déclencher l'événement d'ajout d'un nouveau code. /// /// Le code ajouté. private void QuandAjouterCode(Code code) => AjouterCode?.Invoke(this, new AjouterCodeEventArgs(code)); /// /// Méthode pour déclencher l'événement de passage de la main au joueur suivant. /// private void QuandPasserMain() => PasserMain?.Invoke(this, new PasserMainEventArgs()); /// /// Méthode pour déclencher l'événement de fin de partie. /// /// La liste des joueurs gagnants. /// La liste des joueurs perdants. private void QuandPartieTerminee(IEnumerable gagnants, IEnumerable perdants) => PartieTerminee?.Invoke(this, new PartieTermineeEventArgs(gagnants, perdants)); /// /// Crée une nouvelle instance de la classe Partie. /// /// Les règles de la partie. public Partie(IRegles regles) { Regles = regles; } /// /// Lance le déroulement de la partie. /// public void Jouer() { JoueurBuilder joueurBuilder = new JoueurBuilder(); joueurBuilder.ConstruireJoueur += Joueur; QuandDemanderNom(joueurs.Count + 1, joueurBuilder); } /// /// Un joueur a saisi son nom /// private void Joueur(Object? sender, ConstruireJoueurEventArgs e) { Joueur joueur = new Joueur(string.IsNullOrEmpty(e.Nom) ? $"Joueur {joueurs.Count + 1}" : e.Nom); Plateau plateau = new Plateau(Regles.TailleCodeMaximum, Regles.TourMaximum); joueurs.Add(joueur); plateaux.Add(plateau); QuandAjouterJoueur(joueur); joueur.JouerCode += Tour; if (joueurs.Count != Regles.NbJoueursMaximum) { JoueurBuilder joueurBuilder = new JoueurBuilder(); joueurBuilder.ConstruireJoueur += Joueur; QuandDemanderNom(joueurs.Count + 1, joueurBuilder); } else { Commencer(); } } /// /// La partie démarre /// private void Commencer() { courant = 0; Joueur joueurCourant = joueurs[courant.Value]; Plateau plateauCourant = plateaux[courant.Value]; QuandDebutPartie(); QuandNouveauTour(joueurCourant, plateauCourant.Tour, new Code(Regles.TailleCodeMaximum), plateauCourant.Grille(), plateauCourant.Indicateurs()); } /// /// Un joueur a joué son tour /// private void Tour(Object? sender, JouerCodeEventArgs e) { Plateau plateauCourant = plateaux[courant!.Value]; plateauCourant.AjouterCode(e.Code); QuandAjouterCode(e.Code); if (++courant == joueurs.Count) courant = 0; QuandPasserMain(); if(courant == 0 && (plateauCourant.Tour > Regles.TourMaximum || plateaux.Where(plateau => plateau.Victoire).Any())) { Terminee(); } else { Joueur joueurCourant = joueurs[courant!.Value]; plateauCourant = plateaux[courant!.Value]; QuandNouveauTour(joueurCourant, plateauCourant.Tour, new Code(Regles.TailleCodeMaximum), plateauCourant.Grille(), plateauCourant.Indicateurs()); } } /// /// La partie est terminée /// private void Terminee() { List gagnants = new List(); List perdants = new List(); for(int i = 0; i < joueurs.Count; i++) { if (plateaux[i].Victoire) gagnants.Add(joueurs[i]); else perdants.Add(joueurs[i]); } QuandPartieTerminee(gagnants, perdants); } } }