Merge de master dans tests
continuous-integration/drone/push Build is failing Details

master
Céleste BARBOSA 12 months ago
commit a513ba8447

@ -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<TEventArgs>(sender: Object?, e: TEventArgs): string?
+JetonEventHandler<TEventArgs>(sender: Object?, e: TEventArgs): Jeton
---
+DemanderJoueur: StringEventHandler<DemanderJoueurEventArgs>?
+DemanderJeton: JetonEventHandler<DemanderJetonEventArgs>?
+AjouterJoueur: EventHandler<AjouterJoueursEventArgs>?
+DebutPartie: EventHandler<AjouterJoueursEventArgs>?
+NouveauTour: EventHandler<AjouterJoueursEventArgs>?
+NouveauJeton: EventHandler<AjouterJoueursEventArgs>?
+NouveauCode: EventHandler<AjouterJoueursEventArgs>?
+PasserMain: EventHandler<AjouterJoueursEventArgs>?
+PartieTerminee: EventHandler<AjouterJoueursEventArgs>?
---
-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

@ -0,0 +1,64 @@
```plantuml
@startuml
package CoreLibrary <<Rectangle>> {
package Core <<Rectangle>> {
class Code
class Plateau
struct Jeton
enum Couleur
enum Indicateur
}
package Joueurs <<Rectangle>> {
class Joueur
}
package Regles <<Rectangle>> {
interface IRegles
class ReglesClassiques
}
package Evenements <<Rectangle>> {
class AjouterCodeEventArgs
class AjouterJetonEventArgs
class AjouterJoueurEventArgs
class DebutPartieEventArgs
class DemanderJetonEventArgs
class DemanderJoueurEventArgs
class NouveauTourEventArgs
class PartieTermineeEventArgs
class PasserMainEventArgs
}
package Exceptions <<Rectangle>> {
class CodeCompletException
class CodeIncompletException
class CodeInvalideException
class CodeVideException
class GrilleCompleteException
class IndiceCodeException
class PartieNonCommenceeException
class TailleCodeException
class TailleGrilleException
}
class Partie
}
package ConsoleApp <<Rectangle>> {
class Program
class Utils
}
package System <<Rectangle>> {
class Exception
class EventArgs
class Random
}
@enduml
```

@ -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

@ -0,0 +1,147 @@
using CoreLibrary.Events;
using CoreLibrary;
namespace ConsoleApp
{
/// <summary>
/// Fournit des gestionnaires d'événements pour les événements liés au déroulement de la partie.
/// </summary>
public static class Evenements
{
/// <summary>
/// Gestionnaire d'événement pour l'ajout d'un joueur.
/// </summary>
public static string? DemanderJoueur(Object? sender, DemanderJoueurEventArgs e)
{
Console.WriteLine($"Joueur {e.Numero}");
Console.Write(">>> ");
string? nom = Console.ReadLine();
Console.WriteLine();
return nom;
}
/// <summary>
/// Gestionnaire d'événement pour le début de la partie.
/// </summary>
public static void CommencerLaPartie(Object? sender, DebutPartieEventArgs e)
{
Utils.DessinerSeparateur();
Console.WriteLine("La partie commence, bonne chance à tous !\n");
}
/// <summary>
/// Gestionnaire d'événement pour le début d'un nouveau tour.
/// </summary>
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();
}
/// <summary>
/// Gestionnaire d'événement pour la demande d'ajout d'un jeton.
/// </summary>
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]);
}
/// <summary>
/// Gestionnaire d'événement pour l'ajout d'un jeton.
/// </summary>
public static void AjouterJeton(Object? sender, AjouterJetonEventArgs e)
{
Utils.DessinerPion(e.Jeton.Couleur);
}
/// <summary>
/// Gestionnaire d'événement pour la suppression du dernier jeton ajouté.
/// </summary>
public static void SupprimerDernierJeton(Object? sender, SupprimerDernierJetonEventArgs e)
{
Console.Write("\b\b\b \b\b\b\b\b\b");
}
/// <summary>
/// Gestionnaire d'événement pour l'ajout d'un code.
/// </summary>
public static void AjouterCode(Object? sender, AjouterCodeEventArgs e)
{
Console.WriteLine();
Utils.DessinerSeparateur();
}
/// <summary>
/// Gestionnaire d'événement pour la fin de la partie.
/// </summary>
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...");
}
}
}
}

@ -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();

