fusion avec les nouvelles documentations

master
Céleste BARBOSA 11 months ago
commit f1fe5281e6

@ -5,17 +5,44 @@ 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
{
/// <summary>
/// Collection observable de jetons.
/// </summary>
[DataMember]
public ObservableCollection<Jeton> Jetons { get; private init; } = new ObservableCollection<Jeton>();
/// <summary>
/// Obtient le nombre actuel de jetons dans le code.
/// </summary>
public int Taille => Jetons.Count;
/// <summary>
/// Taille maximale de jetons autorisée pour le code.
/// </summary>
[DataMember]
public int TailleMax { get; private init; }
/// <summary>
/// Indique si le code est complet.
/// </summary>
public bool Complet => Taille == TailleMax;
/// <summary>
/// Indique si le code est vide.
/// </summary>
public bool Vide => Taille == 0;
/// <summary>
/// Constructeur de code avec une taille maximale spécifiée.
/// </summary>
/// <param name="taille">La taille maximale de jetons autorisée pour le code.</param>
/// <exception cref="TailleCodeException">Exception lancée si la taille spécifiée est négative ou nulle.</exception>
public Code(int taille)
{
if (taille < 0)
@ -24,6 +51,11 @@ namespace CoreLibrary.Core
TailleMax = taille;
}
/// <summary>
/// Ajoute un jeton au code.
/// </summary>
/// <param name="jeton">Le jeton à ajouter.</param>
/// <exception cref="CodeCompletException">Lancée si le code est déjà complet.</exception>
public void AjouterJeton(Jeton jeton)
{
if (Complet)
@ -32,6 +64,12 @@ namespace CoreLibrary.Core
Jetons.Add(jeton);
}
/// <summary>
/// Récupère le jeton à l'indice spécifié.
/// </summary>
/// <param name="indice">L'indice du jeton à récupérer.</param>
/// <returns>Renvoie le jeton à l'indice spécifié.</returns>
/// <exception cref="IndiceCodeException">Lancée si l'indice est en dehors des limites de la collection de jetons.</exception>
public Jeton RecupererJeton(int indice)
{
if (indice < 0 || indice >= Taille)
@ -40,6 +78,10 @@ namespace CoreLibrary.Core
return Jetons.ElementAt(indice);
}
/// <summary>
/// Supprime le dernier jeton du code.
/// </summary>
/// <exception cref="CodeVideException">Lancée si le code est vide.</exception>
public void SupprimerDernierJeton()
{
if (Vide)
@ -48,6 +90,13 @@ namespace CoreLibrary.Core
Jetons.RemoveAt(Taille - 1);
}
/// <summary>
/// Compare le code avec le code secret et retourne une liste d'indicateurs.
/// </summary>
/// <param name="code">Le code à comparer.</param>
/// <returns>Renvoie une liste d'indicateurs représentant les résultats de la comparaison.</returns>
/// <exception cref="CodeIncompletException">Lancée si le code n'est pas complet.</exception>
/// <exception cref="CodeInvalideException">Lancée si le code est invalide.</exception>
public IReadOnlyList<Indicateur> Comparer(Code code)
{
// Je suis le bon code
@ -86,6 +135,10 @@ namespace CoreLibrary.Core
return indicateurs;
}
/// <summary>
/// Retourne la taille du code sous forme de chaîne de caractères.
/// </summary>
/// <returns>Renvoie une chaîne de caractères représentant la taille du code.</returns>
public override string ToString() => $"Code({Taille})";
}
}

