Nouvelle architecture du core et console
continuous-integration/drone/push Build is failing Details

master
Céleste BARBOSA 11 months ago
parent d336cb4e92
commit f4466b4731

@ -1,4 +1,4 @@
using CoreLibrary.Events;
using CoreLibrary.Evenements;
using CoreLibrary.Joueurs;
using CoreLibrary.Core;
using System.Diagnostics.CodeAnalysis;
@ -17,7 +17,7 @@ namespace ConsoleApp
/// <param name="e">L'instance de l'événement DemanderNomEventArgs créée par Partie.</param>
/// <returns>Le nom du joueur.</returns>
/// </summary>
public static void DemanderNom(Object? sender, DemanderJoueurEventArgs e)
public static void DemanderNom(Object? sender, PartieDemanderJoueurEventArgs e)
{
Console.WriteLine($"Joueur {e.Indice}");
Console.Write(">>> ");
@ -26,7 +26,7 @@ namespace ConsoleApp
Console.WriteLine();
e.JoueurBuilder.Nom(nom);
e.JoueurDemande.SeConnecter(!string.IsNullOrEmpty(nom) ? Program.Manageur.DemanderJoueur(nom) : new Joueur($"Joueur {e.Indice}"));
}
@ -35,7 +35,7 @@ namespace ConsoleApp
/// <param name="sender">La classe qui appelle l'événement; ici Partie.</param>
/// <param name="e">L'instance de l'événement DebutPartieEventArgs créée par Partie.</param>
/// </summary>
public static void CommencerLaPartie(Object? sender, DebutPartieEventArgs e)
public static void CommencerLaPartie(Object? sender, PartieDebutPartieEventArgs e)
{
Utils.DessinerSeparateur();
@ -47,20 +47,21 @@ namespace ConsoleApp
/// <param name="sender">La classe qui appelle l'événement; ici Partie.</param>
/// <param name="e">L'instance de l'événement NouveauTourEventArgs créée par Partie.</param>
/// </summary>
public static void NouveauTour(Object? sender, NouveauTourEventArgs e)
public static void NouveauTour(Object? sender, PartieNouveauTourEventArgs e)
{
Utils.DessinerSeparateur();
Console.WriteLine($"Tour {e.Tour} - {e.Joueur.Nom}\n");
Utils.DessinerPlateau(e.Grille, e.Indicateurs);
(IReadOnlyList<IReadOnlyList<Jeton>> codes, IReadOnlyList<IReadOnlyList<Indicateur>> indicateurs) = e.Plateau.Grille;
Utils.DessinerPlateau(e.Plateau);
Console.WriteLine();
Code code = e.Code;
while(!code.EstComplet())
while(!code.Complet)
{
Jeton? jeton = Utils.SaisirJeton(code.NbJetons);
Jeton? jeton = Utils.SaisirJeton(code.Taille);
if (jeton.HasValue)
{
Utils.DessinerPion(jeton.Value.Couleur);
@ -73,7 +74,7 @@ namespace ConsoleApp
}
}
e.Joueur.Code(code);
e.Plateau.AjouterCode(code);
}
/// <summary>
@ -81,7 +82,7 @@ namespace ConsoleApp
/// <param name="sender">La classe qui appelle l'événement; ici Partie.</param>
/// <param name="e">L'instance de l'événement AjouterCodeEventArgs créée par Partie.</param>
/// </summary>
public static void AjouterCode(Object? sender, AjouterCodeEventArgs e)
public static void AjouterCode(Object? sender, PartiePasserLaMainEventArgs e)
{
Console.WriteLine();
@ -93,7 +94,7 @@ namespace ConsoleApp
/// <param name="sender">La classe qui appelle l'événement; ici Partie.</param>
/// <param name="e">L'instance de l'événement PartieTermineeEventArgs créée par Partie.</param>
/// </summary>
public static void PartieTerminee(Object? sender, PartieTermineeEventArgs e)
public static void PartieTerminee(Object? sender, PartiePartieTermineeEventArgs e)
{
Joueur[] gagnants = e.Gagnants.ToArray();

@ -1,5 +1,7 @@
using CoreLibrary;
using CoreLibrary.Manageurs;
using CoreLibrary.Persistance;
using CoreLibrary.Regles;
using CoreLibrary;
using System.Diagnostics.CodeAnalysis;
namespace ConsoleApp
@ -11,17 +13,19 @@ namespace ConsoleApp
[ExcludeFromCodeCoverage]
public static class Program
{
public static Manageur Manageur { get; private set; } = new Manageur(new PersistanceJSON());
public static void Main()
{
Utils.DessinerTitre();
Partie maPartie = new Partie(new ReglesClassiques());
Partie maPartie = Manageur.NouvellePartie(new ReglesClassiques());
maPartie.DemanderNom += Evenements.DemanderNom;
maPartie.DebutPartie += Evenements.CommencerLaPartie;
maPartie.NouveauTour += Evenements.NouveauTour;
maPartie.AjouterCode += Evenements.AjouterCode;
maPartie.PartieTerminee += Evenements.PartieTerminee;
maPartie.PartieDemanderJoueur += Evenements.DemanderNom;
maPartie.PartieDebutPartie += Evenements.CommencerLaPartie;
maPartie.PartieNouveauTour += Evenements.NouveauTour;
maPartie.PartiePasserLaMain += Evenements.AjouterCode;
maPartie.PartiePartieTerminee += Evenements.PartieTerminee;
maPartie.Jouer();
}

@ -12,18 +12,18 @@ namespace ConsoleApp
// 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 }
{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 }
{Indicateur.BonnePlace, ConsoleColor.Black },
{Indicateur.BonneCouleur, ConsoleColor.White }
};
/// <summary>
@ -72,7 +72,7 @@ namespace ConsoleApp
Console.BackgroundColor = Console.ForegroundColor.Equals(ConsoleColor.Black) ? ConsoleColor.White : ConsoleColor.Black;
Console.OutputEncoding = System.Text.Encoding.UTF8;
Console.Write("O");
Console.Write('O');
Console.ResetColor();
@ -83,59 +83,54 @@ namespace ConsoleApp
/// 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)
private static void DessinerLigne<T>(int taille, IEnumerable<T> ligne) where T : Enum
{
foreach(Enum pion in ligne)
Console.Write(" ");
foreach (Enum pion in ligne)
DessinerPion(pion);
// Ajoute des espaces s'il y a moins de 4 pions à dessiner
Console.Write("".PadLeft((4 - ligne.Length) * 3));
// Ajoute des espaces s'il y a moins de taille pions à dessiner
Console.Write("".PadLeft((taille - ligne.Count()) * 3 + 1));
}
/// <summary>
/// Dessine un plateau de jeu dans la console, affichant les codes et leurs 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)
/// <param name="plateau">Le plateau de jeu.</param>
public static void DessinerPlateau(Plateau plateau)
{
IEnumerable<Jeton?>[] grilleTableau = grille.ToArray();
IEnumerable<Indicateur>[] indicateursTableau = indicateurs.ToArray();
(IReadOnlyList<IReadOnlyList<Jeton>> codes, IReadOnlyList<IReadOnlyList<Indicateur>> indicateurs) = plateau.Grille;
int tailleGrille = 2 + plateau.TailleMaxCode * 3;
Console.WriteLine(" Codes Indicateurs ");
Console.WriteLine("──────────────── ────────────────");
Console.WriteLine("│ │ │ │");
Console.WriteLine($"─{new string('─', tailleGrille)}─ ─{new string('─', tailleGrille)}─");
Console.WriteLine($"│{new string(' ', tailleGrille)}│ │{new string(' ', tailleGrille)}│");
for (int i = 0; i < grille.Count(); ++i)
for (int i = 0; i < plateau.TailleMax; ++i)
{
Console.Write("│ ");
if(i >= codes.Count)
{
Console.WriteLine($"│{new string(' ', tailleGrille)}│ │{new string(' ', tailleGrille)}│");
continue;
}
DessinerLigne(
grilleTableau[i]
.Where(jeton => jeton.HasValue)
.Select(jeton => (Enum)jeton!.Value.Couleur)
.ToArray()
);
IReadOnlyList<Jeton> ligneCodes = codes.ElementAt(i);
IReadOnlyList<Indicateur> ligneIndicateurs = indicateurs.ElementAt(i);
Console.Write(" ");
Console.Write("│");
if (indicateursTableau[i] == null)
{
indicateursTableau[i] = [];
}
DessinerLigne(plateau.TailleMaxCode, ligneCodes.Select(jeton => jeton.Couleur));
DessinerLigne(
indicateursTableau[i]
.Select(indicateur => (Enum)indicateur)
.ToArray()
);
Console.Write("│ │");
Console.WriteLine(" │");
}
DessinerLigne(plateau.TailleMaxCode, ligneIndicateurs);
Console.WriteLine("│");
}
Console.WriteLine("│ │ │ │");
Console.WriteLine("──────────────── ────────────────");
Console.WriteLine($"│{new string(' ', tailleGrille)}│ │{new string(' ', tailleGrille)}│");
Console.WriteLine($"─{new string('─', tailleGrille)}─ ─{new string('─', tailleGrille)}─");
}
/// <summary>

@ -1,166 +1,84 @@
using CoreLibrary.Exceptions;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
namespace CoreLibrary.Core
{
/// <summary>
/// Classe représentant un code composé de jetons et ses différentes méthodes.
/// </summary>
[DataContract]
public class Code
{
private readonly ObservableCollection<Jeton?> lesJetons = new ObservableCollection<Jeton?>();
/// <summary>
/// Le nombre maximum de jetons dans le code.
/// </summary>
[DataMember]
public int NbJetonsMax { get; private set; }
private readonly List<Jeton> jetons = new List<Jeton>();
/// <summary>
/// Le nombre de jetons dans le code.
/// </summary>
public IReadOnlyList<Jeton> Jetons => jetons;
public int Taille => jetons.Count;
[DataMember]
public int NbJetons { get => lesJetons.Count; }
public int TailleMax { get; private init; }
public bool Complet => Taille == TailleMax;
public bool Vide => Taille == 0;
[DataMember]
public ObservableCollection<Jeton?> Jetons => lesJetons;
/// <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)
public Code(int taille)
{
NbJetonsMax = tailleCode;
if (taille < 0)
throw new TailleCodeException(taille);
if (tailleCode <= 0)
{
throw new TailleCodeException(tailleCode);
}
TailleMax = taille;
}
/// <summary>
/// Initialise une nouvelle instance de la classe <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 TailleCodeException(jetons.Count());
}
NbJetonsMax = 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 (lesJetons.Count == NbJetonsMax)
{
if (Complet)
throw new CodeCompletException();
}
lesJetons.Add(jeton);
jetons.Add(jeton);
}
/// <summary>
/// Supprime le dernier jeton ajouté au code.
/// </summary>
/// <exception cref="CodeVideException">Levée lorsque le code est vide.</exception>
public void SupprimerDernierJeton()
public Jeton RecupererJeton(int indice)
{
if (lesJetons.Count == 0)
{
throw new CodeVideException();
}
if (indice < 0 || indice >= Taille)
throw new IndiceCodeException(indice, Taille - 1);
lesJetons.RemoveAt(lesJetons.Count - 1);
return jetons.ElementAt(indice);
}
/// <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)
public void SupprimerDernierJeton()
{
if (indice < 0 || indice >= lesJetons.Count)
throw new IndiceCodeException(indice, lesJetons.Count - 1);
Jeton? jeton = lesJetons[indice];
if (!jeton.HasValue)
throw new IndiceCodeException(indice, lesJetons.Count - 1);
if (Vide)
throw new CodeVideException();
return jeton.Value;
jetons.RemoveAt(Taille - 1);
}
/// <summary>
/// Vérifie si le code est complet.
/// </summary>
/// <returns>True si le code est complet, sinon False.</returns>
public bool EstComplet()
public IReadOnlyList<Indicateur> Comparer(Code code)
{
return lesJetons.Count == NbJetonsMax;
}
// Je suis le bon code
/// <summary>
/// Compare le code avec un autre code et génère des indicateurs.
/// </summary>
/// <param name="autreCode">Le code à comparer avec le code actuel.</param>
/// <returns>Les indicateurs de bonne place et bonne couleur entre les deux codes.</returns>
public IEnumerable<Indicateur> Comparer(Code autreCode)
{
// Mon code est le code correct, l'autre code est celui qui teste
List<Indicateur> indicateurs = new List<Indicateur>();
Indicateur[] indicateurs = [];
if (!code.Complet)
throw new CodeIncompletException();
if (!autreCode.EstComplet())
return indicateurs;
if (code.TailleMax != TailleMax)
throw new CodeInvalideException();
List<Jeton?> mesJetons = new List<Jeton?>(Jetons);
List<Jeton?> sesJetons = new List<Jeton?>(autreCode.Jetons);
List<Jeton> mesJetons = Jetons.ToList();
List<Jeton> sesJetons = code.Jetons.ToList();
for (int i = 0; i < mesJetons.Count; ++i)
{
Jeton? monJeton = mesJetons[i];
Jeton? sonJeton = sesJetons[i];
if (monJeton.HasValue && sonJeton.HasValue && monJeton.Value.Couleur.Equals(sonJeton.Value.Couleur))
if (mesJetons[i] == sesJetons[i])
{
indicateurs = indicateurs.Append(Indicateur.BONNEPLACE).ToArray();
mesJetons[i] = null;
sesJetons[i] = null;
mesJetons.RemoveAt(i);
sesJetons.RemoveAt(i);
indicateurs.Add(Indicateur.BonnePlace);
}
}
for (int i = 0; i < sesJetons.Count; ++i)
{
Jeton? sonJeton = sesJetons[i];
if (sonJeton.HasValue && mesJetons.Contains(sonJeton.Value))
if (mesJetons.Remove(sesJetons[i]))
{
indicateurs = indicateurs.Append(Indicateur.BONNECOULEUR).ToArray();
mesJetons[mesJetons.IndexOf(sonJeton)] = null;
sesJetons[i] = null;
sesJetons.RemoveAt(i);
indicateurs.Add(Indicateur.BonneCouleur);
}
}
@ -168,5 +86,3 @@ namespace CoreLibrary.Core
}
}
}

