using CoreLibrary.Persistance; using CoreLibrary.Core; using CoreLibrary.Evenements; using CoreLibrary.Joueurs; using CoreLibrary.Regles; using System.Runtime.Serialization; namespace CoreLibrary { /// /// Classe représentant une partie. /// [DataContract] [KnownType(typeof(ReglesClassiques))] public class Partie : IEstPersistant { /// /// Evénement déclencher quand il faut ajouter un joueur. /// public event EventHandler? PartieDemanderJoueur; /// /// Evénement déclencher lors du commencement d'une partie. /// public event EventHandler? PartieDebutPartie; /// /// Evénement déclencher quand il s'agit d'un nouveau tour. /// public event EventHandler? PartieNouveauTour; /// /// Evénement déclencher quand on passe la main au joueur suivant. /// public event EventHandler? PartiePasserLaMain; /// /// Evénement déclencher quand la partie est terminée. /// public event EventHandler? PartiePartieTerminee; /// /// Méthode pour déclencher l'événement qui demande le joueur. /// /// . private void QuandPartieDemanderJoueur(Joueur joueurDemande) => PartieDemanderJoueur?.Invoke(this, new PartieDemanderJoueurEventArgs(joueurs.Count + 1, joueurDemande)); /// /// Méthode pour déclencher l'événement de début de partie. /// private void QuandPartieDebutPartie() => PartieDebutPartie?.Invoke(this, new PartieDebutPartieEventArgs()); /// /// Méthode pour déclencher l'événement de nouveau tour. /// private void QuandPartieNouveauTour() => PartieNouveauTour?.Invoke(this, new PartieNouveauTourEventArgs(Tour, joueurs.ElementAt(courant), plateaux.ElementAt(courant), new Code(Regles.TailleCode))); /// /// Méthode pour déclencher l'événement pour passer la main. /// private void QuandPartiePasserLaMain() => PartiePasserLaMain?.Invoke(this, new PartiePasserLaMainEventArgs(joueurs.ElementAt(courant))); /// /// Méthode pour déclencher l'événement si la partie est terminée. /// /// Liste des joueurs gagnants. /// Liste des joueurs perdants. private void QuandPartiePartieTerminee(IReadOnlyList gagnants, IReadOnlyList perdants) => PartiePartieTerminee?.Invoke(this, new PartiePartieTermineeEventArgs(gagnants, perdants)); /// /// Liste des joueurs. /// [DataMember] private readonly List joueurs = new List(); /// /// Liste des plateaux. /// [DataMember] private readonly List plateaux = new List(); /// /// Entier correspondant au joueur courant. /// [DataMember] private int courant = 0; /// /// La liste des joueurs remplit. /// public IReadOnlyList Joueurs => joueurs; /// /// Booléen pour suivre le statut de la partie. /// [DataMember] public bool Termine { get; private set; } = false; /// /// Entier correspondant au nombre de tour. /// [DataMember] public int Tour { get; private set; } = 0; /// /// Regles utiliser dans la partie. /// [DataMember] public IRegles Regles { get; private init; } /// /// Premier constructeur de partie. /// /// Les règles de la partie. public Partie(IRegles regles) { Regles = regles; } /// /// Deuxième constructeur de partie. /// /// La partie à reprendre en cours. public Partie(Partie partie) { joueurs = partie.joueurs; plateaux = partie.plateaux; courant = partie.courant; Tour = partie.Tour; Regles = partie.Regles; partie.PartieDemanderJoueur = null; partie.PartieDebutPartie = null; partie.PartieNouveauTour = null; partie.PartiePasserLaMain = null; partie.PartiePartieTerminee = null; } /// /// Lance le déroulement de la partie. /// public void Jouer() { if (joueurs.Count != Regles.NbJoueurs) DemanderJoueur(); else DebutPartie(); } /// /// Demande un joueur. /// private void DemanderJoueur() { Joueur joueurDemande = new Joueur(); joueurDemande.JoueurSeConnecter += JoueurConnecte; QuandPartieDemanderJoueur(joueurDemande); } /// /// Connecte les joueurs à la partie. /// /// Sender envoie l'événement. /// e est l'événement. private void JoueurConnecte(object? sender, JoueurSeConnecterEventArgs e) { joueurs.Add(e.Nom); plateaux.Add(new Plateau(Regles.TailleCode, Regles.NbTour)); if (joueurs.Count < Regles.NbJoueurs) { DemanderJoueur(); } else { DebutPartie(); } } /// /// Lance le début de la partie. /// private void DebutPartie() { if (Tour == 0) ++Tour; foreach (Plateau plateau in plateaux) { plateau.PlateauAjouterCode += PlateauAjouterCode; } QuandPartieDebutPartie(); NouveauTour(); } /// /// Permet de changer de tour. /// private void NouveauTour() { QuandPartieNouveauTour(); } /// /// Ajoute un code au plateau. /// /// Sender permet d'envoyer l'événement. /// e est l'événement. private void PlateauAjouterCode(object? sender, PlateauAjouterCodeEventArgs e) { QuandPartiePasserLaMain(); if (courant + 1 == joueurs.Count && (e.Plateau.Complet || plateaux.Any(plateau => plateau.Victoire))) { PartieTerminee(); } else { if (courant + 1 == joueurs.Count) { ++Tour; courant = 0; } else ++courant; NouveauTour(); } } /// /// La partie est terminée. /// private void PartieTerminee() { Termine = true; List gagnants = new List(); List perdants = new List(); for (int i = 0; i < joueurs.Count; ++i) { if (plateaux.ElementAt(i).Victoire) gagnants.Add(joueurs[i]); else perdants.Add(joueurs[i]); } QuandPartiePartieTerminee(gagnants, perdants); } } }