diff --git a/Documentation/conception/diagramme_de_classes.md b/Documentation/conception/diagramme_de_classes.md index 5781895..1baeefd 100644 --- a/Documentation/conception/diagramme_de_classes.md +++ b/Documentation/conception/diagramme_de_classes.md @@ -1,5 +1,6 @@ ```plantuml + @startuml enum Couleur { @@ -16,24 +17,27 @@ enum Indicateur { BONNECOULEUR } -class Jeton { +struct Jeton { + --- + --- +Jeton(couleur: Couleur) } Jeton *--> Couleur: +Couleur: Couleur class Code { + --- + +NbJetons: int = 0 + --- +Code(tailleCode: int) - +Code(jetons: Jeton?[]) + +Code(jetons: Jeton[]) +AjouterJeton(jeton: Jeton): void +SupprimerDernierJeton(): void - +RecupererJeton(indice: int): void + +RecupererJeton(indice: int): Jeton +Jetons(): Jeton?[] +EstComplet(): bool +TailleMaximale(): int +Comparer(autreCode: Code): Indicateur[] - - +NbJetons: int = 0 } Code o--> Jeton: -lesJeton: Jeton?[] @@ -41,7 +45,10 @@ Code o--> Jeton: -lesJeton: Jeton?[] class Plateau { -random: Random -tailleCode: int - + --- + +Victoire: bool = false + +Tour: int = 1 + --- +Plateau(tailleCode: int, tailleGrille: int) +GenererCodeAleatoire(): void +EstComplet(): bool @@ -49,9 +56,6 @@ class Plateau { +EstBonCode(code: Code): bool +Grille(): Jeton?[][] +Indicateurs(): Indicateur[][] - - +Victoire: bool = false - +Tour: int = 1 } Plateau *--> Code: -codeSecret: Code @@ -60,16 +64,24 @@ Plateau *--> Indicateur: -indicateurs: Indicateur[][] class Joueur { - +Joueur(nom: string, plateau: Plateau) - + --- +Nom: string + --- + +Joueur(nom: string, plateau: Plateau) } Joueur *--> Plateau: +Plateau: Plateau interface IRegles { - +AjouterJoueur(joueur: string): void + --- + +Nom: string + +TourMaximum: int + +TailleCodeMaximum: int + +NbJoueurs: int + +NbJoueursMaximum: int + --- + +AjouterJoueur(joueur: string): Joueur +JoueurCourant(): Joueur +PasserLaMain(): void +GenererCode(): Code @@ -77,30 +89,60 @@ interface IRegles { +EstTerminee(): bool +Gagnants(): Joueur[] +Perdants(): Joueur[] - - +Nom: string - +TourMaximum: int - +TailleCodeMaximum: int - +NbJoueurs: int - +NbJoueursMaximum: int } class ReglesClassiques { - +nbJoueurs: int = 0 - +joueurCourant: int? - +joueurs: Joueur[] - - +ReglesClassiques() - + -nbJoueurs: int = 0 + -joueurCourant: int? + --- +Nom: string = "Règles classiques" +TourMaximum: int = 12 +TailleCodeMaximum: int = 4 +NbJoueurs: int +NbJoueursMaximum: int = 2 + --- + +ReglesClassiques() +} + +IRegles <|.. ReglesClassiques + +ReglesClassiques *--> Joueur: -joueurs: Joueur[] + + + +class Partie { + --- + +StringEventHandler(sender: Object?, e: TEventArgs): string? + +JetonEventHandler(sender: Object?, e: TEventArgs): Jeton + --- + +DemanderJoueur: StringEventHandler? + +DemanderJeton: JetonEventHandler? + +AjouterJoueur: EventHandler? + +DebutPartie: EventHandler? + +NouveauTour: EventHandler? + +NouveauJeton: EventHandler? + +NouveauCode: EventHandler? + +PasserMain: EventHandler? + +PartieTerminee: EventHandler? + --- + -QuandDemanderJoueur(int numero): string? + -QuandDemanderJeton(): Jeton? + -QuandAjouterJoueur(Joueur joueur): void + -QuandDebutPartie(): void + -QuandNouveauTour(Joueur joueur, int tour, Jeton?[][] grille, Indicateur[][] indicateurs): void + -QuandNouveauJeton(Jeton jeton): void + -QuandNouveauCode(Code: code): void + -QuandPasserMain(): void + -QuandPartieTerminee(Joueur[] gagnants, Joueur[] perdants): void + +Partie(IRegles regles) + +Jouer(): void } -ReglesClassiques ..|> IRegles + +Partie *--> IRegles: -regles: IRegles + + @enduml diff --git a/Documentation/conception/diagramme_de_paquetage.md b/Documentation/conception/diagramme_de_paquetage.md new file mode 100644 index 0000000..6c8f459 --- /dev/null +++ b/Documentation/conception/diagramme_de_paquetage.md @@ -0,0 +1,64 @@ +```plantuml + +@startuml + +package CoreLibrary <> { + package Core <> { + class Code + class Plateau + struct Jeton + enum Couleur + enum Indicateur + } + + package Joueurs <> { + class Joueur + } + + + package Regles <> { + interface IRegles + class ReglesClassiques + } + + package Evenements <> { + class AjouterCodeEventArgs + class AjouterJetonEventArgs + class AjouterJoueurEventArgs + class DebutPartieEventArgs + class DemanderJetonEventArgs + class DemanderJoueurEventArgs + class NouveauTourEventArgs + class PartieTermineeEventArgs + class PasserMainEventArgs + } + + package Exceptions <> { + class CodeCompletException + class CodeIncompletException + class CodeInvalideException + class CodeVideException + class GrilleCompleteException + class IndiceCodeException + class PartieNonCommenceeException + class TailleCodeException + class TailleGrilleException + } + + class Partie +} + +package ConsoleApp <> { + class Program + class Utils +} + +package System <> { + class Exception + class EventArgs + class Random +} + +@enduml + +``` \ No newline at end of file diff --git a/README.md b/README.md index 24b55f2..a953b79 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,31 @@ -# mastermind +[![Drone](https://codefirst.iut.uca.fr/api/badges/nicolas.barbosa/mastermind/status.svg)](https://codefirst.iut.uca.fr/nicolas.barbosa/mastermind) -SAE2.01 - Développement d'une application -R2.02 - Développement d'applications avec IHM -R2.03 - Qualité de développement +[![Sonar](https://codefirst.iut.uca.fr/sonar/api/project_badges/measure?project=celestebarbosa-mastermind&metric=alert_status&token=849a6b4d77bc19046c81e8fc8f6be8ec0b8c5f3a)](https://codefirst.iut.uca.fr/sonar/dashboard?id=celestebarbosa-mastermind) -Mastermind en C#, MAUI, et .net +[![Bugs](https://codefirst.iut.uca.fr/sonar/api/project_badges/measure?project=celestebarbosa-mastermind&metric=bugs&token=849a6b4d77bc19046c81e8fc8f6be8ec0b8c5f3a)](https://codefirst.iut.uca.fr/sonar/dashboard?id=celestebarbosa-mastermind) +[![Fiabilité](https://codefirst.iut.uca.fr/sonar/api/project_badges/measure?project=celestebarbosa-mastermind&metric=reliability_rating&token=849a6b4d77bc19046c81e8fc8f6be8ec0b8c5f3a)](https://codefirst.iut.uca.fr/sonar/dashboard?id=celestebarbosa-mastermind) -BARBOSA Céleste -PRADY Pauline -TURPIN-ETIENNE Camille +[![Vulnérabilités](https://codefirst.iut.uca.fr/sonar/api/project_badges/measure?project=celestebarbosa-mastermind&metric=vulnerabilities&token=849a6b4d77bc19046c81e8fc8f6be8ec0b8c5f3a)](https://codefirst.iut.uca.fr/sonar/dashboard?id=celestebarbosa-mastermind) +[![Securité](https://codefirst.iut.uca.fr/sonar/api/project_badges/measure?project=celestebarbosa-mastermind&metric=security_rating&token=849a6b4d77bc19046c81e8fc8f6be8ec0b8c5f3a)](https://codefirst.iut.uca.fr/sonar/dashboard?id=celestebarbosa-mastermind) + +[![Risques](https://codefirst.iut.uca.fr/sonar/api/project_badges/measure?project=celestebarbosa-mastermind&metric=security_hotspots&token=849a6b4d77bc19046c81e8fc8f6be8ec0b8c5f3a)](https://codefirst.iut.uca.fr/sonar/dashboard?id=celestebarbosa-mastermind) + +[![Dette technique](https://codefirst.iut.uca.fr/sonar/api/project_badges/measure?project=celestebarbosa-mastermind&metric=sqale_index&token=849a6b4d77bc19046c81e8fc8f6be8ec0b8c5f3a)](https://codefirst.iut.uca.fr/sonar/dashboard?id=celestebarbosa-mastermind) +[![Code Smells](https://codefirst.iut.uca.fr/sonar/api/project_badges/measure?project=celestebarbosa-mastermind&metric=code_smells&token=849a6b4d77bc19046c81e8fc8f6be8ec0b8c5f3a)](https://codefirst.iut.uca.fr/sonar/dashboard?id=celestebarbosa-mastermind) +[![Maintenabilité](https://codefirst.iut.uca.fr/sonar/api/project_badges/measure?project=celestebarbosa-mastermind&metric=sqale_rating&token=849a6b4d77bc19046c81e8fc8f6be8ec0b8c5f3a)](https://codefirst.iut.uca.fr/sonar/dashboard?id=celestebarbosa-mastermind) + +[![Tests](https://codefirst.iut.uca.fr/sonar/api/project_badges/measure?project=celestebarbosa-mastermind&metric=coverage&token=849a6b4d77bc19046c81e8fc8f6be8ec0b8c5f3a)](https://codefirst.iut.uca.fr/sonar/dashboard?id=celestebarbosa-mastermind) +[![Lignes dupliquées (%)](https://codefirst.iut.uca.fr/sonar/api/project_badges/measure?project=celestebarbosa-mastermind&metric=duplicated_lines_density&token=849a6b4d77bc19046c81e8fc8f6be8ec0b8c5f3a)](https://codefirst.iut.uca.fr/sonar/dashboard?id=celestebarbosa-mastermind) +[![Nombre de lignes](https://codefirst.iut.uca.fr/sonar/api/project_badges/measure?project=celestebarbosa-mastermind&metric=ncloc&token=849a6b4d77bc19046c81e8fc8f6be8ec0b8c5f3a)](https://codefirst.iut.uca.fr/sonar/dashboard?id=celestebarbosa-mastermind) + +--- + +# Mastermind - Projet IHM + +**Céleste BARBOSA**\ +**Pauline PRADY**\ +**Camille TURPIN-ETIENNE**\ + +--- + +## Réalisation d'un jeu vidéo en .NET, C# & MAUI diff --git a/Sources/ConsoleApp/Evenements.cs b/Sources/ConsoleApp/Evenements.cs new file mode 100644 index 0000000..33f9151 --- /dev/null +++ b/Sources/ConsoleApp/Evenements.cs @@ -0,0 +1,147 @@ +using CoreLibrary.Events; +using CoreLibrary; + +namespace ConsoleApp +{ + /// + /// Fournit des gestionnaires d'événements pour les événements liés au déroulement de la partie. + /// + public static class Evenements + { + /// + /// Gestionnaire d'événement pour l'ajout d'un joueur. + /// + public static string? DemanderJoueur(Object? sender, DemanderJoueurEventArgs e) + { + Console.WriteLine($"Joueur {e.Numero}"); + Console.Write(">>> "); + + string? nom = Console.ReadLine(); + + Console.WriteLine(); + + return nom; + } + + + /// + /// Gestionnaire d'événement pour le début de la partie. + /// + public static void CommencerLaPartie(Object? sender, DebutPartieEventArgs e) + { + Utils.DessinerSeparateur(); + + Console.WriteLine("La partie commence, bonne chance à tous !\n"); + } + + /// + /// Gestionnaire d'événement pour le début d'un nouveau tour. + /// + public static void NouveauTour(Object? sender, NouveauTourEventArgs e) + { + Utils.DessinerSeparateur(); + + Console.WriteLine($"Tour {e.Tour} - {e.Joueur.Nom}\n"); + + Utils.DessinerPlateau(e.Grille, e.Indicateurs); + + Console.WriteLine(); + + } + + /// + /// Gestionnaire d'événement pour la demande d'ajout d'un jeton. + /// + public static Jeton? DemanderJeton(Object? sender, DemanderJetonEventArgs e) + { + Console.TreatControlCAsInput = true; + + bool aChoisi = false; + int indice = 0; + Couleur[] couleurs = (Couleur[])Enum.GetValues(typeof(Couleur)); + + while (!aChoisi) + { + Utils.DessinerPion(couleurs[indice]); + Console.Write("\b\b\b"); + + switch (Console.ReadKey(true).Key) + { + case ConsoleKey.Enter: + aChoisi = true; + break; + + case ConsoleKey.LeftArrow: + --indice; + break; + + case ConsoleKey.RightArrow: + ++indice; + break; + + case ConsoleKey.Escape: + return null; + + default: + break; + } + + if (indice < 0) + indice = couleurs.Length - 1; + else if (indice >= couleurs.Length) + indice = 0; + } + + Console.TreatControlCAsInput = false; + + return new Jeton(couleurs[indice]); + } + + /// + /// Gestionnaire d'événement pour l'ajout d'un jeton. + /// + public static void AjouterJeton(Object? sender, AjouterJetonEventArgs e) + { + Utils.DessinerPion(e.Jeton.Couleur); + } + + /// + /// Gestionnaire d'événement pour la suppression du dernier jeton ajouté. + /// + public static void SupprimerDernierJeton(Object? sender, SupprimerDernierJetonEventArgs e) + { + Console.Write("\b\b\b \b\b\b\b\b\b"); + } + + /// + /// Gestionnaire d'événement pour l'ajout d'un code. + /// + public static void AjouterCode(Object? sender, AjouterCodeEventArgs e) + { + Console.WriteLine(); + + Utils.DessinerSeparateur(); + } + + /// + /// Gestionnaire d'événement pour la fin de la partie. + /// + public static void PartieTerminee(Object? sender, PartieTermineeEventArgs e) + { + Joueur[] gagnants = e.Gagnants.ToArray(); + + if (gagnants.Length > 1) + { + Console.WriteLine("C'est une égalité !"); + } + else if (gagnants.Length == 1) + { + Console.WriteLine($"C'est une victoire de {gagnants[0].Nom}."); + } + else + { + Console.WriteLine("C'est une défaite des deux joueurs..."); + } + } + } +} diff --git a/Sources/ConsoleApp/Program.cs b/Sources/ConsoleApp/Program.cs index 475a617..0523887 100644 --- a/Sources/ConsoleApp/Program.cs +++ b/Sources/ConsoleApp/Program.cs @@ -1,88 +1,20 @@ -using CoreLibrary; using ConsoleApp; - +using CoreLibrary; Console.OutputEncoding = System.Text.Encoding.UTF8; -ReglesClassiques partie = new ReglesClassiques(); - -Utils.AfficherTitre(); - -Utils.AfficherTitre("Joueurs"); - -string joueur1; -string joueur2; - -while (true) -{ - try - { - joueur1 = Utils.SaisirNom(); - break; - } - catch(UtilsNomJoueurNullException) - { - Console.WriteLine("Nom invalide pour le joueur ! Ressaisir le nom"); - } -} - -while (true) -{ - try - { - joueur2 = Utils.SaisirNom(); - break; - } - catch (UtilsNomJoueurNullException) - { - Console.WriteLine("Nom invalide pour le joueur 2 ! Ressaisir le nom"); - } -} - -Utils.AfficherSeparateur(); - -partie.AjouterJoueur(joueur1); -partie.AjouterJoueur(joueur2); - -partie.CommencerLaPartie(); - -while (!partie.EstTerminee()) -{ - Console.WriteLine(partie.JoueurCourant().Nom); - Console.WriteLine(); - - Utils.DessinerPlateau(partie.JoueurCourant().Plateau.Grille(), partie.JoueurCourant().Plateau.Indicateurs()); - Console.WriteLine(); - - Code code = partie.GenererCode(); - - Utils.ChoixCode(ref code); - - partie.JoueurCourant().Plateau.AjouterCode(code); - - partie.PasserLaMain(); - - Utils.AfficherSeparateur(); -} - -Console.WriteLine("La partie est maintenant terminée !"); - -Joueur[] gagnants = partie.Gagnants().ToArray(); -Joueur[] perdants = partie.Perdants().ToArray(); +Utils.DessinerTitre(); +Partie maPartie = new Partie(new ReglesClassiques()); +maPartie.DemanderJoueur += Evenements.DemanderJoueur; +maPartie.DebutPartie += Evenements.CommencerLaPartie; +maPartie.NouveauTour += Evenements.NouveauTour; +maPartie.DemanderJeton += Evenements.DemanderJeton; +maPartie.AjouterJeton += Evenements.AjouterJeton; +maPartie.SupprimerDernierJeton += Evenements.SupprimerDernierJeton; +maPartie.AjouterCode += Evenements.AjouterCode; +maPartie.PartieTerminee += Evenements.PartieTerminee; -if (gagnants.Length > 1) -{ - Console.WriteLine("C'est une égalité !"); -} -else if (gagnants.Length == 1) -{ - Console.WriteLine($"C'est une victoire de {gagnants[0].Nom}." + - $""); -} -else -{ - Console.WriteLine("C'est une défaite..."); -} +maPartie.Jouer(); diff --git a/Sources/ConsoleApp/Utils.cs b/Sources/ConsoleApp/Utils.cs index 76b1885..f768e8b 100644 --- a/Sources/ConsoleApp/Utils.cs +++ b/Sources/ConsoleApp/Utils.cs @@ -1,239 +1,135 @@ -using CoreLibrary; - -namespace ConsoleApp -{ - internal class Utils - { - private static int nombreJoueurs = 0; - - private readonly static int longueurTitre = 55; - - private readonly static Dictionary convertirCouleurs = new Dictionary() - { - {Couleur.NOIR, ConsoleColor.Black }, - {Couleur.BLANC, ConsoleColor.White }, - {Couleur.ROUGE, ConsoleColor.Red }, - {Couleur.VERT, ConsoleColor.Green }, - {Couleur.BLEU, ConsoleColor.Blue }, - {Couleur.JAUNE, ConsoleColor.Yellow } - }; - private readonly static Dictionary convertirIndicateurs = new Dictionary() - { - {Indicateur.BONNEPLACE, ConsoleColor.Black }, - {Indicateur.BONNECOULEUR, ConsoleColor.White } - }; - - public static void AfficherTitre() - { - - Console.WriteLine(""" - __ __ _ _ _ - | \/ | __ _ ___| |_ ___ _ _ _ __ (_) _ _ __| | - | |\/| |/ _` |(_-<| _|/ -_)| '_|| ' \ | || ' \ / _` | - |_| |_|\__,_|/__/ \__|\___||_| |_|_|_||_||_||_|\__,_| - """); - - AfficherSeparateur(); - } - - public static void AfficherTitre(string titre) - { - int taille = longueurTitre - titre.Length; - int gauche = taille > 0 ? taille / 2 : 0; - - Console.Write(titre.PadLeft(titre.Length + gauche)); - AfficherSeparateur(); - } - - public static void AfficherSeparateur() - { - Console.WriteLine(""" - - _______________________________________________________ - - - """); - } - - public static string SaisirNom() - { - string nom = $"Joueur {++nombreJoueurs}"; - - Console.WriteLine(nom); - Console.Write(">>> "); - nom = Console.ReadLine() ?? nom; - if (nom == "") - { - --nombreJoueurs; - throw new UtilsNomJoueurNullException(); - } - Console.WriteLine(); - - return nom; - } - - public static void DessinerJeton(Jeton jeton) - { - Console.Write(" "); - - Console.ForegroundColor = convertirCouleurs.GetValueOrDefault(jeton.Couleur); - Console.BackgroundColor = Console.ForegroundColor.Equals(ConsoleColor.Black) ? ConsoleColor.White : ConsoleColor.Black; - - Console.Write("⬤"); - - Console.ResetColor(); - - Console.Write(" "); - } - - public static void DessinerIndicateur(Indicateur indicateur) - { - Console.Write(" "); - - Console.ForegroundColor = convertirIndicateurs.GetValueOrDefault(indicateur); - Console.BackgroundColor = Console.ForegroundColor.Equals(ConsoleColor.Black) ? ConsoleColor.White : ConsoleColor.Black; - - Console.Write("⬤"); - - Console.ResetColor(); - - Console.Write(" "); - } - - public static void DessinerCode(IEnumerable jetons) - { - foreach (Jeton? jeton in jetons) - { - if (jeton.HasValue) - { - DessinerJeton(jeton.Value); - } - else - { - Console.Write(" "); - } - } - } - - - public static void DessinerIndicateurs(IEnumerable indicateurs) - { - if (indicateurs == null) - { - indicateurs = []; - } - - foreach (Indicateur indicateur in indicateurs) - { - DessinerIndicateur(indicateur); - } - - if (indicateurs.Count() < 4) - Console.Write("".PadLeft((4 - indicateurs.Count()) * 3)); - } - - public static void DessinerPlateau(IEnumerable> grille, IEnumerable> indicateurs) - { - IEnumerable[] grilleT = grille.ToArray(); - IEnumerable[] indicateursT = indicateurs.ToArray(); - - - Console.WriteLine(" Codes Indicateurs "); - Console.WriteLine("──────────────── ────────────────"); - Console.WriteLine("│ │ │ │"); - - for (int i = 0; i < grilleT.Length; ++i) - { - Console.Write("│ "); - DessinerCode(grilleT[i]); - Console.Write(" │"); - - Console.Write(" "); - - Console.Write("│ "); - DessinerIndicateurs(indicateursT[i]); - Console.WriteLine(" │"); - } - - Console.WriteLine("│ │ │ │"); - Console.WriteLine("──────────────── ────────────────"); - } - - - public static Jeton? ChoixJeton() - { - Console.TreatControlCAsInput = true; - - bool aChoisi = false; - int indice = 0; - Couleur[] couleurs = (Couleur[])Enum.GetValues(typeof(Couleur)); - Couleur couleur = couleurs[indice]; - - while (!aChoisi) - { - DessinerJeton(new Jeton(couleur)); - Console.Write("\b\b\b"); - - ConsoleKey touche = Console.ReadKey(true).Key; - - switch (touche) - { - case ConsoleKey.Enter: - aChoisi = true; - break; - - case ConsoleKey.LeftArrow: - --indice; - break; - - case ConsoleKey.RightArrow: - ++indice; - break; - - case ConsoleKey.Escape: - return null; - - default: - break; - } - - if (indice < 0) - indice = couleurs.Length - 1; - else if (indice >= couleurs.Length) - indice = 0; - - couleur = couleurs[indice]; - } - - Console.TreatControlCAsInput = false; - return new Jeton(couleur); - } - - public static void ChoixCode(ref Code code) - { - while (!code.EstComplet()) - { - Jeton? jeton = ChoixJeton(); - - if (jeton.HasValue) - { - DessinerJeton(jeton.Value); - code.AjouterJeton(jeton.Value); - } - else - { - Console.Write("\b\b\b \b\b\b\b\b\b\b\b\b\b\b\b"); - try - { - code.SupprimerDernierJeton(); - } - catch(CodeTableauLesJetonsVideException) - { - Console.WriteLine("Il n'y a pas de jetons! Impossible de supprimer"); - } - - } - } - } - } -} +using CoreLibrary; + +namespace ConsoleApp +{ + /// + /// Classe utilitaire contenant des méthodes pour dessiner des éléments dans la console. + /// + public static class Utils + { + // Dictionnaires associant les valeurs des énumérations avec les couleurs de la console + private readonly static Dictionary couleursTerminal = new Dictionary() + { + {Couleur.NOIR, ConsoleColor.Black }, + {Couleur.BLANC, ConsoleColor.White }, + {Couleur.ROUGE, ConsoleColor.Red }, + {Couleur.VERT, ConsoleColor.Green }, + {Couleur.BLEU, ConsoleColor.Blue }, + {Couleur.JAUNE, ConsoleColor.DarkYellow } + }; + + private readonly static Dictionary indicateursTerminal = new Dictionary() + { + {Indicateur.BONNEPLACE, ConsoleColor.Black }, + {Indicateur.BONNECOULEUR, ConsoleColor.White } + }; + + /// + /// Dessine le titre du jeu dans la console. + /// + public static void DessinerTitre() + { + Console.WriteLine(@" + __ __ _ _ _ +| \/ | __ _ ___| |_ ___ _ _ _ __ (_) _ _ __| | +| |\/| |/ _` |(_-<| _|/ -_)| '_|| ' \ | || ' \ / _` | +|_| |_|\__,_|/__/ \__|\___||_| |_|_|_||_||_||_|\__,_| +"); + DessinerSeparateur(); + } + + /// + /// Dessine un séparateur dans la console. + /// + public static void DessinerSeparateur() + { + Console.WriteLine(@" + +─────────────────────────────────────────────────────── + + + "); + } + + /// + /// Dessine un pion dans la console. + /// + /// Le pion à dessiner (une couleur ou un indicateur). + public static void DessinerPion(Enum pion) + { + Console.Write(" "); + + // Sélectionne la couleur appropriée en fonction du type de pion (une couleur ou un indicateur) + Console.ForegroundColor = pion.GetType().Equals(typeof(Couleur)) ? + couleursTerminal.GetValueOrDefault((Couleur)pion) : + indicateursTerminal.GetValueOrDefault((Indicateur)pion); + + // Définit la couleur de fond en fonction de la couleur de premier plan + Console.BackgroundColor = Console.ForegroundColor.Equals(ConsoleColor.Black) ? ConsoleColor.White : ConsoleColor.Black; + + Console.Write("⬤"); + + Console.ResetColor(); + + Console.Write(" "); + } + + /// + /// Dessine une ligne de pions sur la console. + /// + /// Un tableau d'énumérations représentant les pions à dessiner. + private static void DessinerLigne(Enum[] ligne) + { + foreach(Enum pion in ligne) + DessinerPion(pion); + + Console.Write("".PadLeft((4 - ligne.Length) * 3)); + } + + /// + /// Dessine un plateau de jeu dans la console, affichant les jetons et les indicateurs. + /// + /// La grille de jeu. + /// Les indicateurs associés à chaque ligne. + public static void DessinerPlateau(IEnumerable> grille, IEnumerable> indicateurs) + { + IEnumerable[] grilleTableau = grille.ToArray(); + IEnumerable[] indicateursTableau = indicateurs.ToArray(); + + Console.WriteLine(" Codes Indicateurs "); + Console.WriteLine("──────────────── ────────────────"); + Console.WriteLine("│ │ │ │"); + + for (int i = 0; i < grille.Count(); ++i) + { + Console.Write("│ "); + + DessinerLigne( + grilleTableau[i] + .Where(jeton => jeton.HasValue) + .Select(jeton => (Enum)jeton!.Value.Couleur) + .ToArray() + ); + + Console.Write(" │ │ "); + + if (indicateursTableau[i] == null) + { + indicateursTableau[i] = []; + } + + DessinerLigne( + indicateursTableau[i] + .Select(indicateur => (Enum)indicateur) + .ToArray() + ); + + Console.WriteLine(" │"); + } + + + Console.WriteLine("│ │ │ │"); + Console.WriteLine("──────────────── ────────────────"); + } + } +} diff --git a/Sources/ConsoleApp/UtilsNomJoueurNullException.cs b/Sources/ConsoleApp/UtilsNomJoueurNullException.cs deleted file mode 100644 index 20187e7..0000000 --- a/Sources/ConsoleApp/UtilsNomJoueurNullException.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace ConsoleApp -{ - public class UtilsNomJoueurNullException : Exception - { - public UtilsNomJoueurNullException() : base("Le nom du joueur est null") - { } - } -} diff --git a/Sources/CoreLibrary/Code.cs b/Sources/CoreLibrary/Code.cs index e0bd61c..053303a 100644 --- a/Sources/CoreLibrary/Code.cs +++ b/Sources/CoreLibrary/Code.cs @@ -1,86 +1,153 @@ -namespace CoreLibrary +using CoreLibrary.Exceptions; + +namespace CoreLibrary { + /// + /// Représente un code composé de jetons. + /// public class Code { private readonly Jeton?[] lesJetons; + /// + /// Obtenir le nombre de jetons dans le code. + /// public int NbJetons { get; private set; } = 0; + /// + /// Initialise une nouvelle instance de la classe avec la longueur de code spécifiée. + /// + /// La longueur du code. + /// Levée lorsque la longueur du code spécifiée est inférieure ou égale à zéro. public Code(int tailleCode) - { - if (tailleCode <= 0) - throw new CodeTailleInvalideException(); + { + if(tailleCode <= 0) + { + throw new TailleCodeException(tailleCode); + } + lesJetons = new Jeton?[tailleCode]; } + /// + /// Initialise une nouvelle instance de la class avec les jetons spécifiés. + /// + /// Les jetons pour initaliser le code. + /// Levée lorsque la collection de jetons spécifiée est vide. public Code(IEnumerable jetons) { - if (!jetons.Any()) - throw new CodeTailleInvalideException(); - + if (jetons.Any()) + { + throw new TailleCodeException(jetons.Count()); + } + lesJetons = new Jeton?[jetons.Count()]; foreach(Jeton jeton in jetons) + { AjouterJeton(jeton); + } } + /// + /// Ajoute un jeton au code. + /// + /// Le jeton à ajouter + /// Levée lorsque le code est plein. public void AjouterJeton(Jeton jeton) - { - if (EstComplet()) - throw new CodeTableauLesJetonsCompletException(); - + { + if (NbJetons == TailleMaximale()) + { + throw new CodeCompletException(); + } + lesJetons[NbJetons++] = jeton; } + /// + /// Supprime le dernier jeton ajouté au code. + /// + /// Levée lorsque le code est vide. public void SupprimerDernierJeton() { - if(NbJetons <= 0) - throw new CodeTableauLesJetonsVideException(); - - + if(NbJetons == 0) + { + throw new CodeVideException(); + } + lesJetons[--NbJetons] = null; - } + /// + /// Récupère le jeton à l'indice spécifié dans le code. + /// + /// L'indice du jeton a récupéré. + /// Le jeton situé à l'indice spécifié. + /// Levée lorsque l'indice est supérieur à la taille maximale du code, inférieur à 0 ou qu'il n'y a pas de jeton à l'indice spécifié public Jeton RecupererJeton(int indice) { if(indice < 0 || indice > TailleMaximale()) - throw new CodeIndiceHorsDePorteeException(); + throw new IndiceCodeException(indice, NbJetons-1); Jeton? jeton = lesJetons[indice]; if (!jeton.HasValue) - throw new CodeJetonNullException(); - + throw new IndiceCodeException(indice, NbJetons-1); + return jeton.Value; } + /// + /// Récupère une énumération des jetons dans le code. + /// + /// Enumération des jetons du code public IEnumerable Jetons() { return lesJetons; } + + /// + /// Vérifie si le code est complet. + /// + /// True si le code est complet, sinon False. public bool EstComplet() { return NbJetons == lesJetons.Length; } + /// + /// Recupère la taille maximal du code. + /// + /// Taille maximal du code. + public int TailleMaximale() { return lesJetons.Length; } + /// + /// Compare le code avec un autre code et génère des indcateurs de correspondance. + /// + /// Le code à comparer avec le code actuel + /// Enumération d'indicateurs de correspondance entre les deux codes. public IEnumerable Comparer(Code autreCode) { // Mon code est le code correct, l'autre code est celui qui teste - if (!autreCode.EstComplet()) - throw new CodeTableauLesJetonsIncompletException(); Indicateur[] indicateurs = []; - Jeton?[] mesJetons = Jetons().ToArray(); - Jeton?[] sesJetons = autreCode.Jetons().ToArray(); + /// Vérifie si les deux codes sont complets + if (!EstComplet() || !autreCode.EstComplet()) + return indicateurs; + + List mesJetons = new List(Jetons()); + List sesJetons = new List(autreCode.Jetons()); + - for (int i = 0; i < mesJetons.Length; ++i) + /// Compare les jetons pour détecter les ceux à la bonnes places + /// S'ils sont à la bonne place alors ils sont enlever du tableau et un indicateur BONNEPLACE est ajouter au tableau des indicateurs. + + for (int i = 0; i < mesJetons.Count; ++i) { Jeton? monJeton = mesJetons[i]; Jeton? sonJeton = sesJetons[i]; @@ -93,26 +160,19 @@ } } + /// Compare les jetons pour détecter ceux qui ont la bonne couleur. + /// S'ils ont la bonne couleur alors ils sont enlever du tableau et un indicateur BONNECOULEUR est ajouter au tableau des indicateurs. - for (int i = 0; i < sesJetons.Length; ++i) + for (int i = 0; i < sesJetons.Count; ++i) { Jeton? sonJeton = sesJetons[i]; - - if (sonJeton.HasValue) + + if (sonJeton.HasValue && mesJetons.Contains(sonJeton.Value)) { - for (int j = 0; j < mesJetons.Length; ++j) - { - Jeton? monJeton = mesJetons[j]; - - if (monJeton.HasValue && sonJeton.Value.Couleur.Equals(monJeton.Value.Couleur)) - { - indicateurs = indicateurs.Append(Indicateur.BONNECOULEUR).ToArray(); - mesJetons[j] = null; - sesJetons[i] = null; - break; - } - - } + indicateurs = indicateurs.Append(Indicateur.BONNECOULEUR).ToArray(); + mesJetons[mesJetons.IndexOf(sonJeton.Value)] = null; + sesJetons[i] = null; + break; } } diff --git a/Sources/CoreLibrary/CodeIndiceHorsDePorteeException.cs b/Sources/CoreLibrary/CodeIndiceHorsDePorteeException.cs deleted file mode 100644 index 36c0929..0000000 --- a/Sources/CoreLibrary/CodeIndiceHorsDePorteeException.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CoreLibrary -{ - public class CodeIndiceHorsDePorteeException : Exception - { - public CodeIndiceHorsDePorteeException() : base("L'indice pointe en dehors du tableau") - { } - } -} diff --git a/Sources/CoreLibrary/CodeJetonNullException.cs b/Sources/CoreLibrary/CodeJetonNullException.cs deleted file mode 100644 index 41297ab..0000000 --- a/Sources/CoreLibrary/CodeJetonNullException.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CoreLibrary -{ - public class CodeJetonNullException : Exception - { - public CodeJetonNullException() : base("le jeton est null") - { } - } -} diff --git a/Sources/CoreLibrary/CodeTableauLesJetonsCompletException.cs b/Sources/CoreLibrary/CodeTableauLesJetonsCompletException.cs deleted file mode 100644 index dfc3d44..0000000 --- a/Sources/CoreLibrary/CodeTableauLesJetonsCompletException.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CoreLibrary -{ - public class CodeTableauLesJetonsCompletException : Exception - { - public CodeTableauLesJetonsCompletException() : base("Le tableau des jetons est plein") - { } - - } -} diff --git a/Sources/CoreLibrary/CodeTableauLesJetonsIncompletException.cs b/Sources/CoreLibrary/CodeTableauLesJetonsIncompletException.cs deleted file mode 100644 index 2205f9c..0000000 --- a/Sources/CoreLibrary/CodeTableauLesJetonsIncompletException.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CoreLibrary -{ - public class CodeTableauLesJetonsIncompletException : Exception - { - public CodeTableauLesJetonsIncompletException() : base("Le tableau des jetons est incomplet") - { } - } -} diff --git a/Sources/CoreLibrary/CodeTableauLesJetonsVideException.cs b/Sources/CoreLibrary/CodeTableauLesJetonsVideException.cs deleted file mode 100644 index d9300f8..0000000 --- a/Sources/CoreLibrary/CodeTableauLesJetonsVideException.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CoreLibrary -{ - public class CodeTableauLesJetonsVideException : Exception - { - public CodeTableauLesJetonsVideException() : base("Le tableau des jetons est vide") - { } - } -} diff --git a/Sources/CoreLibrary/Couleur.cs b/Sources/CoreLibrary/Couleur.cs index 214cd87..ce25820 100644 --- a/Sources/CoreLibrary/Couleur.cs +++ b/Sources/CoreLibrary/Couleur.cs @@ -1,5 +1,8 @@ namespace CoreLibrary { + /// + /// Représente les couleurs disponible pour les jetons. + /// public enum Couleur { ROUGE, diff --git a/Sources/CoreLibrary/Events/AjouterCodeEventArgs.cs b/Sources/CoreLibrary/Events/AjouterCodeEventArgs.cs new file mode 100644 index 0000000..489fded --- /dev/null +++ b/Sources/CoreLibrary/Events/AjouterCodeEventArgs.cs @@ -0,0 +1,23 @@ + +namespace CoreLibrary.Events +{ + /// + /// Représente les arguments d'événement pour l'événement de l'ajout d'un code. + /// + public class AjouterCodeEventArgs : EventArgs + { + /// + /// Obtient le code ajouté. + /// + public Code Code { get; private set; } + + /// + /// Initialise une nouvelle instance de la classe avec le code spécifié. + /// + /// Le code à ajouter. + public AjouterCodeEventArgs(Code code) + { + Code = code; + } + } +} diff --git a/Sources/CoreLibrary/Events/AjouterJetonEventArgs.cs b/Sources/CoreLibrary/Events/AjouterJetonEventArgs.cs new file mode 100644 index 0000000..a19fcbf --- /dev/null +++ b/Sources/CoreLibrary/Events/AjouterJetonEventArgs.cs @@ -0,0 +1,24 @@ + + +namespace CoreLibrary.Events +{ + /// + /// Représente les arguments d'événement pour l'événement d'ajout d'un jeton. + /// + public class AjouterJetonEventArgs : EventArgs + { + /// + /// Obtient le jeton ajouté. + /// + public Jeton Jeton { get; private set; } + + /// + /// Initialise une nouvelle instance de la classe avec le jeton spécifié. + /// + /// Le jeton à ajouter. + public AjouterJetonEventArgs(Jeton jeton) + { + Jeton = jeton; + } + } +} diff --git a/Sources/CoreLibrary/Events/AjouterJoueursEventArgs.cs b/Sources/CoreLibrary/Events/AjouterJoueursEventArgs.cs new file mode 100644 index 0000000..0e04345 --- /dev/null +++ b/Sources/CoreLibrary/Events/AjouterJoueursEventArgs.cs @@ -0,0 +1,22 @@ +namespace CoreLibrary.Events +{ + /// + /// Représente les arguments d'événement pour l'événement d'ajout d'un joueur. + /// + public class AjouterJoueursEventArgs : EventArgs + { + /// + /// Obtient le joueur ajouté. + /// + public Joueur Joueur { get; private set; } + + /// + /// Initialise une nouvelle instance de la classe avec le joueur spécifié. + /// + /// Le joueur à ajouter. + public AjouterJoueursEventArgs(Joueur joueur) + { + Joueur = joueur; + } + } +} diff --git a/Sources/CoreLibrary/Events/DebutPartieEventArgs.cs b/Sources/CoreLibrary/Events/DebutPartieEventArgs.cs new file mode 100644 index 0000000..631c7ca --- /dev/null +++ b/Sources/CoreLibrary/Events/DebutPartieEventArgs.cs @@ -0,0 +1,9 @@ +namespace CoreLibrary.Events +{ + /// + /// Représente les arguments d'événement pour le début d'une partie. + /// + public class DebutPartieEventArgs : EventArgs + { + } +} diff --git a/Sources/CoreLibrary/Events/DemanderJetonEventArgs.cs b/Sources/CoreLibrary/Events/DemanderJetonEventArgs.cs new file mode 100644 index 0000000..41c2059 --- /dev/null +++ b/Sources/CoreLibrary/Events/DemanderJetonEventArgs.cs @@ -0,0 +1,10 @@ + +namespace CoreLibrary.Events +{ + /// + /// Représente les arguments d'événement pour la demande d'ajout d'un jeton. + /// + public class DemanderJetonEventArgs : EventArgs + { + } +} diff --git a/Sources/CoreLibrary/Events/DemanderJoueurEventArgs.cs b/Sources/CoreLibrary/Events/DemanderJoueurEventArgs.cs new file mode 100644 index 0000000..42ed8c2 --- /dev/null +++ b/Sources/CoreLibrary/Events/DemanderJoueurEventArgs.cs @@ -0,0 +1,23 @@ +namespace CoreLibrary.Events +{ + /// + /// Représente les arguments d'événement pour la demande d'ajout d'un joueur. + /// + public class DemanderJoueurEventArgs : EventArgs + { + /// + /// Obtient le numéro du joueur à ajouter. + /// + public int Numero { get; private set; } + + + /// + /// Initialise une nouvelle instance de la classe avec le numéro du joueur spécifié. + /// + /// Le numéro du joueur à ajouter. + public DemanderJoueurEventArgs(int numero) + { + Numero = numero; + } + } +} diff --git a/Sources/CoreLibrary/Events/NouveauTourEventArgs.cs b/Sources/CoreLibrary/Events/NouveauTourEventArgs.cs new file mode 100644 index 0000000..cc577b1 --- /dev/null +++ b/Sources/CoreLibrary/Events/NouveauTourEventArgs.cs @@ -0,0 +1,45 @@ +using CoreLibrary.Exceptions; + +namespace CoreLibrary.Events +{ + /// + /// Représente les arguments d'événement pour le début d'un nouveau tour. + /// + public class NouveauTourEventArgs : EventArgs + { + /// + /// Obtient le joueur dont c'est le tour. + /// + public Joueur Joueur { get; private set; } + + /// + /// Obtient le numéro du tour. + /// + public int Tour { get; private set; } + + /// + /// Obtient la grille du joueur actuelle. + /// + public IEnumerable> Grille { get; private set; } + + /// + /// Obtient les indicateurs de la grille de jeu. + /// + public IEnumerable> Indicateurs { get; private set; } + + /// + /// Initialise une nouvelle instance de la classe avec les informations spécifiées. + /// + /// Le joueur dont c'est le tour. + /// Le numéro du tour. + /// La grille du joueur actuelle. + /// Les indicateurs de la grille de jeu. + public NouveauTourEventArgs(Joueur joueur, int tour, IEnumerable> grille, IEnumerable> indicateurs) + { + Joueur = joueur; + Tour = tour; + Grille = grille; + Indicateurs = indicateurs; + } + } +} \ No newline at end of file diff --git a/Sources/CoreLibrary/Events/PartieTermineeEventArgs.cs b/Sources/CoreLibrary/Events/PartieTermineeEventArgs.cs new file mode 100644 index 0000000..955fc4e --- /dev/null +++ b/Sources/CoreLibrary/Events/PartieTermineeEventArgs.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CoreLibrary.Events +{ + /// + /// Représente les arguments d'événement pour la fin d'une partie. + /// + public class PartieTermineeEventArgs : EventArgs + { + /// + /// Obtient les joueurs gagnants de la partie. + /// + public IEnumerable Gagnants { get; private set; } + + /// + /// Obtient les joueurs perdants de la partie. + /// + public IEnumerable Perdants { get; private set; } + + /// + /// Initialise une nouvelle instance de la classe avec les gagnants et les perdants spécifiés. + /// + /// Les joueurs gagnants de la partie. + /// Les joueurs perdants de la partie. + public PartieTermineeEventArgs(IEnumerable gagnants, IEnumerable perdants) + { + Gagnants = gagnants; + Perdants = perdants; + } + } +} diff --git a/Sources/CoreLibrary/Events/PasserMainEventArgs.cs b/Sources/CoreLibrary/Events/PasserMainEventArgs.cs new file mode 100644 index 0000000..91df021 --- /dev/null +++ b/Sources/CoreLibrary/Events/PasserMainEventArgs.cs @@ -0,0 +1,9 @@ +namespace CoreLibrary.Events +{ + /// + /// Représente les arguments d'événement pour le passage de la main au joueur suivant. + /// + public class PasserMainEventArgs : EventArgs + { + } +} diff --git a/Sources/CoreLibrary/Events/SupprimerDernierJetonEventArgs.cs b/Sources/CoreLibrary/Events/SupprimerDernierJetonEventArgs.cs new file mode 100644 index 0000000..8ba6ae9 --- /dev/null +++ b/Sources/CoreLibrary/Events/SupprimerDernierJetonEventArgs.cs @@ -0,0 +1,9 @@ +namespace CoreLibrary.Events +{ + /// + /// Représente les arguments d'événement pour la suppression du dernier jeton ajouté. + /// + public class SupprimerDernierJetonEventArgs : EventArgs + { + } +} diff --git a/Sources/CoreLibrary/Exceptions/CodeCompletException.cs b/Sources/CoreLibrary/Exceptions/CodeCompletException.cs new file mode 100644 index 0000000..dc4dc7f --- /dev/null +++ b/Sources/CoreLibrary/Exceptions/CodeCompletException.cs @@ -0,0 +1,34 @@ +using System.Runtime.Serialization; + +namespace CoreLibrary.Exceptions +{ + /// + /// Exception levée lorsqu'un jeton est ajouté à un code déjà complet. + /// + [Serializable] + public class CodeCompletException : Exception + { + /// + /// Initialise une nouvelle instance de la classe . + /// + private const string messageDefaut = "Le code dans lequel vous essayez d'ajouter un jeton est déjà complet."; + + public CodeCompletException() : base(messageDefaut) + {} + + public CodeCompletException(string message) : base(message) + {} + + public CodeCompletException(string message, Exception exception) : base(message, exception) + {} + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + protected CodeCompletException(SerializationInfo info, StreamingContext contexte) : base(info, contexte) { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + } + } +} diff --git a/Sources/CoreLibrary/Exceptions/CodeIncompletException.cs b/Sources/CoreLibrary/Exceptions/CodeIncompletException.cs new file mode 100644 index 0000000..b437029 --- /dev/null +++ b/Sources/CoreLibrary/Exceptions/CodeIncompletException.cs @@ -0,0 +1,34 @@ +using System.Runtime.Serialization; + +namespace CoreLibrary.Exceptions +{ + /// + /// Exception levée lorsqu'un code incomplet est ajouté à la grille. + /// + [Serializable] + public class CodeIncompletException : Exception + { + /// + /// Initialise une nouvelle instance de la classe . + /// + private const string messageDefaut = "Le code que vous essayez d'ajouter dans la grille n'est pas complet."; + + public CodeIncompletException() : base(messageDefaut) + { } + + public CodeIncompletException(string message) : base(message) + { } + + public CodeIncompletException(string message, Exception exception) : base(message, exception) + { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + protected CodeIncompletException(SerializationInfo info, StreamingContext contexte) : base(info, contexte) { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + } + } +} diff --git a/Sources/CoreLibrary/Exceptions/CodeInvalideException.cs b/Sources/CoreLibrary/Exceptions/CodeInvalideException.cs new file mode 100644 index 0000000..a786e04 --- /dev/null +++ b/Sources/CoreLibrary/Exceptions/CodeInvalideException.cs @@ -0,0 +1,40 @@ +using System.Runtime.Serialization; + +namespace CoreLibrary.Exceptions +{ + /// + /// Exception levée lorsqu'un code avec une taille invalide est ajouté à la grille. + /// + [Serializable] + public class CodeInvalideException : Exception + { + /// + /// Initialise une nouvelle instance de la classe . + /// + /// La taille du code que vous essayez d'ajouter. + /// La taille du code que le plateau attend. + private const string messageDefaut = "Le code que vous essayez d'ajouter est invalide."; + + public CodeInvalideException() : base(messageDefaut) + { } + + public CodeInvalideException(int tailleCodeAjoute, int tailleCodePlateau) : + base($"Le code que vous essayez d'ajouter est un code de taille {tailleCodeAjoute}, or le plateau attend un code de {tailleCodePlateau}.") + { } + + public CodeInvalideException(string message) : base(message) + { } + + public CodeInvalideException(string message, Exception exception) : base(message, exception) + { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + protected CodeInvalideException(SerializationInfo info, StreamingContext contexte) : base(info, contexte) { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + } + } +} diff --git a/Sources/CoreLibrary/Exceptions/CodeVideException.cs b/Sources/CoreLibrary/Exceptions/CodeVideException.cs new file mode 100644 index 0000000..f9fc813 --- /dev/null +++ b/Sources/CoreLibrary/Exceptions/CodeVideException.cs @@ -0,0 +1,34 @@ +using System.Runtime.Serialization; + +namespace CoreLibrary.Exceptions +{ + /// + /// Exception levée lorsqu'un jeton est supprimé d'un code qui est déjà vide. + /// + [Serializable] + public class CodeVideException : Exception + { + /// + /// Initialise une nouvelle instance de la classe . + /// + private const string messageDefaut = "Le code dans lequel vous essayez de supprimer un jeton est déjà vide."; + + public CodeVideException() : base(messageDefaut) + { } + + public CodeVideException(string message) : base(message) + { } + + public CodeVideException(string message, Exception exception) : base(message, exception) + { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + protected CodeVideException(SerializationInfo info, StreamingContext contexte) : base(info, contexte) { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + } + } +} diff --git a/Sources/CoreLibrary/Exceptions/GrilleCompleteException.cs b/Sources/CoreLibrary/Exceptions/GrilleCompleteException.cs new file mode 100644 index 0000000..b2d9ce0 --- /dev/null +++ b/Sources/CoreLibrary/Exceptions/GrilleCompleteException.cs @@ -0,0 +1,34 @@ +using System.Runtime.Serialization; + +namespace CoreLibrary.Exceptions +{ + /// + /// Exception levée lorsqu'un code est ajouté à une grille qui est déjà complète. + /// + [Serializable] + public class GrilleCompleteException : Exception + { + /// + /// Initialise une nouvelle instance de la classe . + /// + private const string messageDefaut = "La grille dans laquelle vous essayez d'ajouter un code est déjà complète."; + + public GrilleCompleteException() : base(messageDefaut) + { } + + public GrilleCompleteException(string message) : base(message) + { } + + public GrilleCompleteException(string message, Exception exception) : base(message, exception) + { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + protected GrilleCompleteException(SerializationInfo info, StreamingContext contexte) : base(info, contexte) { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + } + } +} diff --git a/Sources/CoreLibrary/Exceptions/IndiceCodeException.cs b/Sources/CoreLibrary/Exceptions/IndiceCodeException.cs new file mode 100644 index 0000000..1366665 --- /dev/null +++ b/Sources/CoreLibrary/Exceptions/IndiceCodeException.cs @@ -0,0 +1,40 @@ +using System.Runtime.Serialization; + +namespace CoreLibrary.Exceptions +{ + /// + /// Exception levée lorsqu'un indice de jeton est invalide. + /// + [Serializable] + public class IndiceCodeException : Exception + { + /// + /// Initialise une nouvelle instance de la classe . + /// + /// L'indice incorrect qui a été spécifié. + /// L'indice maximum permis. + private const string messageDefaut = "L'indice du jeton que vous essayez de récupérer est hors de la plage valide."; + + public IndiceCodeException() : base(messageDefaut) + { } + + public IndiceCodeException(int indice, int indiceMax) : + base($"Vous avez essayé de récupérer le jeton à la place {indice}, mais son indice doit être compris entre 0 et {indiceMax}.") + { } + + public IndiceCodeException(string message) : base(message) + { } + + public IndiceCodeException(string message, Exception exception) : base(message, exception) + { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + protected IndiceCodeException(SerializationInfo info, StreamingContext contexte) : base(info, contexte) { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + } + } +} diff --git a/Sources/CoreLibrary/Exceptions/PartieNonCommenceeException.cs b/Sources/CoreLibrary/Exceptions/PartieNonCommenceeException.cs new file mode 100644 index 0000000..3c0f8c7 --- /dev/null +++ b/Sources/CoreLibrary/Exceptions/PartieNonCommenceeException.cs @@ -0,0 +1,34 @@ +using System.Runtime.Serialization; + +namespace CoreLibrary.Exceptions +{ + /// + /// Exception levée lorsqu'une opération est tentée alors que la partie n'a pas encore commencé. + /// + [Serializable] + public class PartieNonCommenceeException : Exception + { + /// + /// Initialise une nouvelle instance de la classe . + /// + private const string messageDefaut = "La partie n'a pas encore commencée."; + + public PartieNonCommenceeException() : base(messageDefaut) + { } + + public PartieNonCommenceeException(string message) : base(message) + { } + + public PartieNonCommenceeException(string message, Exception exception) : base(message, exception) + { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + protected PartieNonCommenceeException(SerializationInfo info, StreamingContext contexte) : base(info, contexte) { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + } + } +} diff --git a/Sources/CoreLibrary/Exceptions/TailleCodeException.cs b/Sources/CoreLibrary/Exceptions/TailleCodeException.cs new file mode 100644 index 0000000..bf3fae9 --- /dev/null +++ b/Sources/CoreLibrary/Exceptions/TailleCodeException.cs @@ -0,0 +1,39 @@ +using System.Runtime.Serialization; + +namespace CoreLibrary.Exceptions +{ + /// + /// Exception levée lorsqu'une taille de code invalide est spécifiée. + /// + [Serializable] + public class TailleCodeException : Exception + { + /// + /// Initialise une nouvelle instance de la classe . + /// + /// La taille du code spécifiée. + private const string messageDefaut = "Un code doit avoir une taille positive non nulle."; + + public TailleCodeException() : base(messageDefaut) + { } + + public TailleCodeException(int taille) : + base($"Un code doit avoir une taille positive non nulle, or il a reçu {taille}.") + { } + + public TailleCodeException(string message) : base(message) + { } + + public TailleCodeException(string message, Exception exception) : base(message, exception) + { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + protected TailleCodeException(SerializationInfo info, StreamingContext contexte) : base(info, contexte) { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + } + } +} diff --git a/Sources/CoreLibrary/Exceptions/TailleGrilleException.cs b/Sources/CoreLibrary/Exceptions/TailleGrilleException.cs new file mode 100644 index 0000000..e7f06ef --- /dev/null +++ b/Sources/CoreLibrary/Exceptions/TailleGrilleException.cs @@ -0,0 +1,39 @@ +using System.Runtime.Serialization; + +namespace CoreLibrary.Exceptions +{ + /// + /// Exception levée lorsqu'une taille de grille invalide est spécifiée. + /// + [Serializable] + public class TailleGrilleException : Exception + { + /// + /// Initialise une nouvelle instance de la classe . + /// + /// La taille de grille spécifiée. + private const string messageDefaut = "Une grille doit avoir une taille positive non nulle."; + + public TailleGrilleException() : base(messageDefaut) + { } + + public TailleGrilleException(int taille) : + base($"Une grille doit avoir une taille positive non nulle, or elle a reçu {taille}.") + { } + + public TailleGrilleException(string message) : base(message) + { } + + public TailleGrilleException(string message, Exception exception) : base(message, exception) + { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + protected TailleGrilleException(SerializationInfo info, StreamingContext contexte) : base(info, contexte) { } + + [Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")] + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + } + } +} diff --git a/Sources/CoreLibrary/IRegles.cs b/Sources/CoreLibrary/IRegles.cs index dfe558b..8f20344 100644 --- a/Sources/CoreLibrary/IRegles.cs +++ b/Sources/CoreLibrary/IRegles.cs @@ -1,25 +1,80 @@ namespace CoreLibrary { + /// + /// Interface définissant les règles du jeu. + /// public interface IRegles { + /// + /// Obtient le nom des règles du jeu. + /// string Nom { get; } + /// + /// Obtient le nombre de maximum de tours. + /// int TourMaximum { get; } + + /// + /// Obtient la taille maximal du code. + /// int TailleCodeMaximum { get; } + /// + /// Obtient le nombre de joueurs actuels. + /// int NbJoueurs { get; } + + /// + /// Obtient le nombre de maximum de joueurs. + /// int NbJoueursMaximum { get; } - void AjouterJoueur(string nom); + /// + /// Ajoute un joueur avec le nom spécifié. + /// + /// Nom du joueur à ajouter + /// Le joueur ajouté. + Joueur AjouterJoueur(string nom); + + /// + /// Récupère le joueur courant. + /// + /// Le joueur courant. Joueur JoueurCourant(); + + /// + /// Passe la main au joueur suivant. + /// void PasserLaMain(); + /// + /// Génère un code selon les règles du jeu. + /// + /// Le code généré. Code GenererCode(); + /// + /// Initialise le premier joueur à jouer. + /// void CommencerLaPartie(); + + /// + /// Vérifie si la partie est terminée. + /// + /// True si la partie est terminée, sinon False. bool EstTerminee(); + /// + /// Récupère les joueurs gagnants. + /// + /// Enumération des joueurs gagnants. IEnumerable Gagnants(); + + /// + /// Récupère les joueurs perdants. + /// + /// Enumération des joueurs perdants. IEnumerable Perdants(); } } diff --git a/Sources/CoreLibrary/Indicateur.cs b/Sources/CoreLibrary/Indicateur.cs index 05e3689..d26b5da 100644 --- a/Sources/CoreLibrary/Indicateur.cs +++ b/Sources/CoreLibrary/Indicateur.cs @@ -1,5 +1,8 @@ namespace CoreLibrary { + /// + /// Représente les couleurs disponibles pour les indicateurs. + /// public enum Indicateur { BONNEPLACE, diff --git a/Sources/CoreLibrary/Jeton.cs b/Sources/CoreLibrary/Jeton.cs index b115aa2..9940127 100644 --- a/Sources/CoreLibrary/Jeton.cs +++ b/Sources/CoreLibrary/Jeton.cs @@ -1,9 +1,19 @@ namespace CoreLibrary { + /// + /// Représente un jetons de couleur. + /// public struct Jeton { + /// + /// Obtient la couleur du jeton. + /// public readonly Couleur Couleur { get; private init; } + /// + /// Initialise une nouvelle instance de la structure Jeton avec la couleur spécifiée. + /// + /// La couleur du jeton. public Jeton(Couleur couleur) { Couleur = couleur; diff --git a/Sources/CoreLibrary/Joueur.cs b/Sources/CoreLibrary/Joueur.cs index 48a1bbb..e8463bd 100644 --- a/Sources/CoreLibrary/Joueur.cs +++ b/Sources/CoreLibrary/Joueur.cs @@ -1,10 +1,24 @@ namespace CoreLibrary { + /// + /// Représente un joueur. + /// public class Joueur { + /// + /// Obtient le nom du joueur. + /// public string Nom { get; private init; } + /// + /// Obtient le plateau du joueur. + /// public Plateau Plateau { get; private init; } + /// + /// Crée une nouvelle instance de joueur avec un nom et un plateau spécifié. + /// + /// Le nom du joueur + /// Le plateau du joueur public Joueur(string nom, Plateau plateau) { Nom = nom; diff --git a/Sources/CoreLibrary/Partie.cs b/Sources/CoreLibrary/Partie.cs new file mode 100644 index 0000000..1596cf0 --- /dev/null +++ b/Sources/CoreLibrary/Partie.cs @@ -0,0 +1,214 @@ +using CoreLibrary.Events; +using CoreLibrary.Exceptions; + +namespace CoreLibrary +{ + /// + /// Représente une partie de jeu. + /// + public class Partie + { + private readonly IRegles regles; + + + /// + /// Définit le délégué pour gérer les événements avec des arguments de type string. + /// + public delegate string? StringEventHandler(Object? sender, TEventArgs e); + + /// + /// Définit le délégué pour gérer les événements avec des arguments de type Jeton. + /// + public delegate Jeton? JetonEventHandler(Object? sender, TEventArgs e); + + /// + /// Événement déclenché lorsqu'il est nécessaire de d'ajouter un joueur. + /// + public event StringEventHandler? DemanderJoueur; + + /// + /// Événement déclenché lorsqu'il est nécessaire d'ajouter un jeton. + /// + public event JetonEventHandler? DemanderJeton; + + /// + /// É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'il est nécessaire d'ajouter un jeton. + /// + public event EventHandler? AjouterJeton; + + + /// + /// Événement déclenché lorsqu'un jeton est supprimé. + /// + public event EventHandler? SupprimerDernierJeton; + + /// + /// É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 d'ajout d'un joueur. + /// + /// Le numéro du joueur à ajouter + /// Le nom du joueur demandé + private string? QuandDemanderJoueur(int numero) => DemanderJoueur?.Invoke(this, new DemanderJoueurEventArgs(numero)); + + /// + /// Méthode pour déclencher l'événement de demande d'ajout d'un jeton. + /// + /// Le jeton demandé + private Jeton? QuandDemanderJeton() => DemanderJeton?.Invoke(this, new DemanderJetonEventArgs()); + + /// + /// 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 AjouterJoueursEventArgs(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. + /// La grille de jeu. + /// Les indicateurs de jeu. + private void QuandNouveauTour(Joueur joueur, int tour, IEnumerable> grille, IEnumerable> indicateurs) => NouveauTour?.Invoke(this, new NouveauTourEventArgs(joueur, tour, grille, indicateurs)); + + /// + /// Méthode pour déclencher l'événement d'ajout d'un nouveau jeton. + /// + /// Le jeton à ajouter. + private void QuandNouveauJeton(Jeton jeton) => AjouterJeton?.Invoke(this, new AjouterJetonEventArgs(jeton)); + + /// + /// Méthode pour déclencher l'événement de suppression du dernier jeton du code. + /// + private void QuandSupprimerDernierJeton() => SupprimerDernierJeton?.Invoke(this, new SupprimerDernierJetonEventArgs()); + + /// + /// Méthode pour déclencher l'événement d'ajout d'un nouveau code. + /// + /// Le code à ajouter. + private void QuandNouveauCode(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) + { + this.regles = regles; + } + + /// + /// Lance le déroulement de la partie. + /// + public void Jouer() + { + /// Ajout des joueurs jusqu'à atteindre le nombre maximum de joueurs défini par les règles + while (regles.NbJoueurs != regles.NbJoueursMaximum) + while (regles.NbJoueurs != regles.NbJoueursMaximum) + { + string nom = QuandDemanderJoueur(regles.NbJoueurs + 1) ?? $"Joueur {regles.NbJoueurs+1}"; + Joueur joueur = regles.AjouterJoueur(nom); + QuandAjouterJoueur(joueur); + } + + regles.CommencerLaPartie(); + QuandDebutPartie(); + + // Boucle principale du jeu qui dure jusqu'à qu'une condition de fin soit déclenchée + while (!regles.EstTerminee()) + { + Joueur joueurCourant = regles.JoueurCourant(); + Plateau plateauCourant = joueurCourant.Plateau; + + QuandNouveauTour(joueurCourant, plateauCourant.Tour, plateauCourant.Grille(), plateauCourant.Indicateurs()); + + Code code = regles.GenererCode(); + + // Phase de saisie du code par le joueur jusqu'à que le code soit complet. + while (!code.EstComplet()) + { + Jeton? jeton = QuandDemanderJeton(); + + if(jeton == null) + { + if(DemanderJeton != null) + { + // Si quelqu'un écoute l'événement mais ne renvoie rien, alors on supprime le dernier jeton + code.SupprimerDernierJeton(); + QuandSupprimerDernierJeton(); + } + else + { + // Si personne n'écoute l'évenment, on met un jeton aléatoire + jeton = new Jeton(); + } + } + + if(jeton != null) + { + code.AjouterJeton(jeton.Value); + QuandNouveauJeton(jeton.Value); + } + } + plateauCourant.AjouterCode(code); + QuandNouveauCode(code); + + regles.PasserLaMain(); + QuandPasserMain(); + } + + + regles.Gagnants(); + regles.Perdants(); + + QuandPartieTerminee(regles.Gagnants(), regles.Perdants()); + } + } +} diff --git a/Sources/CoreLibrary/Plateau.cs b/Sources/CoreLibrary/Plateau.cs index d8b0c16..70ada70 100644 --- a/Sources/CoreLibrary/Plateau.cs +++ b/Sources/CoreLibrary/Plateau.cs @@ -1,28 +1,46 @@ -namespace CoreLibrary +using CoreLibrary.Exceptions; +using System.Security.Cryptography; + +namespace CoreLibrary { + /// + /// Représente un plateau de jeu composer de code + /// public class Plateau { - private static Random random = new Random(); - private readonly Code codeSecret; private readonly Code?[] grille; private readonly IEnumerable[] indicateurs; private readonly int tailleCode; + /// + /// Obtient le numéro de tour actuel. + /// public int Tour { get; private set; } = 1; + + /// + /// Obtient True si le joueur a gagné sinon False + /// public bool Victoire { get; private set; } = false; + /// + /// Initialise une nouvelle instance de la classe . + /// + /// Taille des codes du plateau + /// Taille du plateau de jeu + /// Levée lorsque la tailleCode est inférieur ou égal à 0. + /// Levée lorsque la tailleGrille est inférieur ou égal à 0. public Plateau(int tailleCode, int tailleGrille) { if(tailleCode <= 0) { - throw new PlateauTailleCodeException(); + throw new TailleCodeException(tailleCode); } if (tailleGrille <= 0) { - throw new PlateauTailleGrilleException(); + throw new TailleGrilleException(tailleGrille); } codeSecret = new Code(tailleCode); @@ -34,31 +52,44 @@ GenererCodeAleatoire(); } + /// + /// Génère un code secret aléatoire en utilisant des jetons de couleurs aléatoire. + /// private void GenererCodeAleatoire() { Couleur[] couleurs = (Couleur[])Enum.GetValues(typeof(Couleur)); for (int i = 0; i < tailleCode; ++i) { - codeSecret.AjouterJeton(new Jeton(couleurs[random.Next(couleurs.Length)])); + codeSecret.AjouterJeton(new Jeton(couleurs[RandomNumberGenerator.GetInt32(0, couleurs.Length)])); } } + /// + /// Vérifie si le plateau de jeu est plein. + /// + /// True si la tableau est plein, sinon False. public bool EstComplet() { return Tour - 1 == grille.Length; } + /// + /// Ajoute le code fourni au plateau de jeu. + /// + /// Le code à ajouter au plateau de jeu. + /// Levée lorsque le code fourni à une taille invalide. + /// Levée lorsque le code fourni est incomplet. public void AjouterCode(Code code) { if (code.TailleMaximale() != tailleCode) { - throw new PlateauTailleCodeException(); + throw new CodeInvalideException(code.TailleMaximale(), tailleCode); } if (!code.EstComplet()) { - throw new PlateauCodeIncompletException(); + throw new CodeIncompletException(); } indicateurs[Tour - 1] = codeSecret.Comparer(code); @@ -71,16 +102,33 @@ } } + /// + /// Vérifie si le code fourni correspond au code secret. + /// + /// Le code à vérifier. + /// True si le code fourni correspond au code secret, sinon False + /// Levée lorsque le code fourni à une taille invalide. + /// Levée lorsque le code fourni est incomplet. public bool EstBonCode(Code code) { - IEnumerable indicateurs = codeSecret.Comparer(code); + if (code.TailleMaximale() != tailleCode) + { + throw new CodeInvalideException(code.TailleMaximale(), tailleCode); + } + + if (!code.EstComplet()) + { + throw new CodeIncompletException(); + } + + IEnumerable indicateursCode = codeSecret.Comparer(code); - if (indicateurs.Count() != tailleCode) + if (indicateursCode.Count() != tailleCode) { return false; } - foreach (Indicateur indicateur in indicateurs) + foreach (Indicateur indicateur in indicateursCode) { if (indicateur != Indicateur.BONNEPLACE) { @@ -91,6 +139,10 @@ return true; } + /// + /// Récupère le plateau de jeu. + /// + /// Le plateau de jeu représenté sous forme d'une collections de jetons. public IEnumerable> Grille() { IEnumerable[] grilleJetons = new IEnumerable[grille.Length]; @@ -103,6 +155,10 @@ return grilleJetons; } + /// + /// Récupère les indicateurs pour chaque tour. + /// + /// Les indicateurs pour chaque tour représentés sous forme d'une collections d'indicateurs. public IEnumerable> Indicateurs() { return indicateurs; diff --git a/Sources/CoreLibrary/PlateauCodeIncompletException.cs b/Sources/CoreLibrary/PlateauCodeIncompletException.cs deleted file mode 100644 index d522cb4..0000000 --- a/Sources/CoreLibrary/PlateauCodeIncompletException.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace CoreLibrary -{ - public class PlateauCodeIncompletException : Exception - { - public PlateauCodeIncompletException() : base("Le code est incomplet") - { } - } -} diff --git a/Sources/CoreLibrary/PlateauTailleCodeException.cs b/Sources/CoreLibrary/PlateauTailleCodeException.cs deleted file mode 100644 index a73ed73..0000000 --- a/Sources/CoreLibrary/PlateauTailleCodeException.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace CoreLibrary -{ - public class PlateauTailleCodeException : Exception - { - public PlateauTailleCodeException() : base("La taille du code doit être positive non nulle.") { } - } -} diff --git a/Sources/CoreLibrary/PlateauTailleCodeIncompleteException.cs b/Sources/CoreLibrary/PlateauTailleCodeIncompleteException.cs deleted file mode 100644 index 38133c7..0000000 --- a/Sources/CoreLibrary/PlateauTailleCodeIncompleteException.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace CoreLibrary -{ - public class PlateauTailleCodeIncompleteException : Exception - { - public PlateauTailleCodeIncompleteException() : base("Le code n'est pas remplit au maximum") { } - } -} diff --git a/Sources/CoreLibrary/PlateauTailleGrilleException.cs b/Sources/CoreLibrary/PlateauTailleGrilleException.cs deleted file mode 100644 index 1305e65..0000000 --- a/Sources/CoreLibrary/PlateauTailleGrilleException.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace CoreLibrary -{ - public class PlateauTailleGrilleException : Exception - { - public PlateauTailleGrilleException() : base("La taille de la grille doit être égale positive non nulle.") - { } - } -} diff --git a/Sources/CoreLibrary/ReglesClassiques.cs b/Sources/CoreLibrary/ReglesClassiques.cs index a7ac01e..44950b5 100644 --- a/Sources/CoreLibrary/ReglesClassiques.cs +++ b/Sources/CoreLibrary/ReglesClassiques.cs @@ -1,110 +1,169 @@ -namespace CoreLibrary -{ - public class ReglesClassiques : IRegles - { - private int nbJoueurs = 0; - private int? joueurCourant; - private readonly Joueur[] joueurs; - - public string Nom { get => "Règles classiques"; } - - public int TourMaximum { get => 12; } - public int TailleCodeMaximum { get => 4; } - public int NbJoueurs { get => nbJoueurs; } - public int NbJoueursMaximum { get => 2; } - - - public ReglesClassiques() - { - joueurs = new Joueur[NbJoueursMaximum]; - } - - - public void AjouterJoueur(string nom) - { - joueurs[nbJoueurs++] = new Joueur(nom, new Plateau(TailleCodeMaximum, TourMaximum)); - } - - public Joueur JoueurCourant() - { - if (!joueurCourant.HasValue) - throw new ReglesClassiquesJoueurCourantNull(); - - return joueurs[joueurCourant.Value]; - } - - public void PasserLaMain() - { - if (!joueurCourant.HasValue) - { - throw new ReglesClassiquesJoueurCourantNull(); - } - - joueurCourant++; - if (joueurCourant >= joueurs.Length) - { - joueurCourant = 0; - } - - } - - - public Code GenererCode() - { - return new Code(TailleCodeMaximum); - } - - - public void CommencerLaPartie() - { - joueurCourant = 0; - } - - - public bool EstTerminee() - { - if (!joueurCourant.HasValue || joueurCourant != 0) - return false; - - if (JoueurCourant().Plateau.Tour > TourMaximum) - return true; - - for (int i = 0; i < joueurs.Length; ++i) - { - if (joueurs[i].Plateau.Victoire) - return true; - } - - return false; - } - - - public IEnumerable Gagnants() - { - Joueur[] gagnants = []; - for (int i = 0; i < joueurs.Length; ++i) - { - if (joueurs[i].Plateau.Victoire) - { - gagnants = gagnants.Append(joueurs[i]).ToArray(); - } - } - - return gagnants; - } - - public IEnumerable Perdants() - { - Joueur[] perdants = []; - for (int i = 0; i < joueurs.Length; ++i) - { - if (!joueurs[i].Plateau.Victoire) - { - perdants = perdants.Append(joueurs[i]).ToArray(); - } - } - - return perdants; - } - } -} +using CoreLibrary.Exceptions; + +namespace CoreLibrary +{ + /// + /// Implémente les règles du jeu. + /// + public class ReglesClassiques : IRegles + { + private int nbJoueurs = 0; + private int? joueurCourant; + private readonly Joueur[] joueurs; + + /// + /// Obtient le nom des règles. + /// + public string Nom { get => "Règles classiques"; } + + /// + /// Obtient le nombre maximum de tours. + /// + public int TourMaximum { get => 12; } + + /// + /// Obtient la taille maximale d'un code. + /// + public int TailleCodeMaximum { get => 4; } + /// + /// Obtient le nombre de joueurs actuels dans le jeu. + /// + public int NbJoueurs { get => nbJoueurs; } + /// + /// Obtient le nombre maximum de joueurs possible pour le jeu. + /// + public int NbJoueursMaximum { get => 2; } + + + /// + /// Initialise une nouvelle instance de la classe en initialisant un tableau de joueurs avec la taille maximale de joueurs autorisée. + /// + public ReglesClassiques() + { + joueurs = new Joueur[NbJoueursMaximum]; + } + + + + /// + /// Ajoute un joueur avec le nom spécifié. + /// + /// Le nom du joueur à ajouter. + /// Le joueur ajouté. + public Joueur AjouterJoueur(string nom) + { + Joueur joueur = new Joueur(nom, new Plateau(TailleCodeMaximum, TourMaximum)); + joueurs[nbJoueurs++] = joueur; + return joueur; + } + + /// + /// Obtient le joueur dont c'est actuellement le tour. + /// + /// Le joueur actuel. + /// Levée lorsqu'il n'y a pas de joueur courant. + + public Joueur JoueurCourant() + { + if (!joueurCourant.HasValue) + throw new PartieNonCommenceeException(); + + return joueurs[joueurCourant.Value]; + } + + /// + /// Passe la main au joueur suivant. + /// + /// Levée lorsqu'il n'y a pas de joueur courant. + public void PasserLaMain() + { + if (!joueurCourant.HasValue) + { + throw new PartieNonCommenceeException(); + } + + joueurCourant++; + if (joueurCourant >= joueurs.Length) + { + joueurCourant = 0; + } + + } + + /// + /// Génère un nouveau code. + /// + /// Le code généré + + public Code GenererCode() + { + return new Code(TailleCodeMaximum); + } + + /// + /// Initialise le premier joueur à jouer. + /// + public void CommencerLaPartie() + { + joueurCourant = 0; + } + + + /// + /// Vérifie si la partie est terminée. + /// + /// True si la partie est terminée, sinon False. + public bool EstTerminee() + { + if (!joueurCourant.HasValue || joueurCourant != 0) + return false; + + if (JoueurCourant().Plateau.Tour > TourMaximum) + return true; + + for (int i = 0; i < joueurs.Length; ++i) + { + if (joueurs[i].Plateau.Victoire) + return true; + } + + return false; + } + + /// + /// Obtient les joueurs gagnants de la partie. + /// + /// La liste des joueurs gagnants. + public IEnumerable Gagnants() + { + Joueur[] gagnants = []; + for (int i = 0; i < joueurs.Length; ++i) + { + if (joueurs[i].Plateau.Victoire) + { + gagnants = gagnants.Append(joueurs[i]).ToArray(); + } + } + + return gagnants; + } + + /// + /// Obtient les joueurs perdants de la partie. + /// + /// La liste des joueurs perdants. + public IEnumerable Perdants() + { + Joueur[] perdants = []; + for (int i = 0; i < joueurs.Length; ++i) + { + if (!joueurs[i].Plateau.Victoire) + { + perdants = perdants.Append(joueurs[i]).ToArray(); + } + } + + return perdants; + } + } +} diff --git a/Sources/CoreLibrary/ReglesClassiquesJoueurCourantNull.cs b/Sources/CoreLibrary/ReglesClassiquesJoueurCourantNull.cs deleted file mode 100644 index 89e6df5..0000000 --- a/Sources/CoreLibrary/ReglesClassiquesJoueurCourantNull.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace CoreLibrary -{ - public class ReglesClassiquesJoueurCourantNull : Exception - { - public ReglesClassiquesJoueurCourantNull() : base("Le joueur courant est null") - { } - } -}