@ -1,15 +1,12 @@
namespace CoreLibrary.Core
{
/// <summary>
/// Enumération des couleurs disponibles pour les jetons.
/// </summary>
public enum Couleur
{
ROUGE,
VERT,
BLEU,
JAUNE,
BLANC,
NOIR
Rouge,
Vert,
Bleu,
Jaune,
Noir,
Blanc
}
}

@ -1,14 +1,8 @@
using System.Runtime.Serialization;
namespace CoreLibrary.Core
namespace CoreLibrary.Core
{
/// <summary>
/// Enumération des indicateurs disponibles pour les jetons.
/// </summary>
[DataContract]
public enum Indicateur
{
BONNEPLACE,
BONNECOULEUR
BonnePlace,
BonneCouleur
}
}

@ -2,25 +2,29 @@
namespace CoreLibrary.Core
{
/// <summary>
/// Structure représentant un jeton de couleur
/// </summary>
[DataContract]
public struct Jeton
public readonly struct Jeton
{
/// <summary>
/// La couleur du jeton.
/// </summary>
[DataMember]
public readonly Couleur Couleur { get; private init; }
public 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;
}
public override readonly bool Equals(object? objet)
{
if (objet == null || objet is not Jeton)
return false;
return Couleur == ((Jeton)objet).Couleur;
}
public static bool operator ==(Jeton gauche, Jeton droite) => gauche.Equals(droite);
public static bool operator !=(Jeton gauche, Jeton droite) => gauche.Equals(droite);
public override readonly int GetHashCode() => Couleur.GetHashCode();
}
}