@ -1,5 +1,8 @@
namespace CoreLibrary.Core
{
/// <summary>
/// Enumération des différentes couleurs possibles pour un jeton.
/// </summary>
public enum Couleur
{
Rouge,

@ -1,5 +1,8 @@
namespace CoreLibrary.Core
{
/// <summary>
/// Enumération des indicateurs de comparaison entre deux codes.
/// </summary>
public enum Indicateur
{
BonnePlace,

@ -2,18 +2,33 @@
namespace CoreLibrary.Core
{
/// <summary>
/// Structure représentant un jeton de couleur.
/// </summary>
[DataContract]
public readonly struct Jeton
{
/// <summary>
/// Obtient la couleur du jeton.
/// </summary>
[DataMember]
public Couleur Couleur { get; private init; }
/// <summary>
/// Constructeur d'un jeton avec une 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? obj)
/// <summary>
/// Détermine si l'objet spécifié est égal à l'objet actuel.
/// </summary>
/// <param name="objet">L'objet à comparer avec l'objet actuel.</param>
/// <returns>Renvoie true si l'objet spécifié est égal à l'objet actuel. Sinon, false.</returns>
public override readonly bool Equals(object? objet)
{
if (obj is not Jeton)
return false;
@ -21,10 +36,26 @@ namespace CoreLibrary.Core
return Couleur == ((Jeton)obj).Couleur;
}
/// <summary>
/// Détermine si deux jetons sont égaux.
/// </summary>
/// <param name="gauche">Le premier jeton à comparer.</param>
/// <param name="droite">Le deuxième jeton à comparer.</param>
/// <returns>Renvoie true si les deux jetons sont égaux. Sinon, false.</returns>
public static bool operator ==(Jeton gauche, Jeton droite) => gauche.Equals(droite);
/// <summary>
/// Détermine si deux jetons ne sont pas égaux.
/// </summary>
/// <param name="gauche">Le premier jeton à comparer.</param>
/// <param name="droite">Le deuxième jeton à comparer.</param>
/// <returns>Renvoie true si les deux jetons ne sont pas égaux. Sinon, false.</returns>
public static bool operator !=(Jeton gauche, Jeton droite) => gauche.Equals(droite);
/// <summary>
/// Fonction de hachage.
/// </summary>
/// <returns>Renvoie un code de hachage pour une couleur.</returns>
public override readonly int GetHashCode() => Couleur.GetHashCode();
}
}

@ -5,33 +5,79 @@ using System.Security.Cryptography;
namespace CoreLibrary.Core
{
/// <summary>
/// Classe représentant le plateau de jeu contenant les codes et les indicateurs.
/// </summary>
[DataContract]
public class Plateau
{
/// <summary>
/// Événement déclenché lorsqu'un code est ajouté au plateau.
/// </summary>
public event EventHandler<PlateauAjouterCodeEventArgs>? PlateauAjouterCode;
private void QuandPlateauAjouterCode() => PlateauAjouterCode?.Invoke(this, new PlateauAjouterCodeEventArgs(this));
/// <summary>
/// Le code secret à deviner.
/// </summary>
[DataMember]
private readonly Code codeSecret;
/// <summary>
/// Liste des codes ajoutés au plateau.
/// </summary>
[DataMember]
private readonly List<Code> codes = new List<Code>();
/// <summary>
/// Liste des listes d'indicateurs pour chaque code ajouté.
/// </summary>
[DataMember]
private readonly List<List<Indicateur>> indicateurs = new List<List<Indicateur>>();
/// <summary>
/// Obtient le nombre de codes sur le plateau.
/// </summary>
public int Taille => codes.Count;
/// <summary>
/// Obtient la taille maximale de codes autorisée sur le plateau.
/// </summary>
[DataMember]
public int TailleMax { get; private init; }
/// <summary>
/// Obtient la taille maximale d'un code.
/// </summary>
[DataMember]
public int TailleMaxCode { get; private init; }
/// <summary>
/// Indique si le plateau à atteint sa taille maximale.
/// </summary>
public bool Complet => Taille == TailleMax;
/// <summary>
/// Indique si la victoire est atteinte.
/// </summary>
[DataMember]
public bool Victoire { get; private set; } = false;
/// <summary>
/// Obtient la grille des codes et des indicateurs.
/// </summary>
public (IEnumerable<IEnumerable<Jeton>>, IEnumerable<IEnumerable<Indicateur>>) Grille => (
codes.Select(code => code.Jetons),
indicateurs
);
/// <summary>
/// Constructeur de plateau avec une taille de code et une taille de plateau spécifiées.
/// </summary>
/// <param name="tailleCode">La taille maximale d'un code.</param>
/// <param name="taillePlateau">La taille maximale du plateau.</param>
/// <exception cref="TailleCodeException">Lancée si la taille du code est négative ou nulle.</exception>
/// <exception cref="TailleGrilleException">Lancée si la taille du plateau spécifiée est négative ou nulle.</exception>
public Plateau(int tailleCode, int taillePlateau)
{
if (tailleCode < 0)
@ -46,6 +92,10 @@ namespace CoreLibrary.Core
codeSecret = GenererCodeSecret();
}
/// <summary>
/// Génère un code secret aléatoire.
/// </summary>
/// <returns>Renvoie le code secret généré.</returns>
private Code GenererCodeSecret()
{
Code code = new Code(TailleMaxCode);
@ -61,6 +111,12 @@ namespace CoreLibrary.Core
return code;
}
/// <summary>
/// Ajoute un code au plateau et compare avec le code secret.
/// </summary>
/// <param name="code">Le code à ajouter.</param>
/// <exception cref="CodeIncompletException">Lancée si le code à ajouter n'est pas complet.</exception>
/// <exception cref="GrilleCompleteException">Lancée si le plateau est déjà complet.</exception>
public void AjouterCode(Code code)
{
if (!code.Complet)

@ -0,0 +1,9 @@
namespace CoreLibrary.Evenements
{
/// <summary>
/// Classe correspondant à l'événement JoueurJoueCode.
/// </summary>
public class JoueurJoueCodeEventArgs : EventArgs
{
}
}

@ -2,10 +2,20 @@
namespace CoreLibrary.Evenements
{
/// <summary>
/// Classe contenant les arguments passés en paramètres lors de l'événement JoueurSeConnecter.
/// </summary>
public class JoueurSeConnecterEventArgs : EventArgs
{
/// <summary>
/// Obtient le joueur qui s'est connecté.
/// </summary>
public Joueur Joueur { get; private init; }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="JoueurSeConnecterEventArgs"/>.
/// </summary>
/// <param name="joueur">Le joueur qui s'est connecté.</param>
public JoueurSeConnecterEventArgs(Joueur joueur)
{
Joueur = joueur;

@ -1,5 +1,8 @@
namespace CoreLibrary.Evenements
{
/// <summary>
/// Classe correspondant à l'événement PartieDebutPartie.
/// </summary>
public class PartieDebutPartieEventArgs : EventArgs
{
}

@ -2,11 +2,27 @@
namespace CoreLibrary.Evenements
{
/// <summary>
/// Classe contenant les arguments passés en paramètres lors de l'événement PartieDemanderJoueur.
/// </summary>
/// <param name="">.</param>
public class PartieDemanderJoueurEventArgs : EventArgs
{
/// <summary>
/// Entier correspondant à l'indice du joueur.
/// </summary>
public int Indice { get; private init; }
/// <summary>
/// Le joueur qui est demandé.
/// </summary>
public Joueur JoueurDemande { get; private init; }
/// <summary>
/// Constructeur de PartieDemanderJoueurEventArgs, avec l'indice du joueur et le joueur demandé spécifiés.
/// </summary>
/// <param name="indice">Indice du joueur demandé.</param>
/// <param name="joueurDemande">Le joueur demandé.</param>
public PartieDemanderJoueurEventArgs(int indice, Joueur joueurDemande)
{
Indice = indice;

@ -2,14 +2,44 @@
namespace CoreLibrary.Evenements
{
/// <summary>
/// Classe contenant les arguments passés en paramètres lors de l'événement PartieDemanderJoueurJouer.
/// </summary>
public class PartieDemanderJoueurJouerEventArgs : EventArgs
{
/// <summary>
/// Obtient le numéro du tour.
/// </summary>
public int Tour { get; private init; }
/// <summary>
/// Obtient le nom du joueur.
/// </summary>
public string Nom { get; private init; }
/// <summary>
/// Obtient le plateau actuel.
/// </summary>
public Plateau Plateau { get; private init; }
/// <summary>
/// Obtient le code en cours.
/// </summary>
public Code Code { get; private init; }
/// <summary>
/// Indique si le joueur est un joueur humain.
/// </summary>
public bool EstJoueur { get; private init; }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="PartieDemanderJoueurJouerEventArgs"/>.
/// </summary>
/// <param name="tour">Le numéro du tour.</param>
/// <param name="nom">Le nom du joueur.</param>
/// <param name="plateau">Le plateau actuel.</param>
/// <param name="code">Le code en cours.</param>
/// <param name="estJoueur">Indique si le joueur est un joueur humain.</param>
public PartieDemanderJoueurJouerEventArgs(int tour, string nom, Plateau plateau, Code code, bool estJoueur)
{
Tour = tour;

@ -1,22 +1,52 @@
using CoreLibrary.Core;
namespace CoreLibrary.Evenements
{
public class PartieNouveauTourEventArgs : EventArgs
{
public int Tour { get; private init; }
public string Nom { get; private init; }
public Plateau Plateau { get; private init; }
public Code Code { get; private init; }
public bool EstJoueur { get; private init; }
public PartieNouveauTourEventArgs(int tour, string nom, Plateau plateau, Code code, bool estJoueur)
{
Tour = tour;
Nom = nom;
Plateau = plateau;
Code = code;
EstJoueur = estJoueur;
}
}
}
using CoreLibrary.Core;
namespace CoreLibrary.Evenements
{
/// <summary>
/// Classe contenant les arguments passés en paramètres lors de l'événement PartieNouveauTour.
/// </summary>
public class PartieNouveauTourEventArgs : EventArgs
{
/// <summary>
/// Obtient le numéro du tour.
/// </summary>
public int Tour { get; private init; }
/// <summary>
/// Obtient le nom du joueur.
/// </summary>
public string Nom { get; private init; }
/// <summary>
/// Obtient le plateau actuel.
/// </summary>
public Plateau Plateau { get; private init; }
/// <summary>
/// Obtient le code en cours.
/// </summary>
public Code Code { get; private init; }
/// <summary>
/// Indique si le joueur est un joueur humain.
/// </summary>
public bool EstJoueur { get; private init; }
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="PartieNouveauTourEventArgs"/>.
/// </summary>
/// <param name="tour">Le numéro du tour.</param>
/// <param name="nom">Le nom du joueur.</param>
/// <param name="plateau">Le plateau actuel.</param>
/// <param name="code">Le code en cours.</param>
/// <param name="estJoueur">Indique si le joueur est un joueur humain.</param>
public PartieNouveauTourEventArgs(int tour, string nom, Plateau plateau, Code code, bool estJoueur)
{
Tour = tour;
Nom = nom;
Plateau = plateau;
Code = code;
EstJoueur = estJoueur;
}
}
}

@ -2,11 +2,26 @@
namespace CoreLibrary.Evenements
{
/// <summary>
/// Classe contenant les arguments passés en paramètre lors de l'événement PartiePartieTerminee.
/// </summary>
public class PartiePartieTermineeEventArgs : EventArgs
{
/// <summary>
/// Liste des gagnants.
/// </summary>
public IReadOnlyList<string> Gagnants { get; private init; }
/// <summary>
/// Liste des perdants.
/// </summary>
public IReadOnlyList<string> Perdants { get; private init; }
/// <summary>
/// Constructeur de PartiePartieTermineeEventArgs, avec la liste des gagnants et perdants spécifiés.
/// </summary>
/// <param name="gagnants">Liste des gagnants.</param>
/// <param name="perdants">Liste des perdants.</param>
public PartiePartieTermineeEventArgs(IReadOnlyList<string> gagnants, IReadOnlyList<string> perdants)
{
Gagnants = gagnants;

@ -1,9 +1,19 @@
namespace CoreLibrary.Evenements
{
/// <summary>
/// Classe contenant les arguments passés en paramètre, lors de l'événement PartiePasserLaMain.
/// </summary>
public class PartiePasserLaMainEventArgs
{
/// <summary>
/// Chaîne de caractère pour le joueur courant.
/// </summary>
public string Joueur { get; private init; }
/// <summary>
/// Constructeur de PartiePasserLaMainEventArgs, avec le joueur spécifié.
/// </summary>
/// <param name="joueur">Chaîne de caractères représentant le joueur courant que nous souhaitons obtenir.</param>
public PartiePasserLaMainEventArgs(string joueur)
{
Joueur = joueur;

@ -2,10 +2,20 @@
namespace CoreLibrary.Evenements
{
/// <summary>
/// Classe contenant les arguments passés en paramètre lors de l'événement PlateauAjouterCode.
/// </summary>
public class PlateauAjouterCodeEventArgs : EventArgs
{
/// <summary>
/// Le plateau où nous souhaitons ajouté le code.
/// </summary>
public Plateau Plateau { get; private init; }
/// <summary>
/// Constructeur de PlateauAjouterCodeEventArgs, avec le plateau spécifié.
/// </summary>
/// <param name="plateau">Le plateau que nous souhaitons avoir.</param>
public PlateauAjouterCodeEventArgs(Plateau plateau)
{
Plateau = plateau;

@ -8,11 +8,17 @@ using CoreLibrary.Core;
namespace CoreLibrary.Joueurs
{
/// <summary>
/// Représente un joueur.
/// </summary>
[DataContract]
[KnownType(typeof(ReglesClassiques))]
[KnownType(typeof(ReglesDifficiles))]
public class Joueur : IEstPersistant
{
/// <summary>
/// Événement déclenché lorsqu'un joueur se connecte.
/// </summary>
public event EventHandler<JoueurSeConnecterEventArgs>? JoueurSeConnecter;
private void QuandJoueurSeConnecter(Joueur joueur) => JoueurSeConnecter?.Invoke(this, new JoueurSeConnecterEventArgs(joueur));
@ -20,19 +26,37 @@ namespace CoreLibrary.Joueurs
[DataMember]
private Dictionary<(IRegles, Statistique), int> statistiques = new Dictionary<(IRegles, Statistique), int>();
/// <summary>
/// Obtient le nom du joueur.
/// </summary>
[DataMember]
public string Nom { get; private set; } = "";
/// <summary>
/// Indique si le joueur est connecté.
/// </summary>
public bool EstConnecte { get; private set; } = false;
/// <summary>
/// Constructeur de joueur.
/// </summary>
public Joueur()
{
}
/// <summary>
/// Constructeur de joueur avec le nom spécifié.
/// </summary>
/// <param name="nom">Le nom du joueur.</param>
public Joueur(string nom)
{
Nom = nom;
}
/// <summary>
/// Connecte le joueur.
/// </summary>
/// <param name="joueur">Le joueur à connecter.</param>
public void SeConnecter(Joueur joueur)
{
if (EstConnecte)
@ -41,19 +65,43 @@ namespace CoreLibrary.Joueurs
QuandJoueurSeConnecter(joueur);
}
/// <summary>
/// Permet au joueur de jouer une partie.
/// </summary>
/// <param name="partie">La partie à jouer.</param>
public void JouerPartie(Partie partie)
{
partie.PartieDemanderJoueurJouer += QuandDemanderJoueurJouer;
}
/// <summary>
/// Méthode appelée lorsque la partie demande à ce joueur de jouer.
/// </summary>
/// <param name="sender">La source de l'événement.</param>
/// <param name="e">Les arguments de l'événement.</param>
public virtual void QuandDemanderJoueurJouer(object? sender, PartieDemanderJoueurJouerEventArgs e)
{
}
/// <summary>
/// Retourne une représentation sous forme de chaîne de caractères.
/// </summary>
/// <returns>Renvoie une chaîne de caractères du nom du joueur.</returns>
public override string ToString() => Nom;
/// <summary>
/// Obtient la statistique spécifiée pour les règles données.
/// </summary>
/// <param name="regles">Les règles du jeu.</param>
/// <param name="statistique">Le type de statistique.</param>
/// <returns>La valeur de la statistique.</returns>
public int Statistique(IRegles regles, Statistique statistique) => statistiques.GetValueOrDefault((regles, statistique),0);
/// <summary>
/// Incrémente la valeur de la statistique spécifiée pour les règles données.
/// </summary>
/// <param name="regles">Les règles du jeu.</param>
/// <param name="statistique">Le type de statistique.</param>
public void IncrementerStatistique(IRegles regles, Statistique statistique) =>
statistiques[(regles, statistique)] = Statistique(regles, statistique) + 1;
}

@ -3,28 +3,38 @@ using CoreLibrary.Evenements;
namespace CoreLibrary.Joueurs
{
/// <summary>
/// Représente un joueur automatique (robot).
/// </summary>
public class Robot : Joueur
{
private static int nbRobots;
private List<Code>? codesPossibles;
static Robot()
{
nbRobots = 0;
}
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="Robot"/>.
/// </summary>
public Robot() :
base($"Naps {nbRobots + 1}")
{
++nbRobots;
}
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="Robot"/> avec le nom spécifié.
/// </summary>
/// <param name="nom">Le nom du robot.</param>
public Robot(string nom) :
base(nom)
{
}
/// <summary>
/// Méthode appelée lorsqu'un joueur doit jouer dans une partie.
/// </summary>
/// <param name="sender">La source de l'événement.</param>
/// <param name="e">Les arguments de l'événement.</param>
public override void QuandDemanderJoueurJouer(object? sender, PartieDemanderJoueurJouerEventArgs e)
{
if (e.Nom != Nom)
@ -35,76 +45,108 @@ namespace CoreLibrary.Joueurs
SupprimerCodesImpossibles(codesPossibles, e.Plateau);
for(int i = 0; i < e.Code.TailleMax; ++i)
for (int i = 0; i < e.Code.TailleMax; ++i)
e.Code.AjouterJeton(codesPossibles.ElementAt(0).Jetons[i]);
}
private static List<Code> GenererTousCodesPossibles(int tailleCode)
/// <summary>
/// Génère tous les codes possibles pour une taille de code donnée.
/// </summary>
/// <param name="tailleCode">La taille du code.</param>
private void GenererTousCodesPossibles(int tailleCode)
{
// Obtient toutes les valeurs de l'énumération Couleur
Couleur[] couleurs = Enum.GetValues<Couleur>();
// Calcule le nombre total de combinaisons possibles
int nbLignes = (int)Math.Pow(couleurs.Length, tailleCode);
// Crée une matrice pour stocker les jetons de chaque combinaison
Jeton?[,] jetons = new Jeton?[nbLignes, tailleCode];
for(int indiceColonne = 0; indiceColonne < jetons.GetLength(1); ++indiceColonne)
// Pour chaque colonne de la matrice
for (int indiceColonne = 0; indiceColonne < jetons.GetLength(1); ++indiceColonne)
{
// Calcule le nombre de répétitions pour chaque couleur
int repetition = nbLignes / (int)Math.Pow(couleurs.Length, (indiceColonne + 1));
// Pour chaque ligne de la matrice
for (int indiceLigne = 0; indiceLigne < jetons.GetLength(0); ++indiceLigne)
{
jetons[indiceLigne, indiceColonne] = new Jeton(couleurs[(indiceLigne / repetition) % couleurs.Length]);
// Calcule l'indice de la couleur à utiliser dans cette colonne
int couleurIndex = (indiceLigne / repetition) % couleurs.Length;
// Crée un jeton avec la couleur correspondante et l'ajoute à la matrice
jetons[indiceLigne, indiceColonne] = new Jeton(couleurs[couleurIndex]);
}
}
List<Code> codes = new List<Code>();
// Pour chaque combinaison de jetons générée
for (int i = 0; i < jetons.GetLength(0); ++i)
{
// Crée un nouveau code avec les jetons de la combinaison
Code code = new Code(tailleCode);
for (int j = 0; j < jetons.GetLength(1); ++j)
{
code.AjouterJeton(jetons[i, j]!.Value);
}
codes!.Add(code);
// Ajoute le code à la liste des codes possibles
codesPossibles!.Add(code);
}
return codes;
}
/// <summary>
/// Vérifie si un code est possible sur le plateau.
/// </summary>
/// <param name="plateau">Le plateau de jeu.</param>
/// <param name="code">Le code à vérifier.</param>
/// <returns>True si le code est possible, sinon False.</returns>
private static bool EstCodePossible(Plateau plateau, Code code)
{
for(int i = 0; i < plateau.Taille; ++i)
for (int i = 0; i < plateau.Taille; ++i)
{
Code sonCode = new Code(code.TailleMax);
for(int j = 0; j < code.TailleMax; ++j)
for (int j = 0; j < code.TailleMax; ++j)
{
sonCode.AjouterJeton(plateau.Grille.Item1.ElementAt(i).ElementAt(j));
}
IReadOnlyList<Indicateur> indicateurs = sonCode.Comparer(code);
if (
indicateurs.Count(indicateur => indicateur == Indicateur.BonnePlace) != plateau.Grille.Item2.ElementAt(i).Count(indicateur => indicateur == Indicateur.BonnePlace) ||
indicateurs.Count(indicateur => indicateur == Indicateur.BonneCouleur) != plateau.Grille.Item2.ElementAt(i).Count(indicateur => indicateur == Indicateur.BonneCouleur)
)
// Vérifie si les indicateurs du code correspondent aux indicateurs du plateau
if (indicateurs.Count(indicateur => indicateur == Indicateur.BonnePlace) != plateau.Grille.Item2.ElementAt(i).Count(indicateur => indicateur == Indicateur.BonnePlace) ||
indicateurs.Count(indicateur => indicateur == Indicateur.BonneCouleur) != plateau.Grille.Item2.ElementAt(i).Count(indicateur => indicateur == Indicateur.BonneCouleur))
{
return false;
}
}
return true;
}
private static void SupprimerCodesImpossibles(List<Code> codes, Plateau plateau)
/// <summary>
/// Supprime les codes impossibles du plateau.
/// </summary>
/// <param name="plateau">Le plateau de jeu.</param>
private static void SupprimerCodesImpossibles(Plateau plateau)
{
if (codes == null)
return;
List<int> indicesASupprimer = new List<int>();
for(int i = codes.Count - 1; i >= 0; --i)
// Pour chaque code possible
for (int i = codesPossibles.Count - 1; i >= 0; --i)
{
if(!EstCodePossible(plateau, codes.ElementAt(i)))
// Vérifie s'il est possible sur le plateau
if (!EstCodePossible(plateau, codesPossibles.ElementAt(i)))
indicesASupprimer.Add(i);
}
// Supprime les codes impossibles de la liste
foreach (int indice in indicesASupprimer)
codes.RemoveAt(indice);
}

@ -5,16 +5,45 @@ using CoreLibrary.Statistiques;
namespace CoreLibrary.Manageurs
{
/// <summary>
/// Classe représentant un manager.
/// </summary>
public class Manageur
{
/// <summary>
/// Attribut privé pour la persistance.
/// </summary>
private readonly IPersistance persistance;
/// <summary>
/// Liste des joueurs enregistrés.
/// </summary>
private readonly List<Joueur> joueurs;
/// <summary>
/// Liste des parties enregistrées.
/// </summary>
private readonly List<Partie> parties;
/// <summary>
/// Obtient la liste des joueurs enregistrés.
/// </summary>
public IReadOnlyList<Joueur> Joueurs => joueurs;
/// <summary>
/// Obtient la liste des parties enregistrées terminés.
/// </summary>
public IReadOnlyList<Partie> Parties => parties;
public IEnumerable<Partie> PartiesNonTerminees => parties.Where(partie => !partie.Termine).Reverse();
/// <summary>
/// Obtient la liste des parties non terminées.
/// </summary>
public IEnumerable<Partie> PartiesNonTerminees => parties.Where(partie => !partie.Termine).Reverse().ToList();
/// <summary>
/// Constructeur de manager avec la persistance spécifiée.
/// </summary>
/// <param name="persistance">Persistance permettant le chargement des joueurs et parties.</param>
public Manageur(IPersistance persistance)
{
this.persistance = persistance;
@ -23,12 +52,20 @@ namespace CoreLibrary.Manageurs
parties = persistance.Charger<Partie>().ToList();
}
/// <summary>
/// Sauvegarde les joueurs et les parties.
/// </summary>
private void Sauvegarder()
{
persistance.Enregistrer(joueurs.ToArray());
persistance.Enregistrer(parties.ToArray());
}
/// <summary>
/// Charge une partie avec la partie à charger spécifiée.
/// </summary>
/// <param name="partie">La partie que l'on veut charger.</param>
/// <returns>Renvoie la partie.</returns>
public Partie ChargerPartie(Partie partie)
{
parties.Remove(partie);
@ -41,6 +78,11 @@ namespace CoreLibrary.Manageurs
return nouvellePartie;
}
/// <summary>
/// Créer une nouvelle partie avec les règles spécifiée.
/// </summary>
/// <param name="regles">Regle permettant la création de la partie.</param>
/// <returns>Renvoie la nouvelle partie créée.</returns>
public Partie NouvellePartie(IRegles regles)
{
Partie partie = new Partie(regles);
@ -51,6 +93,11 @@ namespace CoreLibrary.Manageurs
return partie;
}
/// <summary>
/// Suivre le cour d'une partie avec la partie spécifiée.
/// Sauvegarde quand certains événements sont appelés dans la partie.
/// </summary>
/// <param name="partie">La partie à écouter.</param>
private void EcouterPartie(Partie partie)
{
partie.PartieDemanderJoueur += (sender, e) => Sauvegarder();
@ -82,6 +129,11 @@ namespace CoreLibrary.Manageurs
Sauvegarder();
};
}
/// <summary>
/// Recherche un joueur existant par son nom.
/// </summary>
/// <param name="nom">Le nom du joueur à rechercher.</param>
/// <returns>Le joueur s'il existe, sinon null.</returns>
private Joueur? DemanderJoueurExistant(string nom)
{
@ -96,6 +148,11 @@ namespace CoreLibrary.Manageurs
return null;
}
/// <summary>
/// Recherche un joueur par son nom ou le crée s'il n'existe pas.
/// </summary>
/// <param name="nom">Le nom du joueur.</param>
/// <returns>Le joueur trouvé ou créé.</returns>
public Joueur DemanderJoueur(string nom)
{
Joueur? joueur = DemanderJoueurExistant(nom);

@ -7,47 +7,138 @@ using System.Runtime.Serialization;
namespace CoreLibrary
{
/// <summary>
/// Classe représentant une partie.
/// </summary>
[DataContract]
[KnownType(typeof(ReglesClassiques))]
[KnownType(typeof(ReglesDifficiles))]
public class Partie : IEstPersistant
{
/// <summary>
/// Evénement déclenché lorsqu'il faut ajouter un joueur à la partie.
/// </summary>
public event EventHandler<PartieDemanderJoueurEventArgs>? PartieDemanderJoueur;
/// <summary>
/// Evénement déclenché lors du commencement de la partie.
/// </summary>
public event EventHandler<PartieDebutPartieEventArgs>? PartieDebutPartie;
/// <summary>
/// Evénement déclenché lorsqu'il faut demander à un joueur de jouer.
/// </summary>
public event EventHandler<PartieDemanderJoueurJouerEventArgs>? PartieDemanderJoueurJouer;
/// <summary>
/// Evénement déclenché lorsqu'un nouveau tour commence.
/// </summary>
public event EventHandler<PartieNouveauTourEventArgs>? PartieNouveauTour;
/// <summary>
/// Evénement déclenché lorsqu'on passe la main au joueur suivant.
/// </summary>
public event EventHandler<PartiePasserLaMainEventArgs>? PartiePasserLaMain;
/// <summary>
/// Evénement déclenché lorsque la partie est terminée.
/// </summary>
public event EventHandler<PartiePartieTermineeEventArgs>? PartiePartieTerminee;
/// <summary>
/// Méthode pour déclencher l'événement qui demande le joueur.
/// </summary>
/// <param name="joueurDemande">.</param>
private void QuandPartieDemanderJoueur(Joueur joueurDemande) => PartieDemanderJoueur?.Invoke(this, new PartieDemanderJoueurEventArgs(joueurs.Count + 1, joueurDemande));
/// <summary>
/// Méthode pour déclencher l'événement de début de partie.
/// </summary>
private void QuandPartieDebutPartie() => PartieDebutPartie?.Invoke(this, new PartieDebutPartieEventArgs());
/// <summary>
/// Méthode pour déclencher l'événement demandant à un joueur de jouer.
/// </summary>
/// <param name="code">Le code à utiliser pour jouer.</param>
private void QuandPartieDemanderJoueurJouer(Code code) => PartieDemanderJoueurJouer?.Invoke(this, new PartieDemanderJoueurJouerEventArgs(Tour, Joueurs.ElementAt(courant), plateaux.ElementAt(courant), code, joueurs[Joueurs.ElementAt(courant)]));
/// <summary>
/// Méthode pour déclencher l'événement d'un nouveau tour.
/// </summary>
/// <param name="code">Le code utilisé pour le nouveau tour.</param>
private void QuandPartieNouveauTour(Code code) => PartieNouveauTour?.Invoke(this, new PartieNouveauTourEventArgs(Tour, Joueurs.ElementAt(courant), plateaux.ElementAt(courant), code, joueurs[Joueurs.ElementAt(courant)]));
/// <summary>
/// Méthode pour déclencher l'événement de passer la main au joueur suivant.
/// </summary>
private void QuandPartiePasserLaMain() => PartiePasserLaMain?.Invoke(this, new PartiePasserLaMainEventArgs(Joueurs.ElementAt(courant)));
/// <summary>
/// Méthode pour déclencher l'événement de fin de partie.
/// </summary>
/// <param name="gagnants">Liste des noms des joueurs gagnants.</param>
/// <param name="perdants">Liste des noms des joueurs perdants.</param>
private void QuandPartiePartieTerminee(IReadOnlyList<string> gagnants, IReadOnlyList<string> perdants) => PartiePartieTerminee?.Invoke(this, new PartiePartieTermineeEventArgs(gagnants, perdants));
/// <summary>
/// Dictionnaire des joueurs, avec leur nom et le statut de leur joueur (humain ou robot).
/// </summary>
[DataMember]
private readonly Dictionary<string, bool> joueurs = new Dictionary<string, bool>();
/// <summary>
/// Liste des plateaux de jeu.
/// </summary
[DataMember]
private readonly List<Plateau> plateaux = new List<Plateau>();
/// <summary>
/// Indice correspondant au joueur courant.
/// </summary>
[DataMember]
private int courant = 0;
/// <summary>
/// Liste des noms des joueurs.
/// </summary>
public IEnumerable<string> Joueurs => joueurs.Keys;
/// <summary>
/// Liste des noms des robots.
/// </summary>
public IEnumerable<string> Robots => joueurs.Where(joueur => joueur.Value).Select(joueur => joueur.Key);
/// <summary>
/// Indique si la partie est terminée.
/// </summary>
[DataMember]
public bool Termine { get; private set; } = false;
/// <summary>
/// Numéro du tour actuel.
/// </summary>
[DataMember]
public int Tour { get; private set; } = 0;
/// <summary>
/// Règles utilisées dans la partie.
/// </summary>
[DataMember]
public IRegles Regles { get; private init; }
/// <summary>
/// Premier constructeur de la partie.
/// </summary>
/// <param name="regles">Les règles de la partie.</param>
public Partie(IRegles regles)
{
Regles = regles;
}
/// <summary>
/// Deuxième constructeur de la partie.
/// </summary>
/// <param name="partie">La partie à reprendre en cours.</param>
public Partie(Partie partie)
{
joueurs = partie.joueurs;
@ -67,6 +158,9 @@ namespace CoreLibrary
(joueurs[joueur] ? new Joueur(joueur) : new Robot(joueur)).JouerPartie(this);
}
/// <summary>
/// Lance le déroulement de la partie.
/// </summary>
public void Jouer()
{
if (joueurs.Count != Regles.NbJoueurs)
@ -75,6 +169,9 @@ namespace CoreLibrary
DebutPartie();
}
/// <summary>
/// Demande un joueur.
/// </summary>
private void DemanderJoueur()
{
Joueur joueurDemande = new Joueur();
@ -83,6 +180,11 @@ namespace CoreLibrary
QuandPartieDemanderJoueur(joueurDemande);
}
/// <summary>
/// Connecte les joueurs à la partie.
/// </summary>
/// <param name="sender">La classe qui appelle l'événement, ici Joueur.</param>
/// <param name="e">L'instance de l'événement JoueurSeConnecterEventArgs créée par Joueur.</param>
private void JoueurConnecte(object? sender, JoueurSeConnecterEventArgs e)
{
joueurs.Add(e.Joueur.Nom, e.Joueur.GetType().Equals(typeof(Joueur)));
@ -100,6 +202,9 @@ namespace CoreLibrary
}
}
/// <summary>
/// Lance le début de la partie.
/// </summary>
private void DebutPartie()
{
if (Tour == 0)
@ -115,6 +220,9 @@ namespace CoreLibrary
NouveauTour();
}
/// <summary>
/// Passe au tour suivant.
/// </summary>
private void NouveauTour()
{
Code code = new Code(Regles.TailleCode);
@ -123,6 +231,11 @@ namespace CoreLibrary
QuandPartieNouveauTour(code);
}
/// <summary>
/// Ajoute un code au plateau.
/// </summary>
/// <param name="sender">La classe qui appelle l'événement, ici Plateau.</param>
/// <param name="e">L'instance de l'événement PlateauAjouterCodeEventArgs créée par Plateau.</param>
private void PlateauAjouterCode(object? sender, PlateauAjouterCodeEventArgs e)
{
QuandPartiePasserLaMain();
@ -145,6 +258,9 @@ namespace CoreLibrary
}
}
/// <summary>
/// La partie est terminée.
/// </summary>
private void PartieTerminee()
{
Termine = true;

@ -1,4 +1,7 @@
namespace CoreLibrary.Persistance
{
/// <summary>
/// Interface IEstPersistant.
/// </summary>
public interface IEstPersistant;
}

@ -1,9 +1,22 @@
namespace CoreLibrary.Persistance
{
/// <summary>
/// Interface IPersistance permettant de charger et d'enregistrer.
/// </summary>
public interface IPersistance
{
/// <summary>
/// Charge les objets de type T.
/// </summary>
/// <typeparam name="T">Le type d'objet à charger.</typeparam>
/// <returns>Un tableau d'objets chargés.</returns>
public T[] Charger<T>() where T : IEstPersistant;
/// <summary>
/// Enregistre les éléments spécifiés.
/// </summary>
/// <typeparam name="T">Le type d'objet à enregistrer.</typeparam>
/// <param name="elements">Le tableau d'objets à enregistrer.</param>
public void Enregistrer<T>(T[] elements) where T : IEstPersistant;
}
}

@ -4,18 +4,39 @@ using System.Xml;
namespace CoreLibrary.Persistance
{
/// <summary>
/// Classe PersistanceJSON, implémentant l'interface IPersistance, pour la persistance des données au format JSON.
/// </summary>
public class PersistanceJson : IPersistance
{
/// <summary>
/// Chaîne de caractères représentant le nom du dossier pour sauvegarder et charger.
/// </summary>
private readonly string nomDossier = "Fichiers";
/// <summary>
/// Chaîne de caractères représentant le nom du doissier à la racine.
/// </summary>
private readonly string nomRacine = "Sources";
/// <summary>
/// Chaîne de caractères représentant le nom du dossier courant.
/// </summary>
private readonly string dossier = AppDomain.CurrentDomain.BaseDirectory;
/// <summary>
/// Constructeur de PersistanceJSON.
/// </summary>
public PersistanceJson()
{
while (new DirectoryInfo(dossier).Name != nomRacine)
dossier = Path.GetFullPath(Path.Combine(dossier, @"../"));
}
/// <summary>
/// Charge les données trouvées dans le fichier de sauvegarde au format JSON.
/// </summary>
/// <returns>Renvoie un tableau de tous les éléments chargés.</returns>
public T[] Charger<T>() where T : IEstPersistant
{
string fichier = $"{typeof(T).Name.ToLower()}s.json";
@ -41,6 +62,10 @@ namespace CoreLibrary.Persistance
return elements != null ? elements : Array.Empty<T>();
}
/// <summary>
/// Enregistre les éléments spécifiés dans le fichier de sauvegarde au format JSON.
/// </summary>
/// <param name="elements">Elements à enregistrer dans le fichier de sauvegarde.</param>
public void Enregistrer<T>(T[] elements) where T : IEstPersistant
{
string fichier = $"{typeof(T).Name.ToLower()}s.json";

@ -1,14 +1,42 @@
namespace CoreLibrary.Regles
{
/// <summary>
/// Interface pour créer des règles.
/// </summary>
public interface IRegles
{
int Indice { get; }
/// <summary>
/// Obtient le nom des règles.
/// </summary>
string Nom { get; }
string Description { get; }
/// <summary>
/// Obtient le nombre de joueurs.
/// </summary>
int NbJoueurs { get; }
/// <summary>
/// Obtient le nombre de tour.
/// </summary>
int NbTour { get; }
/// <summary>
/// Obtient la taille d'un code.
/// </summary>
int TailleCode { get; }
/// Détermine si les règles sont égales à un objet spécifié.
/// </summary>
/// <param name="obj">L'objet à comparer avec les règles.</param>
/// <returns>True si les règles sont égales à l'objet spécifié, sinon false.</returns>
bool Equals(object? obj);
/// <summary>
/// Obtient le code de hachage pour les règles.
/// </summary>
/// <returns>Code de hachage des règles.</returns>
int GetHashCode();
}
}

@ -2,16 +2,53 @@
namespace CoreLibrary.Regles
{
/// <summary>
/// Classe pour les règles classiques, implémente IRegles.
/// </summary>
[DataContract]
public class ReglesClassiques : IRegles
{
/// <summary>
/// Obtient l'indice des règles classiques.
/// </summary>
public int Indice => 1;
/// <summary>
/// Chaîne de caractères pour le nom des règles classiques.
/// </summary>
public string Nom => "Règles classiques";
/// <summary>
/// Obtient la description des règles classiques.
/// </summary>
public string Description => "Le but du jeu est de découvrir la combinaison. On génère aléatoirement deux combinaisons de 4 couleurs (six couleurs au total : jaune, bleu, rouge, vert, blanc et noir), une combinaison pour chaque joueur. Deux joueurs se battent pour trouver la combinaison en premier, il y a douze tours. Le premier joueur à trouver la combinaison à gagner, chaque joueur a le même nombre de coups à réaliser. Donc si le joueur un à trouvé la solution au bout de huit coups, le joueur deux doit finir son huitième coup. Si le joueur deux trouve la combinaison, les deux joueurs sont à égalité. Sinon, le joueur un gagne. Pour trouver la combinaison, les joueurs disposent de quatre indicateurs. Ces indicateurs sont quatre ronds qui représentent les quatre couleurs sélectionnées par le joueur. Un rond noir signifie quune couleur est à la bonne place, un rond blanc correspond à une mauvaise place et s'il ny a pas dindicateur aucune des couleurs nest présentent dans la combinaison.";
/// <summary>
/// Nombre de joueurs autorisé pour les règles classiques.
/// </summary>
public int NbJoueurs => 2;
/// <summary>
/// Nombre de tour maximum pour des règles classiques.
/// </summary>
public int NbTour => 12;
/// <summary>
/// Taille du code maximale pour des règles classiques.
/// </summary>
public int TailleCode => 4;
/// <summary>
/// Détermine si les règles classiques sont égales à un objet spécifié.
/// </summary>
/// <param name="obj">L'objet à comparer avec les règles classiques.</param>
/// <returns>True si les règles classiques sont égales à l'objet spécifié, sinon false.</returns>
public override bool Equals(object? obj) => obj is ReglesClassiques;
/// <summary>
/// Obtient le code de hachage pour les règles classiques.
/// </summary>
/// <returns>Le code de hachage des règles classiques.</returns>
public override int GetHashCode() => Nom.GetHashCode();
}
}

@ -2,16 +2,54 @@
namespace CoreLibrary.Regles
{
/// <summary>
/// Classe définissant les règles difficiles du jeu.
/// </summary>
[DataContract]
public class ReglesDifficiles : IRegles
{
/// <summary>
/// Obtient l'indice des règles difficiles.
/// </summary>
public int Indice => 2;
/// <summary>
/// Obtient le nom des règles difficiles.
/// </summary>
public string Nom => "Règles difficiles";
/// <summary>
/// Obtient la description des règles difficiles.
/// </summary>
public string Description => "Le but du jeu est de découvrir la combinaison. On génère aléatoirement deux combinaisons de 6 couleurs (six couleurs au total : jaune, bleu, rouge, vert, blanc et noir), une combinaison pour chaque joueur. Deux joueurs se battent pour trouver la combinaison en premier, il y a douze tours. Le premier joueur à trouver la combinaison à gagner, chaque joueur a le même nombre de coups à réaliser. Donc si le joueur un à trouvé la solution au bout de huit coups, le joueur deux doit finir son huitième coup. Si le joueur deux trouve la combinaison, les deux joueurs sont à égalité. Sinon, le joueur un gagne. Pour trouver la combinaison, les joueurs disposent de quatre indicateurs. Ces indicateurs sont quatre ronds qui représentent les 6 couleurs sélectionnées par le joueur. Un rond noir signifie quune couleur est à la bonne place, un rond blanc correspond à une mauvaise place et s'il ny a pas dindicateur aucune des couleurs nest présentent dans la combinaison.";
/// <summary>
/// Obtient le nombre de joueurs autorisé pour les règles difficiles.
/// </summary>
public int NbJoueurs => 2;
/// <summary>
/// Obtient le nombre de tours maximum pour les règles difficiles.
/// </summary>
public int NbTour => 12;
/// <summary>
/// Obtient la taille maximale du code pour les règles difficiles.
/// </summary>
public int TailleCode => 6;
/// <summary>
/// Détermine si les règles difficiles sont égales à un objet spécifié.
/// </summary>
/// <param name="obj">L'objet à comparer avec les règles difficiles.</param>
/// <returns>True si les règles difficiles sont égales à l'objet spécifié, sinon false.</returns>
public override bool Equals(object? obj) => obj is ReglesDifficiles;
/// <summary>
/// Obtient le code de hachage pour les règles difficiles.
/// </summary>
/// <returns>Le code de hachage des règles difficiles.</returns>
public override int GetHashCode() => Nom.GetHashCode();
}
}

@ -1,5 +1,8 @@
namespace CoreLibrary.Statistiques
{
/// <summary>
/// Enumération des statistiques.
/// </summary>
public enum Statistique
{
PartieGagnee,

@ -1,22 +1,42 @@
namespace MauiSpark.Pages;
namespace MauiSpark.Pages;
/// <summary>
/// Page d'accueil de l'application.
/// </summary>
public partial class AccueilPage : ContentPage
{
public partial class AccueilPage : ContentPage
{
public AccueilPage()
{
NavigationPage.SetHasBackButton(this, false);
NavigationPage.SetHasNavigationBar(this, false);
InitializeComponent();
}
private void QuandJouerClique(Object? sender, EventArgs e)
{
Navigation.PushAsync(new ModePage());
/// <summary>
/// Constructeur de la page d'accueil.
/// Initialise les paramètres de navigation et les composants de la page.
/// </summary>
public AccueilPage()
{
NavigationPage.SetHasBackButton(this, false);
NavigationPage.SetHasNavigationBar(this, false);
InitializeComponent();
}
/// <summary>
/// Méthode déclenchée lorsque le bouton "Jouer" est cliqué.
/// Navigue vers la page Mode.
/// </summary>
/// <param name="sender">L'objet qui appelle l'événement ; dans ce cas, le bouton "Jouer".</param>
/// <param name="e">L'instance de l'événement EventArgs créée par le système.</param>
private void QuandJouerClique(Object? sender, EventArgs e)
{
Navigation.PushAsync(new ModePage());
}
/// <summary>
/// Méthode déclenchée lorsque le bouton "Reprendre" est cliqué.
/// Navigue vers la page Reprendre.
/// </summary>
/// <param name="sender">L'objet qui appelle l'événement ; dans ce cas, le bouton "Reprendre".</param>
/// <param name="e">L'instance de l'événement EventArgs créée par le système.</param>
private void QuandReprendreClique(Object? sender, EventArgs e)
{
Navigation.PushAsync(new ReprendrePage());
}
}
}

@ -6,24 +6,49 @@ using System.Runtime.CompilerServices;
namespace MauiSpark.Pages
{
/// <summary>
/// Représente un joueur dans le classement.
/// </summary>
partial class Enfant
{
private readonly Classement classement;
/// <summary>
/// Obtient ou définit le joueur associé à cet enfant.
/// </summary>
public Joueur Joueur { get; set; }
/// <summary>
/// Obtient la place du joueur dans le classement.
/// </summary>
public int Place => classement.Enfants.ToList().IndexOf(this) + 1;
/// <summary>
/// Obtient les statistiques du joueur dans le classement.
/// </summary>
public IEnumerable<int> Statistiques => Enum.GetValues<Statistique>()
.Select(statistique => Joueur.Statistique(classement.Regles, statistique));
/// <summary>
/// Obtient une liste des objets de cet enfant dans le classement (Son nom et sa place).
/// </summary>
public IEnumerable<string> Objets => new List<string>([$"{Place}", Joueur.Nom])
.Concat(Statistiques.Select(statistique => $"{statistique}"));
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="Enfant"/>.
/// </summary>
/// <param name="joueur">Le joueur associé à cet enfant.</param>
/// <param name="classement">Le classement auquel cet enfant appartient.</param>
public Enfant(Joueur joueur, Classement classement)
{
this.classement = classement;
Joueur = joueur;
}
/// <summary>
/// Détermine si l'objet spécifié est égal à l'objet actuel.
/// </summary>
public override bool Equals(object? obj)
{
if (obj == null || obj is not Enfant)
@ -32,21 +57,42 @@ namespace MauiSpark.Pages
return Joueur == ((Enfant)obj).Joueur;
}
/// <summary>
/// Retourne le code de hachage de cet objet.
/// </summary>
public override int GetHashCode() => Joueur.GetHashCode();
}
/// <summary>
/// Représente le classement des joueurs.
/// </summary>
partial class Classement : INotifyPropertyChanged
{
/// <summary>
/// Se produit lorsque la valeur d'une propriété de l'objet change.
/// </summary>
public event PropertyChangedEventHandler? PropertyChanged;
/// <summary>
/// Déclenche l'événement <see cref="PropertyChanged"/> pour notifier les modifications de propriété.
/// </summary>
/// <param name="propriete">Le nom de la propriété qui a changé.</param>
public void QuandProprieteChangee([CallerMemberName] string? propriete = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propriete));
private int indiceRegles = 0;
/// <summary>
/// Obtient les règles actuelles du classement.
/// </summary>
public IRegles Regles => ClassementPage.ToutesRegles.ElementAt(indiceRegles);
private Statistique statistique = Enum.GetValues<Statistique>().First();
/// <summary>
/// Obtient ou définit la statistique utilisée pour classer les joueurs.
/// </summary>
public Statistique Statistique
{
get => statistique;
@ -58,6 +104,10 @@ namespace MauiSpark.Pages
}
private bool inverser = true;
/// <summary>
/// Obtient ou définit une valeur indiquant si le classement est inversé.
/// </summary>
public bool Inverser {
get => inverser;
set
@ -67,6 +117,9 @@ namespace MauiSpark.Pages
}
}
/// <summary>
/// Obtient les titres des colonnes du classement.
/// </summary>
public IEnumerable<string> Titres => new List<string>(["Place", "Nom"]).Concat(
Enum.GetValues<Statistique>().Select(
statistique => string.Concat((Enum.GetName(typeof(Statistique), statistique) ?? "").Select(
@ -75,6 +128,9 @@ namespace MauiSpark.Pages
)
);
/// <summary>
/// Obtient la liste des enfants (joueurs) dans le classement, triée en fonction de la statistique et des règles actuelles.
/// </summary>
public IEnumerable<Enfant> Enfants => Inverser ?
MauiProgram.Manageur.Joueurs
.OrderBy(joueur => joueur.Statistique(Regles, Statistique))
@ -83,6 +139,10 @@ namespace MauiSpark.Pages
.OrderBy(joueur => joueur.Statistique(Regles, Statistique))
.Select(joueur => new Enfant(joueur, this));
/// <summary>
/// Incrémente l'indice des règles du classement selon une valeur spécifiée.
/// </summary>
/// <param name="valeur">La valeur à ajouter à l'indice des règles.</param>
public void IncrementerRegles(int valeur)
{
if ((indiceRegles += valeur) < 0)
@ -95,13 +155,24 @@ namespace MauiSpark.Pages
}
}
/// <summary>
/// Partie de la logique de l'interface utilisateur de la page de classement.
/// Gère les calculs de classement, l'affichage des statistiques et le changement des règles de jeu.
/// </summary>
public partial class ClassementPage : ContentPage
{
/// <summary>
/// Obtient toutes les règles de jeu disponibles.
/// </summary>
public static IEnumerable<IRegles> ToutesRegles => typeof(IRegles).Assembly.GetTypes()
.Where(type => typeof(IRegles).IsAssignableFrom(type) && type.IsClass)
.Select(type => (Activator.CreateInstance(type) as IRegles)!)
.OrderBy(regles => regles.Indice);
/// <summary>
/// Constructeur de la page de classement des joueurs.
/// Initialise les paramètres de navigation et les composants de la page.
/// </summary>
public ClassementPage()
{
InitializeComponent();
@ -111,11 +182,19 @@ namespace MauiSpark.Pages
BindingContext = new Classement();
}
/// <summary>
/// Méthode appelée lorsqu'un bouton de changement de règles est pressé.
/// Augmente ou diminue l'indice des règles selon le bouton pressé.
/// </summary>
public void ChangerReglesPresse(object sender, EventArgs e)
{
((Classement)BindingContext).IncrementerRegles(sender == DiminuerRegles ? -1 : 1);
}
/// <summary>
/// Méthode appelée lorsqu'un bouton statistique est pressée.
/// Modifie la statistique de classement ou inverse l'ordre du classement si la même statistique est déjà sélectionnée.
/// </summary>
public void StatistiquePressee(object sender, EventArgs e)
{
if (sender is not Label || !Enum.IsDefined(typeof(Statistique), ((Label)sender).Text.Replace(" ", "")))

@ -3,12 +3,25 @@ using CoreLibrary.Joueurs;
namespace MauiSpark.Pages;
/// <summary>
/// Page de connexion où les joueurs de la partie sont entrés.
/// </summary>
public partial class ConnexionPage : ContentPage
{
private int? indice;
/// <summary>
/// Indice du joueur à entrer.
/// </summary>
private int? indice;
/// <summary>
/// Le joueur demandé.
/// </summary>
private Joueur? joueurDemande;
/// <summary>
/// Constructeur de la page de connexion.
/// Initialise les paramètres de navigation et les composants de la page.
/// </summary>
public ConnexionPage()
{
NavigationPage.SetHasNavigationBar(this, false);
@ -16,7 +29,12 @@ public partial class ConnexionPage : ContentPage
InitializeComponent();
}
public async void QuandDemanderNom(Object? sender, PartieDemanderJoueurEventArgs e)
/// <summary>
/// Méthode déclenchée lorsque l'événement DemanderNom de partie est appelée.
/// </summary>
/// <param name="sender">La classe qui appelle l'événement ; ici Partie.</param>
/// <param name="e">L'instance de l'événement PartieDemanderJoueurEventArgs créée par Partie.</param>
public async void QuandDemanderNom(Object? sender, PartieDemanderJoueurEventArgs e)
{
if(Application.Current != null && Application.Current.MainPage != null && ((NavigationPage)Application.Current.MainPage).CurrentPage != this)
await Application.Current.MainPage.Navigation.PushAsync(this);
@ -27,7 +45,12 @@ public partial class ConnexionPage : ContentPage
BindingContext = $"Joueur {e.Indice}";
}
private void QuandSeConnecterPresse(Object sender, EventArgs e)
/// <summary>
/// Méthode déclenchée lorsque le bouton "Se Connecter" est cliqué.
/// </summary>
/// <param name="sender">L'objet qui appelle l'événement ; ici le bouton SeConnecterPresse.</param>
/// <param name="e">L'instance de l'événement EventArgs créée par le système.</param>
private void QuandSeConnecterPresse(Object sender, EventArgs e)
{
if (joueurDemande == null || indice == null)
return;
@ -45,6 +68,11 @@ public partial class ConnexionPage : ContentPage
joueurDemande.SeConnecter(joueur);
}
/// <summary>
/// Méthode déclenchée lorsque le bouton "Robot" est cliqué.
/// </summary>
/// <param name="sender">L'objet qui appelle l'événement ; ici le bouton RobotPresse.</param>
/// <param name="e">L'instance de l'événement EventArgs créée par le système.</param>
private void QuandRobotPresse(object sender, EventArgs e)
{
if (joueurDemande == null || indice == null)

@ -1,18 +1,26 @@
using CoreLibrary.Regles;
namespace MauiSpark.Pages;
public partial class ModePage : ContentPage
{
public ModePage()
{
NavigationPage.SetHasNavigationBar(this, false);
BindingContext = typeof(IRegles).Assembly.GetTypes()
.Where(type => typeof(IRegles).IsAssignableFrom(type) && type.IsClass)
.Select(type => (Activator.CreateInstance(type) as IRegles)!)
.OrderBy(regles => regles.Indice);
InitializeComponent();
}
using CoreLibrary.Regles;
namespace MauiSpark.Pages;
/// <summary>
/// Page de sélection des modes de jeux.
/// </summary>
public partial class ModePage : ContentPage
{
/// <summary>
/// Constructeur de la page mode.
/// Initialise les paramètres de navigation et les composants de la page.
/// Initialise le binding contexte avec une liste de règles.
/// </summary>
public ModePage()
{
NavigationPage.SetHasNavigationBar(this, false);
BindingContext = typeof(IRegles).Assembly.GetTypes()
.Where(type => typeof(IRegles).IsAssignableFrom(type) && type.IsClass)
.Select(type => (Activator.CreateInstance(type) as IRegles)!)
.OrderBy(regles => regles.Indice);
InitializeComponent();
}
}

@ -4,14 +4,37 @@ using CoreLibrary.Exceptions;
namespace MauiSpark.Pages;
/// <summary>
/// Représente un tour de jeu, avec le plateau actuel, le joueur en cours, le numéro de tour et le code.
/// </summary>
internal class Tour
{
/// <summary>
/// Obtient ou définit le plateau de jeu pour ce tour.
/// </summary>
public IEnumerable<(IEnumerable<Jeton>, IEnumerable<Indicateur>)> Plateau { get; private init; }
/// <summary>
/// Obtient ou définit le nom du joueur pour ce tour.
/// </summary>
public string Joueur { get; private init; }
/// <summary>
/// Obtient ou définit le numéro de tour.
/// </summary>
public string Numero { get; private init; }
/// <summary>
/// Obtient ou définit le code pour ce tour.
/// </summary>
public Code Code { get; private init; }
public bool EstJoueur { get; private init; }
/// <summary>
/// Initialise un tour à partir des arguments de l'événement de nouveau tour de jeu.
/// </summary>
/// <param name="e">Les arguments de l'événement PartieNouveauTourEventArgs.</param>
public Tour(PartieNouveauTourEventArgs e)
{
Numero = $"Tour {e.Tour}";
@ -38,12 +61,19 @@ internal class Tour
}
}
/// <summary>
/// Page affichant le plateau de jeu et permettant aux joueurs d'interagir avec celui-ci.
/// </summary>
public partial class PlateauPage : ContentPage
{
private Code? code;
private Plateau? plateau;
private bool? estJoueur;
/// <summary>
/// Constructeur de la page du plateau de jeu.
/// Initialise les paramètres de navigation et les composants de la page.
/// </summary>
public PlateauPage()
{
NavigationPage.SetHasNavigationBar(this, false);
@ -51,6 +81,12 @@ public partial class PlateauPage : ContentPage
InitializeComponent();
}
/// <summary>
/// Méthode appelée lorsqu'un nouveau tour de jeu commence.
/// Affiche le nouveau tour de jeu sur le plateau.
/// </summary>
/// <param name="sender">La source de l'événement ; dans ce cas, la partie.</param>
/// <param name="e">Les arguments de l'événement PartieNouveauTourEventArgs.</param>
public async void QuandNouveauTour(object? sender, PartieNouveauTourEventArgs e)
{
if (Application.Current == null || Application.Current.MainPage == null)
@ -76,6 +112,12 @@ public partial class PlateauPage : ContentPage
BindingContext = new Tour(e);
}
/// <summary>
/// Supprime le dernier jeton ajouté au code en cours.
/// Affiche une alerte si le code est vide.
/// </summary>
/// <param name="sender">La source de l'événement ; ici, le bouton de suppression de jeton.</param>
/// <param name="e">Les arguments de l'événement EventArgs.</param>
private void SupprimerDernierJeton(Object sender, EventArgs e)
{
try
@ -89,6 +131,12 @@ public partial class PlateauPage : ContentPage
}
}
/// <summary>
/// Valide le code actuel et l'ajoute au plateau de jeu.
/// Affiche une alerte si le code est incomplet.
/// </summary>
/// <param name="sender">La source de l'événement ; ici, le bouton de validation de code.</param>
/// <param name="e">Les arguments de l'événement EventArgs.</param>
private void ValiderCode(Object sender, EventArgs e)
{
try
@ -102,6 +150,12 @@ public partial class PlateauPage : ContentPage
}
}
/// <summary>
/// Ouvre la page des règles du jeu.
/// </summary>
/// <param name="sender">La source de l'événement ; ici, le bouton de règles du jeu.</param>
/// <param name="e">Les arguments de l'événement EventArgs.</param>
private async void QuandReglesClique(object sender, EventArgs e)
{
await Navigation.PushAsync(new ReglesPage());

@ -2,17 +2,25 @@ using CoreLibrary.Regles;
namespace MauiSpark.Pages;
/// <summary>
/// Page affichant les règles disponibles.
/// </summary>
public partial class ReglesPage : ContentPage
{
{
/// <summary>
/// Constructeur de la page des règles.
/// Initialise les paramètres de navigation et les composants de la page.
/// Initialise le contexte de liaison avec une liste de règles disponibles.
/// </summary>
public ReglesPage()
{
NavigationPage.SetHasNavigationBar(this, false);
BindingContext = typeof(IRegles).Assembly.GetTypes()
.Where(type => typeof(IRegles).IsAssignableFrom(type) && type.IsClass)
.Select(type => (Activator.CreateInstance(type) as IRegles)!)
.OrderBy(regles => regles.Indice);
BindingContext = typeof(IRegles).Assembly.GetTypes()
.Where(type => typeof(IRegles).IsAssignableFrom(type) && type.IsClass)
.Select(type => (Activator.CreateInstance(type) as IRegles)!)
.OrderBy(regles => regles.Indice);
InitializeComponent();
}
}

@ -1,8 +1,16 @@
namespace MauiSpark.Pages;
/// <summary>
/// Page permettant de reprendre les parties en cours.
/// </summary>
public partial class ReprendrePage : ContentPage
{
public ReprendrePage()
/// <summary>
/// Constructeur de la page de reprise.
/// Initialise les paramètres de navigation et les composants de la page.
/// Initialise le contexte de liaison avec les parties non terminées.
/// </summary>
public ReprendrePage()
{
NavigationPage.SetHasNavigationBar(this, false);

@ -11,17 +11,29 @@ partial class Message
public string Image { get; init; } = "";
}
/// <summary>
/// Page affichée lorsque la partie est terminée, montrant le résultat de la partie.
/// </summary>
public partial class VictoirePage : ContentPage
{
public VictoirePage()
/// <summary>
/// Constructeur de la page de victoire.
/// Initialise les paramètres de navigation et les composants de la page.
/// </summary>
public VictoirePage()
{
NavigationPage.SetHasNavigationBar(this, false);
InitializeComponent();
}
/// <summary>
/// Méthode déclenchée lorsque la partie est terminée.
/// Affiche le résultat de la partie en fonction des gagnants et des perdants.
/// </summary>
/// <param name="sender">La classe qui appelle l'événement ; ici Partie.</param>
/// <param name="e">L'instance de l'événement PartiePartieTermineeEventArgs créée par Partie.</param>
public async void QuandPartieTerminee(object? sender, PartiePartieTermineeEventArgs e)
{
if (Application.Current == null || Application.Current.MainPage == null)
@ -43,6 +55,7 @@ public partial class VictoirePage : ContentPage
IReadOnlyList<string> gagnants = e.Gagnants;
IReadOnlyList<string> perdants = e.Perdants;
// Affichage du message en fonction du résultat de la partie
if (gagnants.Count == 1)
BindingContext = new Message()
{
@ -66,6 +79,12 @@ public partial class VictoirePage : ContentPage
};
}
/// <summary>
/// Méthode déclenchée lorsque le bouton de retour au menu est pressé.
/// Retourne à la page précédente.
/// </summary>
/// <param name="sender">L'objet qui appelle l'événement ; ici le bouton de retour au menu.</param>
/// <param name="e">L'instance de l'événement EventArgs créée par le système.</param>
public async void QuandMenuPresse(object sender, EventArgs e)
{
await Navigation.PopAsync();

@ -2,13 +2,26 @@ using MauiSpark.Pages;
namespace MauiSpark.Vues;
/// <summary>
/// Vue représentant un bouton pour accéder à la page de classement.
/// </summary>
public partial class BoutonClassementVue : ContentView
{
public BoutonClassementVue()
/// <summary>
/// Constructeur de la vue du bouton de classement.
/// Initialise les composants de la vue.
/// </summary>
public BoutonClassementVue()
{
InitializeComponent();
}
/// <summary>
/// Méthode déclenchée lorsque le bouton de classement est cliqué.
/// Navigue vers la page de classement.
/// </summary>
/// <param name="sender">L'objet qui appelle l'événement ; ici le bouton de classement.</param>
/// <param name="e">L'instance de l'événement EventArgs créée par le système.</param>
private void QuandClassementClique(Object? sender, EventArgs e)
{
Navigation.PushAsync(new ClassementPage());

@ -2,13 +2,26 @@ using MauiSpark.Pages;
namespace MauiSpark.Vues;
/// <summary>
/// Vue représentant un bouton pour accéder à la page des règles.
/// </summary>
public partial class BoutonReglesVue : ContentView
{
/// <summary>
/// Constructeur de la vue du bouton des règles.
/// Initialise les composants de la vue.
/// </summary>
public BoutonReglesVue()
{
InitializeComponent();
}
/// <summary>
/// Méthode déclenchée lorsque le bouton des règles est cliqué.
/// Navigue vers la page des règles.
/// </summary>
/// <param name="sender">L'objet qui appelle l'événement ; ici le bouton des règles.</param>
/// <param name="e">L'instance de l'événement EventArgs créée par le système.</param>
private void QuandReglesClique(Object? sender, EventArgs e)
{
Navigation.PushAsync(new ReglesPage());

@ -1,15 +1,28 @@
namespace MauiSpark.Vues;
/// <summary>
/// Vue représentant une image de résultat.
/// </summary>
public partial class ImageResultatVue : ContentView
{
/// <summary>
/// Propriété attachée à l'image affichée dans la vue.
/// </summary>
public static readonly BindableProperty ImageProperty = BindableProperty.Create(nameof(Image), typeof(ImageSource), typeof(ImageResultatVue), null);
/// <summary>
/// Obtient ou définit l'image affichée dans la vue.
/// </summary>
public ImageSource Image
{
get => (ImageSource)GetValue(ImageProperty);
set => SetValue(ImageProperty, value);
}
/// <summary>
/// Constructeur de la vue de l'image de résultat.
/// Initialise les composants de la vue et lie le contexte de liaison à cette instance.
/// </summary>
public ImageResultatVue()
{
InitializeComponent();

@ -4,22 +4,42 @@ using System.Globalization;
namespace MauiSpark.Vues;
/// <summary>
/// Vue représentant un indicateur coloré.
/// </summary>
public partial class IndicateurVue : ContentView
{
/// <summary>
/// Propriété attachée à la couleur de l'indicateur.
/// </summary>
public static readonly BindableProperty CouleurProperty = BindableProperty.Create(nameof(Couleur), typeof(Color), typeof(IndicateurVue), default(Color));
public Color Couleur
/// <summary>
/// Obtient ou définit la couleur de l'indicateur.
/// </summary>
public Color Couleur
{
get => (Color)GetValue(CouleurProperty);
set => SetValue(CouleurProperty, value);
}
public IndicateurVue()
/// <summary>
/// Constructeur de la vue de l'indicateur.
/// Initialise les composants de la vue et lie le contexte de liaison à cette instance.
/// </summary>
public IndicateurVue()
{
InitializeComponent();
BindingContext = this;
}
/// <summary>
/// Méthode déclenchée lorsque la taille de l'indicateur est modifiée.
/// Réajuste la taille du carré représentant l'indicateur pour qu'il soit toujours carré.
/// </summary>
/// <param name="sender">L'objet qui a déclenché l'événement ; ici, le carré représentant l'indicateur.</param>
/// <param name="e">Les arguments de l'événement.</param>
private void QuandTailleChangee(object sender, EventArgs e)
{
double taille = Math.Min(Grid.Width, Grid.Height) / 2;

@ -5,42 +5,82 @@ using System.Globalization;
namespace MauiSpark.Vues;
/// <summary>
/// Vue représentant un jeton coloré.
/// </summary>
public partial class JetonVue : ContentView
{
/// <summary>
/// Propriété attachée à la couleur du jeton.
/// </summary>
public static readonly BindableProperty CouleurProperty = BindableProperty.Create(nameof(Couleur), typeof(Color), typeof(JetonVue), default(Color));
/// <summary>
/// Propriété attachée au code associé au jeton.
/// </summary>
public static readonly BindableProperty CodeProperty = BindableProperty.Create(nameof(Code), typeof(Code), typeof(JetonVue), null);
/// <summary>
/// Propriété attachée indiquant si le jeton est associé à un joueur.
/// </summary>
public static readonly BindableProperty EstJoueurProperty = BindableProperty.Create(nameof(EstJoueur), typeof(bool), typeof(JetonVue), true);
/// <summary>
/// Obtient ou définit la couleur du jeton.
/// </summary>
public Color Couleur
{
get => (Color)GetValue(CouleurProperty);
set => SetValue(CouleurProperty, value);
}
/// <summary>
/// Obtient ou définit le code associé au jeton.
/// </summary>
public Code? Code
{
get => (Code?)GetValue(CodeProperty);
set => SetValue(CodeProperty, value);
}
/// <summary>
/// Obtient ou définit une valeur indiquant si le jeton est associé à un joueur.
/// </summary>
public bool EstJoueur
{
get => (bool)GetValue(EstJoueurProperty);
set => SetValue(EstJoueurProperty, value);
}
/// <summary>
/// Constructeur de la vue du jeton.
/// Initialise les composants de la vue et lie le contexte de liaison à cette instance.
/// </summary>
public JetonVue()
{
InitializeComponent();
BindingContext = this;
}
/// <summary>
/// Méthode déclenchée lorsque la taille du jeton est modifiée.
/// Réajuste la taille du cercle représentant le jeton pour qu'il soit toujours circulaire.
/// </summary>
/// <param name="sender">L'objet qui a déclenché l'événement ; ici, le cercle représentant le jeton.</param>
/// <param name="e">Les arguments de l'événement, s'il y en a.</param>
private void QuandTailleChangee(object sender, EventArgs e)
{
double taille = Math.Min(Grid.Width, Grid.Height) / 2;
Cercle.WidthRequest = Cercle.HeightRequest = taille;
}
/// <summary>
/// Méthode déclenchée lorsque le jeton est pressé.
/// Ajoute un jeton à un code si celui-ci est associé à un joueur.
/// Affiche une alerte si le code est déjà complet.
/// </summary>
/// <param name="sender">L'objet qui a déclenché l'événement ; ici, le cercle représentant le jeton.</param>
/// <param name="e">Les arguments de l'événement, s'il y en a.</param>
private void JetonPresse(object sender, EventArgs e)
{
if (Cercle == null || !sender.Equals(Cercle) || Code == null || Application.Current == null || Application.Current.MainPage == null || !EstJoueur)

@ -4,21 +4,38 @@ using MauiSpark.Pages;
namespace MauiSpark.Vues;
/// <summary>
/// Vue permettant de sélectionner un mode de jeu.
/// </summary>
public partial class ModeVue : ContentView
{
/// <summary>
/// Propriété de dépendance pour les règles du jeu.
/// </summary>
public static readonly BindableProperty ReglesProperty = BindableProperty.Create(nameof(Regles), typeof(IRegles), typeof(ModeVue), null);
/// <summary>
/// Les règles du jeu sélectionnées.
/// </summary>
public IRegles Regles
{
get => (IRegles)GetValue(ReglesProperty);
set => SetValue(ReglesProperty, value);
}
/// <summary>
/// Constructeur par défaut de la vue du mode de jeu.
/// </summary>
public ModeVue()
{
InitializeComponent();
}
/// <summary>
/// Méthode déclenchée lorsque le bouton de sélection des règles est pressé.
/// </summary>
/// <param name="sender">L'objet qui a déclenché l'événement ; ici, le bouton de sélection des règles.</param>
/// <param name="e">Les arguments de l'événement EventArgs.</param>
private void QuandReglesPresse(Object sender, EventArgs e)
{
Partie partie = MauiProgram.Manageur.NouvellePartie(Regles);

@ -4,33 +4,57 @@ using System.ComponentModel;
namespace MauiSpark.Vues;
/// <summary>
/// Vue affichant les détails d'une partie en cours.
/// </summary>
public partial class PartieCommenceeVue : ContentView, INotifyPropertyChanged
{
/// <summary>
/// Propriété de dépendance pour la partie en cours.
/// </summary>
public static readonly BindableProperty PartieProperty = BindableProperty.Create(nameof(Partie), typeof(Partie), typeof(PartieCommenceeVue), null, propertyChanged: QuandPartieChangee);
/// <summary>
/// La partie en cours.
/// </summary>
public Partie Partie
{
get => (Partie)GetValue(PartieProperty);
set => SetValue(PartieProperty, value);
}
/// <summary>
/// Le nom des règles de la partie.
/// </summary>
public string NomRegles
{
get => Partie != null ? Partie.Regles.Nom : "";
}
/// <summary>
/// Le tour actuel de la partie.
/// </summary>
public string TourActuel
{
get => $"Tour : {(Partie != null ? Partie.Tour : 0)} / {(Partie != null ? Partie.Regles.NbTour : 0)}";
}
/// <summary>
/// Les joueurs participant à la partie.
/// </summary>
public string[] Joueurs
{
get => Partie != null ? Partie.Joueurs.ToArray() : [];
}
/// <summary>
/// Le nombre de joueurs participant à la partie.
/// </summary>
public string NombreJoueurs => $"Joueurs : {Joueurs.Length} / {(Partie != null ? Partie.Regles.NbJoueurs : 0)}";
/// <summary>
/// Méthode déclenchée lorsqu'une propriété de la partie change.
/// </summary>
private static void QuandPartieChangee(BindableObject bindable, object ancienneValeur, object nouvelleValeur)
{
((PartieCommenceeVue)bindable).OnPropertyChanged(nameof(NomRegles));
@ -39,6 +63,9 @@ public partial class PartieCommenceeVue : ContentView, INotifyPropertyChanged
((PartieCommenceeVue)bindable).OnPropertyChanged(nameof(NombreJoueurs));
}
/// <summary>
/// Méthode déclenchée lorsqu'un utilisateur appuie sur la vue de la partie.
/// </summary>
private void PartiePressee(object? sender, EventArgs e)
{
if (Partie == null)
@ -53,6 +80,9 @@ public partial class PartieCommenceeVue : ContentView, INotifyPropertyChanged
partie.Jouer();
}
/// <summary>
/// Constructeur par défaut de la vue de la partie en cours.
/// </summary>
public PartieCommenceeVue()
{
InitializeComponent();

@ -1,22 +1,41 @@
namespace MauiSpark.Vues;
/// <summary>
/// Vue pour afficher le titre et la description des règles.
/// </summary>
public partial class ReglesVue : ContentView
{
/// <summary>
/// Identifie la propriété de dépendance pour le titre des règles.
/// </summary>
public static readonly BindableProperty TitreProperty = BindableProperty.Create(nameof(Titre), typeof(string), typeof(ReglesVue), default(string));
/// <summary>
/// Identifie la propriété de dépendance pour la description des règles.
/// </summary>
public static readonly BindableProperty DescriptionProperty = BindableProperty.Create(nameof(Description), typeof(string), typeof(ReglesVue), default(string));
/// <summary>
/// Obtient ou définit le titre des règles.
/// </summary>
public string Titre
{
get => (string)GetValue(TitreProperty);
set => SetValue(TitreProperty, value);
}
/// <summary>
/// Obtient ou définit la description des règles.
/// </summary>
public string Description
{
get => (string)GetValue(DescriptionProperty);
set => SetValue(DescriptionProperty, value);
}
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="ReglesVue"/>.
/// </summary>
public ReglesVue()
{
InitializeComponent();

@ -1,15 +1,27 @@
namespace MauiSpark.Vues;
/// <summary>
/// Vue pour afficher un titre.
/// </summary>
public partial class TitreVue : ContentView
{
/// <summary>
/// Identifie la propriété de dépendance pour le texte du titre.
/// </summary>
public static readonly BindableProperty TexteProperty = BindableProperty.Create(nameof(Texte), typeof(string), typeof(TitreVue), default(string));
/// <summary>
/// Obtient ou définit le texte du titre.
/// </summary>
public string Texte
{
get => (string)GetValue(TexteProperty);
set => SetValue(TexteProperty, value);
}
/// <summary>
/// Initialise une nouvelle instance de la classe <see cref="TitreVue"/>.
/// </summary>
public TitreVue()
{
InitializeComponent();

Loading…
Cancel
Save