@ -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<Couleur, ConsoleColor> convertirCouleurs = new Dictionary<Couleur, ConsoleColor>()
{
{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<Indicateur, ConsoleColor> convertirIndicateurs = new Dictionary<Indicateur, ConsoleColor>()
{
{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<Jeton?> jetons)
{
foreach (Jeton? jeton in jetons)
{
if (jeton.HasValue)
{
DessinerJeton(jeton.Value);
}
else
{
Console.Write(" ");
}
}
}
public static void DessinerIndicateurs(IEnumerable<Indicateur> 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<IEnumerable<Jeton?>> grille, IEnumerable<IEnumerable<Indicateur>> indicateurs)
{
IEnumerable<Jeton?>[] grilleT = grille.ToArray();
IEnumerable<Indicateur>[] 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
{
/// <summary>
/// Classe utilitaire contenant des méthodes pour dessiner des éléments dans la console.
/// </summary>
public static class Utils
{
// Dictionnaires associant les valeurs des énumérations avec les couleurs de la console
private readonly static Dictionary<Couleur, ConsoleColor> couleursTerminal = new Dictionary<Couleur, ConsoleColor>()
{
{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<Indicateur, ConsoleColor> indicateursTerminal = new Dictionary<Indicateur, ConsoleColor>()
{
{Indicateur.BONNEPLACE, ConsoleColor.Black },
{Indicateur.BONNECOULEUR, ConsoleColor.White }
};
/// <summary>
/// Dessine le titre du jeu dans la console.
/// </summary>
public static void DessinerTitre()
{
Console.WriteLine(@"
__ __ _ _ _
| \/ | __ _ ___| |_ ___ _ _ _ __ (_) _ _ __| |
| |\/| |/ _` |(_-<| _|/ -_)| '_|| ' \ | || ' \ / _` |
|_| |_|\__,_|/__/ \__|\___||_| |_|_|_||_||_||_|\__,_|
");
DessinerSeparateur();
}
/// <summary>
/// Dessine un séparateur dans la console.
/// </summary>
public static void DessinerSeparateur()
{
Console.WriteLine(@"
");
}
/// <summary>
/// Dessine un pion dans la console.
/// </summary>
/// <param name="pion">Le pion à dessiner (une couleur ou un indicateur).</param>
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(" ");
}
/// <summary>
/// Dessine une ligne de pions sur la console.
/// </summary>
/// <param name="ligne">Un tableau d'énumérations représentant les pions à dessiner.</param>
private static void DessinerLigne(Enum[] ligne)
{
foreach(Enum pion in ligne)
DessinerPion(pion);
Console.Write("".PadLeft((4 - ligne.Length) * 3));
}
/// <summary>
/// Dessine un plateau de jeu dans la console, affichant les jetons et les indicateurs.
/// </summary>
/// <param name="grille">La grille de jeu.</param>
/// <param name="indicateurs">Les indicateurs associés à chaque ligne.</param>
public static void DessinerPlateau(IEnumerable<IEnumerable<Jeton?>> grille, IEnumerable<IEnumerable<Indicateur>> indicateurs)
{
IEnumerable<Jeton?>[] grilleTableau = grille.ToArray();
IEnumerable<Indicateur>[] 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("──────────────── ────────────────");
}
}
}

@ -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")
{ }
}
}

@ -1,86 +1,153 @@
namespace CoreLibrary
using CoreLibrary.Exceptions;
namespace CoreLibrary
{
/// <summary>
/// Représente un code composé de jetons.
/// </summary>
public class Code
{
private readonly Jeton?[] lesJetons;
/// <summary>
/// Obtenir le nombre de jetons dans le code.
/// </summary>
public int NbJetons { get; private set; } = 0;
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="Code"/> avec la longueur de code spécifiée.
/// </summary>
/// <param name="tailleCode">La longueur du code.</param>
/// <exception cref="TailleCodeException">Levée lorsque la longueur du code spécifiée est inférieure ou égale à zéro.</exception>
public Code(int tailleCode)
{
if (tailleCode <= 0)
throw new CodeTailleInvalideException();
{
if(tailleCode <= 0)
{
throw new TailleCodeException(tailleCode);
}
lesJetons = new Jeton?[tailleCode];
}
/// <summary>
/// Initialise une nouvelle instance de la class <see cref="Code"/> avec les jetons spécifiés.
/// </summary>
/// <param name="jetons">Les jetons pour initaliser le code.</param>
/// <exception cref="TailleCodeException">Levée lorsque la collection de jetons spécifiée est vide.</exception>
public Code(IEnumerable<Jeton> 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);
}
}
/// <summary>
/// Ajoute un jeton au code.
/// </summary>
/// <param name="jeton">Le jeton à ajouter</param>
/// <exception cref="CodeCompletException">Levée lorsque le code est plein.</exception>
public void AjouterJeton(Jeton jeton)
{
if (EstComplet())
throw new CodeTableauLesJetonsCompletException();
{
if (NbJetons == TailleMaximale())
{
throw new CodeCompletException();
}
lesJetons[NbJetons++] = jeton;
}
/// <summary>
/// Supprime le dernier jeton ajouté au code.
/// </summary>
/// <exception cref="CodeVideException">Levée lorsque le code est vide.</exception>
public void SupprimerDernierJeton()
{
if(NbJetons <= 0)
throw new CodeTableauLesJetonsVideException();
if(NbJetons == 0)
{
throw new CodeVideException();
}
lesJetons[--NbJetons] = null;
}
/// <summary>
/// Récupère le jeton à l'indice spécifié dans le code.
/// </summary>
/// <param name="indice">L'indice du jeton a récupéré.</param>
/// <returns>Le jeton situé à l'indice spécifié.</returns>
/// <exception cref="IndiceCodeException">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é</exception>
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;
}
/// <summary>
/// Récupère une énumération des jetons dans le code.
/// </summary>
/// <returns>Enumération des jetons du code</returns>
public IEnumerable<Jeton?> Jetons()
{
return lesJetons;
}
/// <summary>
/// Vérifie si le code est complet.
/// </summary>
/// <returns>True si le code est complet, sinon False.</returns>
public bool EstComplet()
{
return NbJetons == lesJetons.Length;
}
/// <summary>
/// Recupère la taille maximal du code.
/// </summary>
/// <returns>Taille maximal du code.</returns>
public int TailleMaximale()
{
return lesJetons.Length;
}
/// <summary>
/// Compare le code avec un autre code et génère des indcateurs de correspondance.
/// </summary>
/// <param name="autreCode">Le code à comparer avec le code actuel</param>
/// <returns>Enumération d'indicateurs de correspondance entre les deux codes.</returns>
public IEnumerable<Indicateur> 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<Jeton?> mesJetons = new List<Jeton?>(Jetons());
List<Jeton?> sesJetons = new List<Jeton?>(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;
}
}

@ -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")
{ }
}
}

@ -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")
{ }
}
}

@ -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")
{ }
}
}