@ -1,175 +1,82 @@
using CoreLibrary.Exceptions;
using CoreLibrary.Evenements;
using System.Runtime.Serialization;
using System.Security.Cryptography;
namespace CoreLibrary.Core
{
/// <summary>
/// Classe représentant un plateau de jeu composé de codes et leurs indicateurs ainsi que les méthodes associées.
/// </summary>
[DataContract]
public class Plateau
{
public event EventHandler<PlateauAjouterCodeEventArgs>? PlateauAjouterCode;
private void QuandPlateauAjouterCode() => PlateauAjouterCode?.Invoke(this, new PlateauAjouterCodeEventArgs(this));
[DataMember]
private readonly Code codeSecret;
[DataMember]
private readonly Code?[] grille;
private readonly List<Code> codes = new List<Code>();
[DataMember]
private readonly IEnumerable<Indicateur>[] indicateurs;
private readonly List<List<Indicateur>> indicateurs = new List<List<Indicateur>>();
public int Taille => codes.Count;
[DataMember]
private readonly int tailleCode;
/// <summary>
/// Le numéro de tour actuel.
/// </summary>
public int TailleMax { get; private init; }
[DataMember]
public int Tour { get; private set; } = 1;
/// <summary>
/// La victoire du joueur, True si le joueur a gagné sinon False
/// </summary>
public int TailleMaxCode { get; private init; }
public bool Complet => Taille == TailleMax;
[DataMember]
public bool Victoire { get; private set; } = false;
public (IReadOnlyList<IReadOnlyList<Jeton>>, IReadOnlyList<IReadOnlyList<Indicateur>>) Grille => (
codes.Select(code => code.Jetons).ToList(),
indicateurs
);
/// <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érieure ou égale à 0.</exception>
/// <exception cref="TailleGrilleException">Levée lorsque la tailleGrille est inférieure ou égale à 0.</exception>
public Plateau(int tailleCode, int tailleGrille)
public Plateau(int tailleCode, int taillePlateau)
{
if (tailleCode <= 0)
{
if (tailleCode < 0)
throw new TailleCodeException(tailleCode);
}
if (tailleGrille <= 0)
{
throw new TailleGrilleException(tailleGrille);
}
codeSecret = new Code(tailleCode);
grille = new Code?[tailleGrille];
indicateurs = new IEnumerable<Indicateur>[tailleGrille];
if (taillePlateau < 0)
throw new TailleGrilleException(taillePlateau);
this.tailleCode = tailleCode;
TailleMax = taillePlateau;
TailleMaxCode = tailleCode;
GenererCodeAleatoire();
codeSecret = GenererCodeSecret();
}
/// <summary>
/// Génère un code secret aléatoire en utilisant des jetons de couleurs aléatoires.
/// </summary>
private void GenererCodeAleatoire()
private Code GenererCodeSecret()
{
Couleur[] couleurs = (Couleur[])Enum.GetValues(typeof(Couleur));
Code code = new Code(TailleMaxCode);
Couleur[] couleurs = Enum.GetValues<Couleur>();
for (int i = 0; i < tailleCode; ++i)
while (!code.Complet)
{
codeSecret.AjouterJeton(new Jeton(couleurs[RandomNumberGenerator.GetInt32(0, couleurs.Length)]));
code.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;
return code;
}
/// <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.NbJetonsMax != tailleCode)
{
throw new CodeInvalideException(code.NbJetonsMax, tailleCode);
}
if (!code.EstComplet())
{
if (!code.Complet)
throw new CodeIncompletException();
}
indicateurs[Tour - 1] = codeSecret.Comparer(code);
grille[Tour - 1] = code;
++Tour;
if (Complet)
throw new GrilleCompleteException();
if (EstBonCode(code))
{
Victoire = true;
}
}
codes.Add(code);
IReadOnlyList<Indicateur> indicateurs = codeSecret.Comparer(code);
this.indicateurs.Add(indicateurs.ToList());
/// <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)
{
if (code.NbJetonsMax != tailleCode)
{
throw new CodeInvalideException(code.NbJetonsMax, tailleCode);
}
if (!code.EstComplet())
{
throw new CodeIncompletException();
}
IEnumerable<Indicateur> indicateursCode = codeSecret.Comparer(code);
if (indicateursCode.Count() != tailleCode)
{
return false;
}
foreach (Indicateur indicateur in indicateursCode)
{
if (indicateur != Indicateur.BONNEPLACE)
{
return false;
}
}
return true;
}
/// <summary>
/// Récupère le plateau de jeu.
/// </summary>
/// <returns>Le plateau de jeu représenté sous forme d'un tableau de tableau de jetons.</returns>
public IEnumerable<IEnumerable<Jeton?>> Grille()
{
IEnumerable<Jeton?>[] grilleJetons = new IEnumerable<Jeton?>[grille.Length];
for (int i = 0; i < grille.Length; ++i)
{
grilleJetons[i] = grille[i]?.Jetons ?? new Code(tailleCode).Jetons;
}
return grilleJetons;
}
if (!Victoire && indicateurs.Count(indicateur => indicateur == Indicateur.BonnePlace) == TailleMaxCode)
Victoire = true;
/// <summary>
/// Récupère les indicateurs pour chaque tour.
/// </summary>
/// <returns>Les indicateurs pour chaque tour représentés sous forme d'un tableau de tableau d'indicateurs.</returns>
public IEnumerable<IEnumerable<Indicateur>> Indicateurs()
{
return indicateurs;
QuandPlateauAjouterCode();
}
}
}

@ -0,0 +1,6 @@
namespace CoreLibrary.Evenements
{
public class JoueurJoueCodeEventArgs : EventArgs
{
}
}

@ -0,0 +1,14 @@
using CoreLibrary.Joueurs;
namespace CoreLibrary.Evenements
{
public class JoueurSeConnecterEventArgs : EventArgs
{
public Joueur JoueurConnecte { get; private init; }
public JoueurSeConnecterEventArgs(Joueur joueurConnecte)
{
JoueurConnecte = joueurConnecte;
}
}
}

@ -0,0 +1,6 @@
namespace CoreLibrary.Evenements
{
public class PartieDebutPartieEventArgs : EventArgs
{
}
}

@ -0,0 +1,16 @@
using CoreLibrary.Joueurs;
namespace CoreLibrary.Evenements
{
public class PartieDemanderJoueurEventArgs : EventArgs
{
public int Indice { get; private init; }
public Joueur JoueurDemande { get; private init; }
public PartieDemanderJoueurEventArgs(int indice, Joueur joueurDemande)
{
Indice = indice;
JoueurDemande = joueurDemande;
}
}
}

@ -0,0 +1,21 @@
using CoreLibrary.Core;
using CoreLibrary.Joueurs;
namespace CoreLibrary.Evenements
{
public class PartieNouveauTourEventArgs : EventArgs
{
public int Tour { get; private init; }
public Joueur Joueur { get; private init; }
public Plateau Plateau { get; private init; }
public Code Code { get; private init; }
public PartieNouveauTourEventArgs(int tour, Joueur joueur, Plateau plateau, Code code)
{
Tour = tour;
Joueur = joueur;
Plateau = plateau;
Code = code;
}
}
}

@ -0,0 +1,16 @@
using CoreLibrary.Joueurs;
namespace CoreLibrary.Evenements
{
public class PartiePartieTermineeEventArgs : EventArgs
{
public IReadOnlyList<Joueur> Gagnants { get; private init; }
public IReadOnlyList<Joueur> Perdants { get; private init; }
public PartiePartieTermineeEventArgs(IReadOnlyList<Joueur> gagnants, IReadOnlyList<Joueur> perdants)
{
Gagnants = gagnants;
Perdants = perdants;
}
}
}

@ -0,0 +1,15 @@
using CoreLibrary.Joueurs;
namespace CoreLibrary.Evenements
{
public class PartiePasserLaMainEventArgs
{
public Joueur Joueur { get; private init; }
public PartiePasserLaMainEventArgs(Joueur joueur)
{
Joueur = joueur;
}
}
}

@ -0,0 +1,14 @@
using CoreLibrary.Core;
namespace CoreLibrary.Evenements
{
public class PlateauAjouterCodeEventArgs : EventArgs
{
public Plateau Plateau { get; private init; }
public PlateauAjouterCodeEventArgs(Plateau plateau)
{
Plateau = plateau;
}
}
}

@ -1,24 +0,0 @@
using CoreLibrary.Core;
namespace CoreLibrary.Events
{
/// <summary>
/// Classe contenant les arguments passées en paramètre lors de l'événement AjouterCode.
/// </summary>
public class AjouterCodeEventArgs : EventArgs
{
/// <summary>
/// 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 qui a été ajouté.</param>
public AjouterCodeEventArgs(Code code)
{
Code = code;
}
}
}

@ -1,24 +0,0 @@
using CoreLibrary.Joueurs;
namespace CoreLibrary.Events
{
/// <summary>
/// Classe contenant les arguments passées en paramètre lors de l'événement AjouterJoueur.
/// </summary>
public class AjouterJoueurEventArgs : EventArgs
{
/// <summary>
/// Le joueur ajouté.
/// </summary>
public Joueur Joueur { get; private set; }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="AjouterJoueurEventArgs"/> avec le joueur spécifié.
/// </summary>
/// <param name="joueur">Le joueur qui a été ajouté.</param>
public AjouterJoueurEventArgs(Joueur joueur)
{
Joueur = joueur;
}
}
}

@ -1,24 +0,0 @@
using CoreLibrary.Joueurs;
namespace CoreLibrary.Events
{
/// <summary>
/// Classe contenant les arguments passées en paramètre lors de l'événement ConstruireJoueurEventArgs.
/// </summary>
public class ConstruireJoueurEventArgs : EventArgs
{
/// <summary>
/// Le joueur à ajouter.
/// </summary>
public Joueur Joueur { get; private set; }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="ConstruireJoueurEventArgs"/> avec les informations spécifiées.
/// </summary>
/// <param name="joueur">Le joueur à ajouter.</param>
public ConstruireJoueurEventArgs(Joueur joueur)
{
Joueur = joueur;
}
}
}

@ -1,9 +0,0 @@
namespace CoreLibrary.Events
{
// <summary>
/// Classe contenant les arguments passées en paramètre lors de l'événement DebutPartie
/// </summary>
public class DebutPartieEventArgs : EventArgs
{
}
}