@ -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")
{ }
}
}

@ -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")
{ }
}
}

@ -1,5 +1,8 @@
namespace CoreLibrary
{
/// <summary>
/// Représente les couleurs disponible pour les jetons.
/// </summary>
public enum Couleur
{
ROUGE,

@ -0,0 +1,23 @@

namespace CoreLibrary.Events
{
/// <summary>
/// Représente les arguments d'événement pour l'événement de l'ajout d'un code.
/// </summary>
public class AjouterCodeEventArgs : EventArgs
{
/// <summary>
/// Obtient le code ajouté.
/// </summary>
public Code Code { get; private set; }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="AjouterCodeEventArgs"/> avec le code spécifié.
/// </summary>
/// <param name="code">Le code à ajouter.</param>
public AjouterCodeEventArgs(Code code)
{
Code = code;
}
}
}

@ -0,0 +1,24 @@

namespace CoreLibrary.Events
{
/// <summary>
/// Représente les arguments d'événement pour l'événement d'ajout d'un jeton.
/// </summary>
public class AjouterJetonEventArgs : EventArgs
{
/// <summary>
/// Obtient le jeton ajouté.
/// </summary>
public Jeton Jeton { get; private set; }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="AjouterJetonEventArgs"/> avec le jeton spécifié.
/// </summary>
/// <param name="jeton">Le jeton à ajouter.</param>
public AjouterJetonEventArgs(Jeton jeton)
{
Jeton = jeton;
}
}
}

@ -0,0 +1,22 @@
namespace CoreLibrary.Events
{
/// <summary>
/// Représente les arguments d'événement pour l'événement d'ajout d'un joueur.
/// </summary>
public class AjouterJoueursEventArgs : EventArgs
{
/// <summary>
/// Obtient le joueur ajouté.
/// </summary>
public Joueur Joueur { get; private set; }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="AjouterJoueursEventArgs"/> avec le joueur spécifié.
/// </summary>
/// <param name="joueur">Le joueur à ajouter.</param>
public AjouterJoueursEventArgs(Joueur joueur)
{
Joueur = joueur;
}
}
}

@ -0,0 +1,9 @@
namespace CoreLibrary.Events
{
/// <summary>
/// Représente les arguments d'événement pour le début d'une partie.
/// </summary>
public class DebutPartieEventArgs : EventArgs
{
}
}

@ -0,0 +1,10 @@

namespace CoreLibrary.Events
{
/// <summary>
/// Représente les arguments d'événement pour la demande d'ajout d'un jeton.
/// </summary>
public class DemanderJetonEventArgs : EventArgs
{
}
}

@ -0,0 +1,23 @@
namespace CoreLibrary.Events
{
/// <summary>
/// Représente les arguments d'événement pour la demande d'ajout d'un joueur.
/// </summary>
public class DemanderJoueurEventArgs : EventArgs
{
/// <summary>
/// Obtient le numéro du joueur à ajouter.
/// </summary>
public int Numero { get; private set; }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="DemanderJoueurEventArgs"/> avec le numéro du joueur spécifié.
/// </summary>
/// <param name="numero">Le numéro du joueur à ajouter.</param>
public DemanderJoueurEventArgs(int numero)
{
Numero = numero;
}
}
}

@ -0,0 +1,45 @@
using CoreLibrary.Exceptions;
namespace CoreLibrary.Events
{
/// <summary>
/// Représente les arguments d'événement pour le début d'un nouveau tour.
/// </summary>
public class NouveauTourEventArgs : EventArgs
{
/// <summary>
/// Obtient le joueur dont c'est le tour.
/// </summary>
public Joueur Joueur { get; private set; }
/// <summary>
/// Obtient le numéro du tour.
/// </summary>
public int Tour { get; private set; }
/// <summary>
/// Obtient la grille du joueur actuelle.
/// </summary>
public IEnumerable<IEnumerable<Jeton?>> Grille { get; private set; }
/// <summary>
/// Obtient les indicateurs de la grille de jeu.
/// </summary>
public IEnumerable<IEnumerable<Indicateur>> Indicateurs { get; private set; }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="NouveauTourEventArgs"/> avec les informations spécifiées.
/// </summary>
/// <param name="joueur">Le joueur dont c'est le tour.</param>
/// <param name="tour">Le numéro du tour.</param>
/// <param name="grille">La grille du joueur actuelle.</param>
/// <param name="indicateurs">Les indicateurs de la grille de jeu.</param>
public NouveauTourEventArgs(Joueur joueur, int tour, IEnumerable<IEnumerable<Jeton?>> grille, IEnumerable<IEnumerable<Indicateur>> indicateurs)
{
Joueur = joueur;
Tour = tour;
Grille = grille;
Indicateurs = indicateurs;
}
}
}

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoreLibrary.Events
{
/// <summary>
/// Représente les arguments d'événement pour la fin d'une partie.
/// </summary>
public class PartieTermineeEventArgs : EventArgs
{
/// <summary>
/// Obtient les joueurs gagnants de la partie.
/// </summary>
public IEnumerable<Joueur> Gagnants { get; private set; }
/// <summary>
/// Obtient les joueurs perdants de la partie.
/// </summary>
public IEnumerable<Joueur> Perdants { get; private set; }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="PartieTermineeEventArgs"/> avec les gagnants et les perdants spécifiés.
/// </summary>
/// <param name="gagnants">Les joueurs gagnants de la partie.</param>
/// <param name="perdants">Les joueurs perdants de la partie.</param>
public PartieTermineeEventArgs(IEnumerable<Joueur> gagnants, IEnumerable<Joueur> perdants)
{
Gagnants = gagnants;
Perdants = perdants;
}
}
}

@ -0,0 +1,9 @@
namespace CoreLibrary.Events
{
/// <summary>
/// Représente les arguments d'événement pour le passage de la main au joueur suivant.
/// </summary>
public class PasserMainEventArgs : EventArgs
{
}
}

@ -0,0 +1,9 @@
namespace CoreLibrary.Events
{
/// <summary>
/// Représente les arguments d'événement pour la suppression du dernier jeton ajouté.
/// </summary>
public class SupprimerDernierJetonEventArgs : EventArgs
{
}
}

@ -0,0 +1,34 @@
using System.Runtime.Serialization;
namespace CoreLibrary.Exceptions
{
/// <summary>
/// Exception levée lorsqu'un jeton est ajouté à un code déjà complet.
/// </summary>
[Serializable]
public class CodeCompletException : Exception
{
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="CodeCompletException"/>.
/// </summary>
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);
}
}
}