@ -1,31 +0,0 @@
using CoreLibrary.Joueurs;
namespace CoreLibrary.Events
{
/// <summary>
/// Classe contenant les arguments passées en paramètre lors de l'événement DemanderNom.
/// </summary>
public class DemanderNomEventArgs : EventArgs
{
/// <summary>
/// L'indice du joueur
/// </summary>
public int Indice { get; private set; }
/// <summary>
/// Le constructeur de joueur dans lequel il faut renseigner le nom du joueur
/// </summary>
public JoueurBuilder JoueurBuilder { get; private set; }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="DemanderNomEventArgs"/> avec les informations spécifiées.
/// </summary>
/// <param name="code">L'indice du joueur.</param>
/// <param name="code">La classe dans laquelle on attend la réponse du joueur.</param>
public DemanderNomEventArgs(int indice, JoueurBuilder joueurBuilder)
{
Indice = indice;
JoueurBuilder = joueurBuilder;
}
}
}

@ -1,24 +0,0 @@
using CoreLibrary.Core;
namespace CoreLibrary.Events
{
/// <summary>
/// Classe contenant les arguments passées en paramètre lors de l'événement JouerCode.
/// </summary>
public class JouerCodeEventArgs : EventArgs
{
/// <summary>
/// Le code joué par le joueur
/// </summary>
public Code Code { get; private set; }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="JouerCodeEventArgs"/> avec les informations spécifiées.
/// </summary>
/// <param name="code">Le code joué par le joueur dont c'est le tour.</param>
public JouerCodeEventArgs(Code code)
{
Code = code;
}
}
}

@ -1,22 +0,0 @@
namespace CoreLibrary.Events
{
/// <summary>
/// Classe contenant les arguments passées en paramètre lors de l'événement NouveauJoueur.
/// </summary>
public class NouveauJoueurEventArgs : EventArgs
{
/// <summary>
/// Le nom du joueur
/// </summary>
public string Nom { get; private set; }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="NouveauJoueurEventArgs"/> avec les informations spécifiées.
/// </summary>
/// <param name="nom">Le nom du joueur.</param>
public NouveauJoueurEventArgs(string nom)
{
Nom = nom;
}
}
}

@ -1,53 +0,0 @@
using CoreLibrary.Core;
using CoreLibrary.Joueurs;
namespace CoreLibrary.Events
{
/// <summary>
/// Classe contenant les arguments passées en paramètre lors de l'événement NouveauTour.
/// </summary>
public class NouveauTourEventArgs : EventArgs
{
/// <summary>
/// Le joueur dont c'est le tour.
/// </summary>
public Joueur Joueur { get; private set; }
/// <summary>
/// Le numéro du tour.
/// </summary>
public int Tour { get; private set; }
/// <summary>
/// Le code où ajouter les jetons
/// </summary>
public Code Code { get; private set; }
/// <summary>
/// La grille du joueur actuelle.
/// </summary>
public IEnumerable<IEnumerable<Jeton?>> Grille { get; private set; }
/// <summary>
/// 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, Code code, IEnumerable<IEnumerable<Jeton?>> grille, IEnumerable<IEnumerable<Indicateur>> indicateurs)
{
Joueur = joueur;
Tour = tour;
Code = code;
Grille = grille;
Indicateurs = indicateurs;
}
}
}

@ -1,31 +0,0 @@
using CoreLibrary.Joueurs;
namespace CoreLibrary.Events
{
/// <summary>
/// Classe contenant les arguments passées en paramètre lors de l'événement PartieTerminee.
/// </summary>
public class PartieTermineeEventArgs : EventArgs
{
/// <summary>
/// Les joueurs gagnants de la partie.
/// </summary>
public Joueur[] Gagnants { get; private set; }
/// <summary>
/// Les joueurs perdants de la partie.
/// </summary>
public 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 gagnants.</param>
/// <param name="perdants">Les perdants.</param>
public PartieTermineeEventArgs(Joueur[] gagnants, Joueur[] perdants)
{
Gagnants = gagnants;
Perdants = perdants;
}
}
}

@ -1,9 +0,0 @@
namespace CoreLibrary.Events
{
/// <summary>
/// Classe contenant les arguments passées en paramètre lors de l'événement PasserMain.
/// </summary>
public class PasserMainEventArgs : EventArgs
{
}
}

@ -0,0 +1,49 @@
using CoreLibrary.Joueurs;
using System.Runtime.Serialization;
namespace CoreLibrary.Exceptions
{
/// <summary>
/// Exception levée lorsqu'un joueur se connecte alors qu'il l'est déjà.
/// </summary>
[Serializable]
public class JoueurDejaConnecteException : Exception
{
// Message par défaut
private const string messageDefaut = "Le joueur est déjà connecté.";
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="JoueurDejaConnecteException"/> avec le message par défaut.
/// </summary>
public JoueurDejaConnecteException() : base(messageDefaut)
{}
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="JoueurDejaConnecteException"/> avec le message spécifié.
/// </summary>
public JoueurDejaConnecteException(string message) : base(message)
{}
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="JoueurDejaConnecteException"/> avec le joueur spécifié.
/// </summary>
public JoueurDejaConnecteException(Joueur joueur) : base($"Le joueur {joueur.Nom} est déjà connecté.")
{ }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="JoueurDejaConnecteException"/> avec le message et l'exception parent spécifiés.
/// </summary>
public JoueurDejaConnecteException(string message, Exception exception) : base(message, exception)
{}
[Obsolete("This method is obsolete. Use alternative methods for data retrieval.", DiagnosticId = "SYSLIB0051")]
protected JoueurDejaConnecteException(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,41 +0,0 @@
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
{
// Message par défaut
private const string messageDefaut = "La partie n'a pas encore commencée.";
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="PartieNonCommenceeException"/> avec le message par défaut.
/// </summary>
public PartieNonCommenceeException() : base(messageDefaut)
{ }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="PartieNonCommenceeException"/> avec le message spécifié.
/// </summary>
public PartieNonCommenceeException(string message) : base(message)
{ }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="PartieNonCommenceeException"/> avec le message et l'exception parent spécifiés.
/// </summary>
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);
}
}
}

@ -1,77 +1,55 @@
using CoreLibrary.Core;
using CoreLibrary.Events;
using CoreLibrary.Exceptions;
using CoreLibrary.Persistance;
using CoreLibrary.Evenements;
using CoreLibrary.Regles;
using CoreLibrary.Statistiques;
using System.Runtime.Serialization;
namespace CoreLibrary.Joueurs
{
/// <summary>
/// Classe représentant un joueur.
/// </summary>
[DataContract]
[KnownType(typeof(ReglesClassiques))]
public class Joueur : IEstPersistant
{
/// <summary>
/// Le nom du joueur.
/// </summary>
[DataMember]
public string Nom { get; private init; }
[DataMember]
public int NbCoutTotal { get; set; }
public event EventHandler<JoueurSeConnecterEventArgs>? JoueurSeConnecter;
private void QuandJoueurSeConnecter() => JoueurSeConnecter?.Invoke(this, new JoueurSeConnecterEventArgs(this));
[DataMember]
public int NbPartieGagnee { get; set; }
private Dictionary<(IRegles, Statistique), int> statistiques = new Dictionary<(IRegles, Statistique), int>();
[DataMember]
public int NbPartieEgalite { get; set; }
public string Nom { get; private set; } = "";
[DataMember]
public int NbPartiePerdue { get; set; }
/// <summary>
/// Crée une nouvelle instance de joueur avec un nom
/// Evénement appelé pour jouer un code.
/// </summary>
public event EventHandler<JouerCodeEventArgs>? JouerCode;
/// <summary>
/// Appel de l'événement JouerCode.
/// </summary>
private void QuandJouerCode(Code code) => JouerCode?.Invoke(this, new JouerCodeEventArgs(code));
public bool EstConnecte { get; private set; } = false;
/// <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>
public Joueur(string nom)
public Joueur()
{
Nom = nom;
NbCoutTotal = 0;
NbPartieGagnee = 0;
NbPartieEgalite = 0;
NbPartiePerdue = 0;
}
public Joueur(string nom, int nbCoutTotal, int nbPartieGagnee, int nbPartieEgalite, int nbPartiePerdue)
public Joueur(string nom)
{
Nom = nom;
NbCoutTotal = nbCoutTotal;
NbPartieGagnee = nbPartieGagnee;
NbPartieEgalite = nbPartieEgalite;
NbPartiePerdue = nbPartiePerdue;
}
public void Code(Code code)
public Joueur SeConnecter(Joueur joueur)
{
++NbCoutTotal;
QuandJouerCode(code);
}
if (EstConnecte)
throw new JoueurDejaConnecteException(this);
public void AGagne() => ++NbPartieGagnee;
public void APerdu() => ++NbPartiePerdue;
public void AEgalite() => ++NbPartieEgalite;
Nom = joueur.Nom;
statistiques = joueur.statistiques;
EstConnecte = true;
QuandJoueurSeConnecter();
public override String ToString()
{
return Nom;
return this;
}
public int Statistique(IRegles regles, Statistique statistique) =>
statistiques.GetValueOrDefault((regles, statistique), 0);
public void IncrementerStatistique(IRegles regles, Statistique statistique) =>
statistiques[(regles, statistique)] = Statistique(regles, statistique) + 1;
}
}

@ -1,16 +0,0 @@
using CoreLibrary.Events;
namespace CoreLibrary.Joueurs
{
public class JoueurBuilder
{
public event EventHandler<ConstruireJoueurEventArgs>? ConstruireJoueur;
private void QuandConstruireJoueur(Joueur joueur) => ConstruireJoueur?.Invoke(this, new ConstruireJoueurEventArgs(joueur));
public void Joueur(Joueur joueur)
{
QuandConstruireJoueur(joueur);
}
}
}

@ -1,57 +0,0 @@
using CoreLibrary.Events;
using CoreLibrary.Joueurs;
using CoreLibrary.Persistance;
using System.Collections.Generic;
namespace CoreLibrary.Manager
{
public class Manageur
{
private readonly List<Joueur> joueurs;
private readonly List<Partie> parties;
private readonly IPersistance persistance;
private Partie? partie;
public IReadOnlyCollection<Joueur> Joueurs => joueurs;
public IReadOnlyCollection<Partie> Parties => parties;
public Partie? Partie => partie;
public Manageur(IPersistance persistance)
{
this.persistance = persistance;
joueurs = persistance.Charger<Joueur>().ToList();
parties = persistance.Charger<Partie>().ToList();
}
public void NouvellePartie(Partie partie)
{
this.partie = partie;
parties.Add(partie);
partie.PasserMain += (object? sender, PasserMainEventArgs e) =>
{
persistance.Enregistrer<Partie>(parties.ToArray());
persistance.Enregistrer<Joueur>(joueurs.ToArray());
};
partie.PartieTerminee += (object? sender, PartieTermineeEventArgs e) =>
{
persistance.Enregistrer<Partie>(parties.ToArray());
persistance.Enregistrer<Joueur>(joueurs.ToArray());
};
}
public Joueur DemanderJoueur(string nom)
{
foreach (Joueur joueur in joueurs)
{
if (joueur.Nom == nom)
return joueur;
}
Joueur nouveauJoueur = new Joueur(nom);
joueurs.Add(nouveauJoueur);
return nouveauJoueur;
}
}
}

@ -0,0 +1,76 @@
using CoreLibrary.Persistance;
using CoreLibrary.Joueurs;
using CoreLibrary.Regles;
using CoreLibrary.Statistiques;
namespace CoreLibrary.Manageurs
{
public class Manageur
{
private readonly IPersistance persistance;
private readonly List<Joueur> joueurs;
private readonly List<Partie> parties;
public Manageur(IPersistance persistance)
{
this.persistance = persistance;
joueurs = persistance.Charger<Joueur>().ToList();
parties = persistance.Charger<Partie>().ToList();
}
private void Sauvegarder()
{
persistance.Enregistrer(joueurs.ToArray());
persistance.Enregistrer(parties.ToArray());
}
public Partie NouvellePartie(IRegles regles)
{
Partie partie = new Partie(regles);
parties.Add(partie);
partie.PartiePasserLaMain += (sender, e) => e.Joueur.IncrementerStatistique(partie.Regles, Statistique.CoupJoue);
partie.PartieNouveauTour += (sender, e) => Sauvegarder();
partie.PartiePartieTerminee += (sender, e) =>
{
if (e.Gagnants.Count == 1)
{
e.Gagnants[0].IncrementerStatistique(regles, Statistique.PartieGagnee);
}
else
{
foreach (Joueur gagnant in e.Gagnants)
gagnant.IncrementerStatistique(regles, Statistique.PartieEgalite);
}
foreach (Joueur perdant in e.Perdants)
{
perdant.IncrementerStatistique(regles, Statistique.PartiePerdue);
}
};
return partie;
}
public Joueur DemanderJoueur(string nom)
{
foreach (Joueur joueur in joueurs)
{
if (joueur.Nom == nom)
{
return joueur;
}
}
Joueur nouveauJoueur = new Joueur(nom);
joueurs.Add(nouveauJoueur);
return nouveauJoueur;
}
}
}