@ -0,0 +1,34 @@
using System.Runtime.Serialization;
namespace CoreLibrary.Exceptions
{
/// <summary>
/// Exception levée lorsqu'un code incomplet est ajouté à la grille.
/// </summary>
[Serializable]
public class CodeIncompletException : Exception
{
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="CodeIncompletException"/>.
/// </summary>
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);
}
}
}

@ -0,0 +1,40 @@
using System.Runtime.Serialization;
namespace CoreLibrary.Exceptions
{
/// <summary>
/// Exception levée lorsqu'un code avec une taille invalide est ajouté à la grille.
/// </summary>
[Serializable]
public class CodeInvalideException : Exception
{
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="CodeInvalideException"/>.
/// </summary>
/// <param name="tailleCodeAjoute">La taille du code que vous essayez d'ajouter.</param>
/// <param name="tailleCodePlateau">La taille du code que le plateau attend.</param>
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);
}
}
}

@ -0,0 +1,34 @@
using System.Runtime.Serialization;
namespace CoreLibrary.Exceptions
{
/// <summary>
/// Exception levée lorsqu'un jeton est supprimé d'un code qui est déjà vide.
/// </summary>
[Serializable]
public class CodeVideException : Exception
{
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="CodeVideException"/>.
/// </summary>
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);
}
}
}

@ -0,0 +1,34 @@
using System.Runtime.Serialization;
namespace CoreLibrary.Exceptions
{
/// <summary>
/// Exception levée lorsqu'un code est ajouté à une grille qui est déjà complète.
/// </summary>
[Serializable]
public class GrilleCompleteException : Exception
{
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="GrilleCompleteException"/>.
/// </summary>
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);
}
}
}