@ -1,217 +1,118 @@
using CoreLibrary.Core;
using CoreLibrary.Events;
using CoreLibrary.Persistance;
using CoreLibrary.Core;
using CoreLibrary.Evenements;
using CoreLibrary.Joueurs;
using CoreLibrary.Persistance;
using CoreLibrary.Regles;
using System.Runtime.Serialization;
namespace CoreLibrary
{
/// <summary>
/// Représente une partie de jeu.
/// </summary>
[DataContract]
[KnownType(typeof(ReglesClassiques))]
public class Partie : IEstPersistant
{
[DataMember]
public IRegles Regles { get; private set; }
public event EventHandler<PartieDemanderJoueurEventArgs>? PartieDemanderJoueur;
public event EventHandler<PartieDebutPartieEventArgs>? PartieDebutPartie;
public event EventHandler<PartieNouveauTourEventArgs>? PartieNouveauTour;
public event EventHandler<PartiePasserLaMainEventArgs>? PartiePasserLaMain;
public event EventHandler<PartiePartieTermineeEventArgs>? PartiePartieTerminee;
private void QuandPartieDemanderJoueur(Joueur joueurDemande) => PartieDemanderJoueur?.Invoke(this, new PartieDemanderJoueurEventArgs(joueurs.Count + 1, joueurDemande));
private void QuandPartieDebutPartie() => PartieDebutPartie?.Invoke(this, new PartieDebutPartieEventArgs());
private void QuandPartieNouveauTour() => PartieNouveauTour?.Invoke(this, new PartieNouveauTourEventArgs(plateaux.ElementAt(courant).Taille + 1, joueurs.ElementAt(courant), plateaux.ElementAt(courant), new Code(Regles.TailleCode)));
private void QuandPartiePasserLaMain() => PartiePasserLaMain?.Invoke(this, new PartiePasserLaMainEventArgs(joueurs.ElementAt(courant)));
private void QuandPartiePartieTerminee(IReadOnlyList<Joueur> gagnants, IReadOnlyList<Joueur> perdants) => PartiePartieTerminee?.Invoke(this, new PartiePartieTermineeEventArgs(gagnants, perdants));
[DataMember]
private readonly List<Joueur> joueurs = new List<Joueur>();
[DataMember]
private readonly List<Plateau> plateaux = new List<Plateau>();
[DataMember]
private int? courant;
/// <summary>
/// Événement déclenché lorsqu'il est nécessaire de d'ajouter un joueur.
/// </summary>
public event EventHandler<DemanderNomEventArgs>? DemanderNom;
/// <summary>
/// Événement déclenché lorsqu'il est nécessaire d'ajouter un joueur.
/// </summary>
public event EventHandler<AjouterJoueurEventArgs>? 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'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 du nom d'un joueur.
/// </summary>
/// <param name="numero">Le numéro du joueur à ajouter</param>
/// <param name="joueurBuilder">La classe dans laquelle le nom doit être défini</param>
private void QuandDemanderNom(int numero, JoueurBuilder joueurBuilder) => DemanderNom?.Invoke(this, new DemanderNomEventArgs(numero, joueurBuilder));
/// <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 AjouterJoueurEventArgs(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="code">Le code dans lequel il faut ajouter les jetons.</param>
/// <param name="grille">La grille de jeu.</param>
/// <param name="indicateurs">Les indicateurs de jeu.</param>
private void QuandNouveauTour(Joueur joueur, int tour, Code code, IEnumerable<IEnumerable<Jeton?>> grille, IEnumerable<IEnumerable<Indicateur>> indicateurs) => NouveauTour?.Invoke(this, new NouveauTourEventArgs(joueur, tour, code, grille, indicateurs));
/// <summary>
/// Méthode pour déclencher l'événement d'ajout d'un nouveau code.
/// </summary>
/// <param name="code">Le code ajouté.</param>
private void QuandAjouterCode(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(Joueur[] gagnants, 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>
/// <param name="persistance">Persistance de la partie.</param>
private int courant = 0;
[DataMember]
public IRegles Regles { get; private init; }
public Partie(IRegles regles)
{
Regles = regles;
}
/// <summary>
/// Lance le déroulement de la partie.
/// </summary>
public void Jouer()
{
JoueurBuilder joueurBuilder = new JoueurBuilder();
joueurBuilder.ConstruireJoueur += Joueur;
DemanderJoueur();
}
private void DemanderJoueur()
{
Joueur joueurDemande = new Joueur();
joueurDemande.JoueurSeConnecter += JoueurConnecte;
QuandDemanderNom(joueurs.Count + 1, joueurBuilder);
QuandPartieDemanderJoueur(joueurDemande);
}
/// <summary>
/// Un joueur a saisi son nom
/// </summary>
private void Joueur(Object? sender, ConstruireJoueurEventArgs e)
private void JoueurConnecte(object? sender, JoueurSeConnecterEventArgs e)
{
Joueur joueur = e.Joueur;
Plateau plateau = new Plateau(Regles.TailleCodeMaximum, Regles.TourMaximum);
Plateau plateau = new Plateau(Regles.TailleCode, Regles.NbTour);
plateau.PlateauAjouterCode += PlateauAjouterCode;
joueurs.Add(joueur);
joueurs.Add(e.JoueurConnecte);
plateaux.Add(plateau);
QuandAjouterJoueur(joueur);
joueur.JouerCode += Tour;
if (joueurs.Count != Regles.NbJoueursMaximum)
if (joueurs.Count < Regles.NbJoueurs)
{
JoueurBuilder joueurBuilder = new JoueurBuilder();
joueurBuilder.ConstruireJoueur += Joueur;
QuandDemanderNom(joueurs.Count + 1, joueurBuilder);
DemanderJoueur();
}
else
{
Commencer();
DebutPartie();
}
}
/// <summary>
/// La partie démarre
/// </summary>
private void Commencer()
private void DebutPartie()
{
courant = 0;
Joueur joueurCourant = joueurs[courant.Value];
Plateau plateauCourant = plateaux[courant.Value];
QuandDebutPartie();
QuandNouveauTour(joueurCourant, plateauCourant.Tour, new Code(Regles.TailleCodeMaximum), plateauCourant.Grille(), plateauCourant.Indicateurs());
QuandPartieDebutPartie();
NouveauTour();
}
/// <summary>
/// Un joueur a joué son tour
/// </summary>
private void Tour(Object? sender, JouerCodeEventArgs e)
private void NouveauTour()
{
Plateau plateauCourant = plateaux[courant!.Value];
plateauCourant.AjouterCode(e.Code);
QuandAjouterCode(e.Code);
QuandPartieNouveauTour();
}
if (++courant == joueurs.Count)
courant = 0;
QuandPasserMain();
private void PlateauAjouterCode(object? sender, PlateauAjouterCodeEventArgs e)
{
QuandPartiePasserLaMain();
if (courant == 0 && (plateauCourant.Tour > Regles.TourMaximum || plateaux.Where(plateau => plateau.Victoire).Any()))
if (courant + 1 == joueurs.Count && (e.Plateau.Complet || plateaux.Any(plateau => plateau.Victoire)))
{
Terminee();
PartieTerminee();
}
else
{
Joueur joueurCourant = joueurs[courant!.Value];
plateauCourant = plateaux[courant!.Value];
QuandNouveauTour(joueurCourant, plateauCourant.Tour, new Code(Regles.TailleCodeMaximum), plateauCourant.Grille(), plateauCourant.Indicateurs());
if (courant + 1 == joueurs.Count)
courant = 0;
else
++courant;
NouveauTour();
}
}
/// <summary>
/// La partie est terminée
/// </summary>
private void Terminee()
private void PartieTerminee()
{
foreach(Joueur joueur in joueurs)
{
joueur.JouerCode -= Tour;
}
List<Joueur> gagnants = new List<Joueur>();
List<Joueur> perdants = new List<Joueur>();
for (int i = 0; i < joueurs.Count; i++)
for (int i = 0; i < joueurs.Count; ++i)
{
if (plateaux[i].Victoire)
if (plateaux.ElementAt(i).Victoire)
gagnants.Add(joueurs[i]);
else
perdants.Add(joueurs[i]);
}
QuandPartieTerminee(gagnants.ToArray(), perdants.ToArray());
QuandPartiePartieTerminee(gagnants, perdants);
}
}
}

@ -1,6 +1,4 @@
 using CoreLibrary.Joueurs;
namespace CoreLibrary.Persistance
namespace CoreLibrary.Persistance
{
public interface IPersistance
{

@ -6,17 +6,19 @@ namespace CoreLibrary.Persistance
{
public class PersistanceJSON : IPersistance
{
private readonly string dossier = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../..");
private readonly string nomDossier = "Fichiers";
public T[] Charger<T>() where T : IEstPersistant
{
string fichier = $"{typeof(T).Name.ToLower()}s.json";
Directory.SetCurrentDirectory(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../../../../.."));
Directory.SetCurrentDirectory(dossier);
if (!Directory.Exists("Fichiers"))
if (!Directory.Exists(nomDossier))
return [];
Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "Fichiers"));
Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), nomDossier));
if (!File.Exists(fichier))
return [];
@ -36,18 +38,18 @@ namespace CoreLibrary.Persistance
{
string fichier = $"{typeof(T).Name.ToLower()}s.json";
Directory.SetCurrentDirectory(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../../../../.."));
Directory.SetCurrentDirectory(dossier);
if (!Directory.Exists("Fichiers"))
Directory.CreateDirectory("Fichiers");
if (!Directory.Exists(nomDossier))
Directory.CreateDirectory(nomDossier);
Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "Fichiers"));
Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), nomDossier));
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(T[]));
using(FileStream s = File.Create(fichier))
using (FileStream s = File.Create(fichier))
{
using(XmlDictionaryWriter writer = JsonReaderWriterFactory.CreateJsonWriter(
using (XmlDictionaryWriter writer = JsonReaderWriterFactory.CreateJsonWriter(
s,
Encoding.UTF8,
false,

@ -1,31 +1,10 @@

using System.Runtime.Serialization;
namespace CoreLibrary.Regles
namespace CoreLibrary.Regles
{
/// <summary>
/// Interface définissant les règles du jeu.
/// </summary>
public interface IRegles
{
/// <summary>
/// Le nom des règles du jeu.
/// </summary>
string Nom { get; }
/// <summary>
/// Le nombre de maximum de tours.
/// </summary>
int TourMaximum { get; }
/// <summary>
/// La taille maximal du code.
/// </summary>
int TailleCodeMaximum { get; }
/// <summary>
/// Le nombre maximum de joueurs.
/// </summary>
int NbJoueursMaximum { get; }
int NbJoueurs { get; }
int NbTour { get; }
int TailleCode { get; }
}
}

@ -2,34 +2,12 @@
namespace CoreLibrary.Regles
{
/// <summary>
/// Classe définissant les règles classiques du jeu.
/// </summary>
[DataContract]
public class ReglesClassiques : IRegles
{
/// <summary>
/// Le nom des règles.
/// </summary>
[DataMember]
public string Nom { get => "Règles classiques"; }
/// <summary>
/// Le nombre maximum de tour.
/// </summary>
[DataMember]
public int TourMaximum { get => 12; }
/// <summary>
/// La taille maximale d'un code.
/// </summary>
[DataMember]
public int TailleCodeMaximum { get => 4; }
/// <summary>
/// Me nombre maximum de joueurs possibles pour le jeu.
/// </summary>
[DataMember]
public int NbJoueursMaximum { get => 2; }
public string Nom => "Règles classiques";
public int NbJoueurs => 2;
public int NbTour => 12;
public int TailleCode => 4;
}
}

@ -0,0 +1,10 @@
namespace CoreLibrary.Statistiques
{
public enum Statistique
{
PartieGagnee,
PartiePerdue,
PartieEgalite,
CoupJoue
}
}

@ -14,8 +14,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTesting", "UnitTesting\
{341FB405-085D-4C34-B395-64EF0F9B93E0} = {341FB405-085D-4C34-B395-64EF0F9B93E0}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp1", "ConsoleApp1\ConsoleApp1.csproj", "{69A6F940-1A25-4FC0-83E3-ABEFA4003DD6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -40,10 +38,6 @@ Global
{A2182054-C0D1-46D6-BD39-F3F7926CE2DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A2182054-C0D1-46D6-BD39-F3F7926CE2DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A2182054-C0D1-46D6-BD39-F3F7926CE2DD}.Release|Any CPU.Build.0 = Release|Any CPU
{69A6F940-1A25-4FC0-83E3-ABEFA4003DD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{69A6F940-1A25-4FC0-83E3-ABEFA4003DD6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{69A6F940-1A25-4FC0-83E3-ABEFA4003DD6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69A6F940-1A25-4FC0-83E3-ABEFA4003DD6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Loading…
Cancel
Save