@ -0,0 +1,40 @@
using System.Runtime.Serialization;
namespace CoreLibrary.Exceptions
{
/// <summary>
/// Exception levée lorsqu'un indice de jeton est invalide.
/// </summary>
[Serializable]
public class IndiceCodeException : Exception
{
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="IndiceCodeException"/>.
/// </summary>
/// <param name="indice">L'indice incorrect qui a été spécifié.</param>
/// <param name="indiceMax">L'indice maximum permis.</param>
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);
}
}
}

@ -0,0 +1,34 @@
using System.Runtime.Serialization;
namespace CoreLibrary.Exceptions
{
/// <summary>
/// Exception levée lorsqu'une opération est tentée alors que la partie n'a pas encore commencé.
/// </summary>
[Serializable]
public class PartieNonCommenceeException : Exception
{
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="PartieNonCommenceeException"/>.
/// </summary>
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);
}
}
}

@ -0,0 +1,39 @@
using System.Runtime.Serialization;
namespace CoreLibrary.Exceptions
{
/// <summary>
/// Exception levée lorsqu'une taille de code invalide est spécifiée.
/// </summary>
[Serializable]
public class TailleCodeException : Exception
{
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="TailleCodeException"/>.
/// </summary>
/// <param name="taille">La taille du code spécifiée.</param>
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);
}
}
}

@ -0,0 +1,39 @@
using System.Runtime.Serialization;
namespace CoreLibrary.Exceptions
{
/// <summary>
/// Exception levée lorsqu'une taille de grille invalide est spécifiée.
/// </summary>
[Serializable]
public class TailleGrilleException : Exception
{
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="TailleGrilleException"/>.
/// </summary>
/// <param name="taille">La taille de grille spécifiée.</param>
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);
}
}
}

@ -1,25 +1,80 @@
namespace CoreLibrary
{
/// <summary>
/// Interface définissant les règles du jeu.
/// </summary>
public interface IRegles
{
/// <summary>
/// Obtient le nom des règles du jeu.
/// </summary>
string Nom { get; }
/// <summary>
/// Obtient le nombre de maximum de tours.
/// </summary>
int TourMaximum { get; }
/// <summary>
/// Obtient la taille maximal du code.
/// </summary>
int TailleCodeMaximum { get; }
/// <summary>
/// Obtient le nombre de joueurs actuels.
/// </summary>
int NbJoueurs { get; }
/// <summary>
/// Obtient le nombre de maximum de joueurs.
/// </summary>
int NbJoueursMaximum { get; }
void AjouterJoueur(string nom);
/// <summary>
/// Ajoute un joueur avec le nom spécifié.
/// </summary>
/// <param name="nom">Nom du joueur à ajouter</param>
/// <returns>Le joueur ajouté.</returns>
Joueur AjouterJoueur(string nom);
/// <summary>
/// Récupère le joueur courant.
/// </summary>
/// <returns>Le joueur courant.</returns>
Joueur JoueurCourant();
/// <summary>
/// Passe la main au joueur suivant.
/// </summary>
void PasserLaMain();
/// <summary>
/// Génère un code selon les règles du jeu.
/// </summary>
/// <returns>Le code généré.</returns>
Code GenererCode();
/// <summary>
/// Initialise le premier joueur à jouer.
/// </summary>
void CommencerLaPartie();
/// <summary>
/// Vérifie si la partie est terminée.
/// </summary>
/// <returns>True si la partie est terminée, sinon False.</returns>
bool EstTerminee();
/// <summary>
/// Récupère les joueurs gagnants.
/// </summary>
/// <returns>Enumération des joueurs gagnants.</returns>
IEnumerable<Joueur> Gagnants();
/// <summary>
/// Récupère les joueurs perdants.
/// </summary>
/// <returns>Enumération des joueurs perdants.</returns>
IEnumerable<Joueur> Perdants();
}
}

@ -1,5 +1,8 @@
namespace CoreLibrary
{
/// <summary>
/// Représente les couleurs disponibles pour les indicateurs.
/// </summary>
public enum Indicateur
{
BONNEPLACE,

@ -1,9 +1,19 @@
namespace CoreLibrary
{
/// <summary>
/// Représente un jetons de couleur.
/// </summary>
public struct Jeton
{
/// <summary>
/// Obtient la couleur du jeton.
/// </summary>
public readonly Couleur Couleur { get; private init; }
/// <summary>
/// Initialise une nouvelle instance de la structure Jeton avec la couleur spécifiée.
/// </summary>
/// <param name="couleur">La couleur du jeton.</param>
public Jeton(Couleur couleur)
{
Couleur = couleur;

@ -1,10 +1,24 @@
namespace CoreLibrary
{
/// <summary>
/// Représente un joueur.
/// </summary>
public class Joueur
{
/// <summary>
/// Obtient le nom du joueur.
/// </summary>
public string Nom { get; private init; }
/// <summary>
/// Obtient le plateau du joueur.
/// </summary>
public Plateau Plateau { get; private init; }
/// <summary>
/// Crée une nouvelle instance de joueur avec un nom et un plateau spécifié.
/// </summary>
/// <param name="nom">Le nom du joueur</param>
/// <param name="plateau">Le plateau du joueur</param>
public Joueur(string nom, Plateau plateau)
{
Nom = nom;

@ -0,0 +1,214 @@
using CoreLibrary.Events;
using CoreLibrary.Exceptions;
namespace CoreLibrary
{
/// <summary>
/// Représente une partie de jeu.
/// </summary>
public class Partie
{
private readonly IRegles regles;
/// <summary>
/// Définit le délégué pour gérer les événements avec des arguments de type string.
/// </summary>
public delegate string? StringEventHandler<in TEventArgs>(Object? sender, TEventArgs e);
/// <summary>
/// Définit le délégué pour gérer les événements avec des arguments de type Jeton.
/// </summary>
public delegate Jeton? JetonEventHandler<in TEventArgs>(Object? sender, TEventArgs e);
/// <summary>
/// Événement déclenché lorsqu'il est nécessaire de d'ajouter un joueur.
/// </summary>
public event StringEventHandler<DemanderJoueurEventArgs>? DemanderJoueur;
/// <summary>
/// Événement déclenché lorsqu'il est nécessaire d'ajouter un jeton.
/// </summary>
public event JetonEventHandler<DemanderJetonEventArgs>? DemanderJeton;
/// <summary>
/// Événement déclenché lorsqu'il est nécessaire d'ajouter un joueur.
/// </summary>
public event EventHandler<AjouterJoueursEventArgs>? AjouterJoueur;
/// <summary>
/// Événement déclenché lorsqu'une partie commence.
/// </summary>
public event EventHandler<DebutPartieEventArgs>? DebutPartie;
/// <summary>
/// Événement déclenché lorsqu'un nouveau tour commence.
/// </summary>
public event EventHandler<NouveauTourEventArgs>? NouveauTour;
/// <summary>
/// Événement déclenché lorsqu'il est nécessaire d'ajouter un jeton.
/// </summary>
public event EventHandler<AjouterJetonEventArgs>? AjouterJeton;
/// <summary>
/// Événement déclenché lorsqu'un jeton est supprimé.
/// </summary>
public event EventHandler<SupprimerDernierJetonEventArgs>? SupprimerDernierJeton;
/// <summary>
/// Événement déclenché lorsqu'un code est ajouté.
/// </summary>
public event EventHandler<AjouterCodeEventArgs>? AjouterCode;
/// <summary>
/// Événement déclenché lorsque la main est passée au joueur suivant.
/// </summary>
public event EventHandler<PasserMainEventArgs>? PasserMain;
/// <summary>
/// Événement déclenché lorsque la partie est terminée.
/// </summary>
public event EventHandler<PartieTermineeEventArgs>? PartieTerminee;
/// <summary>
/// Méthode pour déclencher l'événement de demande d'ajout d'un joueur.
/// </summary>
/// <param name="numero">Le numéro du joueur à ajouter</param>
/// <returns>Le nom du joueur demandé</returns></returns>
private string? QuandDemanderJoueur(int numero) => DemanderJoueur?.Invoke(this, new DemanderJoueurEventArgs(numero));
/// <summary>
/// Méthode pour déclencher l'événement de demande d'ajout d'un jeton.
/// </summary>
/// <returns>Le jeton demandé</returns>
private Jeton? QuandDemanderJeton() => DemanderJeton?.Invoke(this, new DemanderJetonEventArgs());
/// <summary>
/// Méthode pour déclencher l'événement d'ajout d'un joueur.
/// </summary>
/// <param name="joueur">Le joueur à ajouter.</param>
private void QuandAjouterJoueur(Joueur joueur) => AjouterJoueur?.Invoke(this, new AjouterJoueursEventArgs(joueur));
/// <summary>
/// Méthode pour déclencher l'événement du début d'un partie.
/// </summary>
private void QuandDebutPartie() => DebutPartie?.Invoke(this, new DebutPartieEventArgs());
/// <summary>
/// Méthode pour déclencher l'événement d'un nouveau tour.
/// </summary>
/// <param name="joueur">Le joueur dont c'est le tour.</param>
/// <param name="tour">Le numéro du tour.</param>
/// <param name="grille">La grille de jeu.</param>
/// <param name="indicateurs">Les indicateurs de jeu.</param>
private void QuandNouveauTour(Joueur joueur, int tour, IEnumerable<IEnumerable<Jeton?>> grille, IEnumerable<IEnumerable<Indicateur>> indicateurs) => NouveauTour?.Invoke(this, new NouveauTourEventArgs(joueur, tour, grille, indicateurs));
/// <summary>
/// Méthode pour déclencher l'événement d'ajout d'un nouveau jeton.
/// </summary>
/// <param name="jeton">Le jeton à ajouter.</param>
private void QuandNouveauJeton(Jeton jeton) => AjouterJeton?.Invoke(this, new AjouterJetonEventArgs(jeton));
/// <summary>
/// Méthode pour déclencher l'événement de suppression du dernier jeton du code.
/// </summary>
private void QuandSupprimerDernierJeton() => SupprimerDernierJeton?.Invoke(this, new SupprimerDernierJetonEventArgs());
/// <summary>
/// Méthode pour déclencher l'événement d'ajout d'un nouveau code.
/// </summary>
/// <param name="code">Le code à ajouter.</param>
private void QuandNouveauCode(Code code) => AjouterCode?.Invoke(this, new AjouterCodeEventArgs(code));
/// <summary>
/// Méthode pour déclencher l'événement de passage de la main au joueur suivant.
/// </summary>
private void QuandPasserMain() => PasserMain?.Invoke(this, new PasserMainEventArgs());
/// <summary>
/// Méthode pour déclencher l'événement de fin de partie.
/// </summary>
/// <param name="gagnants">La liste des joueurs gagnants.</param>
/// <param name="perdants">La liste des joueurs perdants.</param>
private void QuandPartieTerminee(IEnumerable<Joueur> gagnants, IEnumerable<Joueur> perdants) => PartieTerminee?.Invoke(this, new PartieTermineeEventArgs(gagnants, perdants));
/// <summary>
/// Crée une nouvelle instance de la classe Partie.
/// </summary>
/// <param name="regles">Les règles de la partie.</param>
public Partie(IRegles regles)
{
this.regles = regles;
}
/// <summary>
/// Lance le déroulement de la partie.
/// </summary>
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());
}
}
}

@ -1,28 +1,46 @@
namespace CoreLibrary
using CoreLibrary.Exceptions;
using System.Security.Cryptography;
namespace CoreLibrary
{
/// <summary>
/// Représente un plateau de jeu composer de code
/// </summary>
public class Plateau
{
private static Random random = new Random();
private readonly Code codeSecret;
private readonly Code?[] grille;
private readonly IEnumerable<Indicateur>[] indicateurs;
private readonly int tailleCode;
/// <summary>
/// Obtient le numéro de tour actuel.
/// </summary>
public int Tour { get; private set; } = 1;
/// <summary>
/// Obtient True si le joueur a gagné sinon False
/// </summary>
public bool Victoire { get; private set; } = false;
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="Plateau"/>.
/// </summary>
/// <param name="tailleCode">Taille des codes du plateau</param>
/// <param name="tailleGrille">Taille du plateau de jeu</param>
/// <exception cref="TailleCodeException">Levée lorsque la tailleCode est inférieur ou égal à 0.</exception>
/// <exception cref="TailleGrilleException">Levée lorsque la tailleGrille est inférieur ou égal à 0.</exception>
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();
}
/// <summary>
/// Génère un code secret aléatoire en utilisant des jetons de couleurs aléatoire.
/// </summary>
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)]));
}
}
/// <summary>
/// Vérifie si le plateau de jeu est plein.
/// </summary>
/// <returns>True si la tableau est plein, sinon False.</returns>
public bool EstComplet()
{
return Tour - 1 == grille.Length;
}
/// <summary>
/// Ajoute le code fourni au plateau de jeu.
/// </summary>
/// <param name="code">Le code à ajouter au plateau de jeu.</param>
/// <exception cref="CodeInvalideException">Levée lorsque le code fourni à une taille invalide.</exception>
/// <exception cref="CodeIncompletException">Levée lorsque le code fourni est incomplet.</exception>
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 @@
}
}
/// <summary>
/// Vérifie si le code fourni correspond au code secret.
/// </summary>
/// <param name="code">Le code à vérifier.</param>
/// <returns>True si le code fourni correspond au code secret, sinon False </returns>
/// <exception cref="CodeInvalideException">Levée lorsque le code fourni à une taille invalide.</exception>
/// <exception cref="CodeIncompletException">Levée lorsque le code fourni est incomplet.</exception>
public bool EstBonCode(Code code)
{
IEnumerable<Indicateur> indicateurs = codeSecret.Comparer(code);
if (code.TailleMaximale() != tailleCode)
{
throw new CodeInvalideException(code.TailleMaximale(), tailleCode);
}
if (!code.EstComplet())
{
throw new CodeIncompletException();
}
IEnumerable<Indicateur> 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;
}
/// <summary>
/// Récupère le plateau de jeu.
/// </summary>
/// <returns>Le plateau de jeu représenté sous forme d'une collections de jetons.</returns>
public IEnumerable<IEnumerable<Jeton?>> Grille()
{
IEnumerable<Jeton?>[] grilleJetons = new IEnumerable<Jeton?>[grille.Length];
@ -103,6 +155,10 @@
return grilleJetons;
}
/// <summary>
/// Récupère les indicateurs pour chaque tour.
/// </summary>
/// <returns>Les indicateurs pour chaque tour représentés sous forme d'une collections d'indicateurs.</returns>
public IEnumerable<IEnumerable<Indicateur>> Indicateurs()
{
return indicateurs;

@ -1,8 +0,0 @@
namespace CoreLibrary
{
public class PlateauCodeIncompletException : Exception
{
public PlateauCodeIncompletException() : base("Le code est incomplet")
{ }
}
}

@ -1,7 +0,0 @@
namespace CoreLibrary
{
public class PlateauTailleCodeException : Exception
{
public PlateauTailleCodeException() : base("La taille du code doit être positive non nulle.") { }
}
}

@ -1,7 +0,0 @@
namespace CoreLibrary
{
public class PlateauTailleCodeIncompleteException : Exception
{
public PlateauTailleCodeIncompleteException() : base("Le code n'est pas remplit au maximum") { }
}
}

@ -1,8 +0,0 @@
namespace CoreLibrary
{
public class PlateauTailleGrilleException : Exception
{
public PlateauTailleGrilleException() : base("La taille de la grille doit être égale positive non nulle.")
{ }
}
}

@ -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<Joueur> 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<Joueur> 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
{
/// <summary>
/// Implémente les règles du jeu.
/// </summary>
public class ReglesClassiques : IRegles
{
private int nbJoueurs = 0;
private int? joueurCourant;
private readonly Joueur[] joueurs;
/// <summary>
/// Obtient le nom des règles.
/// </summary>
public string Nom { get => "Règles classiques"; }
/// <summary>
/// Obtient le nombre maximum de tours.
/// </summary>
public int TourMaximum { get => 12; }
/// <summary>
/// Obtient la taille maximale d'un code.
/// </summary>
public int TailleCodeMaximum { get => 4; }
/// <summary>
/// Obtient le nombre de joueurs actuels dans le jeu.
/// </summary>
public int NbJoueurs { get => nbJoueurs; }
/// <summary>
/// Obtient le nombre maximum de joueurs possible pour le jeu.
/// </summary>
public int NbJoueursMaximum { get => 2; }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="ReglesClassiques"/> en initialisant un tableau de joueurs avec la taille maximale de joueurs autorisée.
/// </summary>
public ReglesClassiques()
{
joueurs = new Joueur[NbJoueursMaximum];
}
/// <summary>
/// Ajoute un joueur avec le nom spécifié.
/// </summary>
/// <param name="nom">Le nom du joueur à ajouter.</param>
/// <returns>Le joueur ajouté.</returns>
public Joueur AjouterJoueur(string nom)
{
Joueur joueur = new Joueur(nom, new Plateau(TailleCodeMaximum, TourMaximum));
joueurs[nbJoueurs++] = joueur;
return joueur;
}
/// <summary>
/// Obtient le joueur dont c'est actuellement le tour.
/// </summary>
/// <returns>Le joueur actuel.</returns>
/// <exception cref="PartieNonCommenceeException">Levée lorsqu'il n'y a pas de joueur courant.</exception>
public Joueur JoueurCourant()
{
if (!joueurCourant.HasValue)
throw new PartieNonCommenceeException();
return joueurs[joueurCourant.Value];
}
/// <summary>
/// Passe la main au joueur suivant.
/// </summary>
/// <exception cref="PartieNonCommenceeException">Levée lorsqu'il n'y a pas de joueur courant.</exception>
public void PasserLaMain()
{
if (!joueurCourant.HasValue)
{
throw new PartieNonCommenceeException();
}
joueurCourant++;
if (joueurCourant >= joueurs.Length)
{
joueurCourant = 0;
}
}
/// <summary>
/// Génère un nouveau code.
/// </summary>
/// <returns>Le code généré</returns>
public Code GenererCode()
{
return new Code(TailleCodeMaximum);
}
/// <summary>
/// Initialise le premier joueur à jouer.
/// </summary>
public void CommencerLaPartie()
{
joueurCourant = 0;
}
/// <summary>
/// Vérifie si la partie est terminée.
/// </summary>
/// <returns>True si la partie est terminée, sinon False.</returns>
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;
}
/// <summary>
/// Obtient les joueurs gagnants de la partie.
/// </summary>
/// <returns>La liste des joueurs gagnants.</returns>
public IEnumerable<Joueur> Gagnants()
{
Joueur[] gagnants = [];
for (int i = 0; i < joueurs.Length; ++i)
{
if (joueurs[i].Plateau.Victoire)
{
gagnants = gagnants.Append(joueurs[i]).ToArray();
}
}
return gagnants;
}
/// <summary>
/// Obtient les joueurs perdants de la partie.
/// </summary>
/// <returns>La liste des joueurs perdants.</returns>
public IEnumerable<Joueur> Perdants()
{
Joueur[] perdants = [];
for (int i = 0; i < joueurs.Length; ++i)
{
if (!joueurs[i].Plateau.Victoire)
{
perdants = perdants.Append(joueurs[i]).ToArray();
}
}
return perdants;
}
}
}

@ -1,8 +0,0 @@
namespace CoreLibrary
{
public class ReglesClassiquesJoueurCourantNull : Exception
{
public ReglesClassiquesJoueurCourantNull() : base("Le joueur courant est null")
{ }
}
}
Loading…
Cancel
Save