fusion Nouveau core vers doc
continuous-integration/drone/push Build is failing Details

master
commit 8897ca4076

@ -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, PartieDemanderJoueurEventArgs e)
public static void DemanderNom(object? sender, PartieDemanderJoueurEventArgs e)
{
Console.WriteLine($"Joueur {e.Indice}");
Console.Write(">>> ");
@ -26,7 +26,9 @@ namespace ConsoleApp
Console.WriteLine();
e.JoueurDemande.SeConnecter(!string.IsNullOrEmpty(nom) ? Program.Manageur.DemanderJoueur(nom) : new Joueur($"Joueur {e.Indice}"));
Joueur joueur = !string.IsNullOrEmpty(nom) ? Program.Manageur.DemanderJoueur(nom) : new Robot();
e.JoueurDemande.SeConnecter(joueur);
}
@ -35,46 +37,50 @@ 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, PartieDebutPartieEventArgs e)
public static void CommencerLaPartie(object? sender, PartieDebutPartieEventArgs e)
{
Utils.DessinerSeparateur();
Console.WriteLine("La partie commence, bonne chance à tous !\n");
}
/// <summary>
/// Ecoute l'événement en rapport avec un nouveau tour.
/// <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, PartieNouveauTourEventArgs e)
public static void NouveauTour(object? sender, PartieNouveauTourEventArgs e)
{
Utils.DessinerSeparateur();
Console.WriteLine($"Tour {e.Tour} - {e.Joueur.Nom}\n");
Console.WriteLine($"{e.Nom} - Tour {e.Tour}\n");
(IReadOnlyList<IReadOnlyList<Jeton>> codes, IReadOnlyList<IReadOnlyList<Indicateur>> indicateurs) = e.Plateau.Grille;
Utils.DessinerPlateau(e.Plateau);
Console.WriteLine();
foreach(Jeton jeton in e.Code.Jetons)
Utils.DessinerPion(jeton.Couleur);
Code code = e.Code;
while(!code.Complet)
while (!e.Code.Complet)
{
Jeton? jeton = Utils.SaisirJeton(code.Taille);
Jeton? jeton = Utils.SaisirJeton(e.Code.Taille);
if (jeton.HasValue)
{
e.Code.AjouterJeton(jeton.Value);
Utils.DessinerPion(jeton.Value.Couleur);
code.AjouterJeton(jeton.Value);
}
else
{
e.Code.SupprimerDernierJeton();
Utils.SupprimerDernierJeton();
code.SupprimerDernierJeton();
}
}
e.Plateau.AjouterCode(code);
Console.WriteLine("\n");
if (!e.EstJoueur)
{
Task t = Task.Delay(3000);
t.GetAwaiter().GetResult();
}
e.Plateau.AjouterCode(e.Code);
}
/// <summary>
@ -82,10 +88,8 @@ 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, PartiePasserLaMainEventArgs e)
public static void AjouterCode(object? sender, PartiePasserLaMainEventArgs e)
{
Console.WriteLine();
Utils.DessinerSeparateur();
}
@ -96,7 +100,7 @@ namespace ConsoleApp
/// </summary>
public static void PartieTerminee(Object? sender, PartiePartieTermineeEventArgs e)
{
Joueur[] gagnants = e.Gagnants.ToArray();
string[] gagnants = e.Gagnants.ToArray();
if (gagnants.Length > 1)
{
@ -104,7 +108,7 @@ namespace ConsoleApp
}
else if (gagnants.Length == 1)
{
Console.WriteLine($"C'est une victoire de {gagnants[0].Nom}.");
Console.WriteLine($"C'est une victoire de {gagnants[0]}.");
}
else
{

@ -3,6 +3,7 @@ using CoreLibrary.Persistance;
using CoreLibrary.Regles;
using CoreLibrary;
using System.Diagnostics.CodeAnalysis;
using CoreLibrary.Joueurs;
namespace ConsoleApp
{

@ -1,4 +1,5 @@
using CoreLibrary.Exceptions;
using CoreLibrary.Evenements;
using CoreLibrary.Exceptions;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;

@ -1,22 +1,17 @@
namespace CoreLibrary.Evenements
using CoreLibrary.Joueurs;
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>
/// Nom du joueur se connectant.
/// </summary>
public string Nom { get; private init; }
public Joueur Joueur { get; private init; }
/// <summary>
/// Constructeur de JoueurSeConnecterEventArgs.
/// </summary>
/// <param name="nom">Nom du joueur qui se connecte.</param>
public JoueurSeConnecterEventArgs(string nom)
public JoueurSeConnecterEventArgs(Joueur joueur)
{
Nom = nom;
Joueur = joueur;
}
}
}

@ -0,0 +1,22 @@
using CoreLibrary.Core;
namespace CoreLibrary.Evenements
{
public class PartieDemanderJoueurJouerEventArgs : 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 PartieDemanderJoueurJouerEventArgs(int tour, string nom, Plateau plateau, Code code, bool estJoueur)
{
Tour = tour;
Nom = nom;
Plateau = plateau;
Code = code;
EstJoueur = estJoueur;
}
}
}

@ -1,5 +1,4 @@
using CoreLibrary.Core;
using CoreLibrary.Joueurs;
namespace CoreLibrary.Evenements
{
@ -12,35 +11,18 @@ namespace CoreLibrary.Evenements
/// Entier correspondant au nombre de tour.
/// </summary>
public int Tour { get; private init; }
/// <summary>
/// Chaîne de caractères correspondant au joueur courant.
/// </summary>
public string Joueur { get; private init; }
/// <summary>
/// Plateau du jeu en cours.
/// </summary>
public string Nom { get; private init; }
public Plateau Plateau { get; private init; }
/// <summary>
/// Code du jeu en cours.
/// </summary>
public Code Code { get; private init; }
public bool EstJoueur { get; private init; }
/// <summary>
/// Constructeur de PartieNouveauTourEventArgs, avec le tour, le joueur, le plateau et le code spécifiés.
/// </summary>
/// <param name="tour">Le nombre de tour passé.</param>
/// <param name="joueur">Le joueur courant.</param>
/// <param name="plateau">Le plateau actuel de la partie.</param>
/// <param name="code">Le dernier code ajouté.</param>
public PartieNouveauTourEventArgs(int tour, string joueur, Plateau plateau, Code code)
public PartieNouveauTourEventArgs(int tour, string nom, Plateau plateau, Code code, bool estJoueur)
{
Tour = tour;
Joueur = joueur;
Nom = nom;
Plateau = plateau;
Code = code;
EstJoueur = estJoueur;
}
}
}

@ -4,6 +4,7 @@ using CoreLibrary.Evenements;
using CoreLibrary.Regles;
using CoreLibrary.Statistiques;
using System.Runtime.Serialization;
using CoreLibrary.Core;
namespace CoreLibrary.Joueurs
{
@ -12,6 +13,7 @@ namespace CoreLibrary.Joueurs
/// </summary>
[DataContract]
[KnownType(typeof(ReglesClassiques))]
[KnownType(typeof(ReglesDifficiles))]
public class Joueur : IEstPersistant
{
/// <summary>
@ -19,11 +21,8 @@ namespace CoreLibrary.Joueurs
/// </summary>
public event EventHandler<JoueurSeConnecterEventArgs>? JoueurSeConnecter;
private void QuandJoueurSeConnecter() => JoueurSeConnecter?.Invoke(this, new JoueurSeConnecterEventArgs(Nom));
private void QuandJoueurSeConnecter(Joueur joueur) => JoueurSeConnecter?.Invoke(this, new JoueurSeConnecterEventArgs(joueur));
/// <summary>
/// Dictionnaire des statistiques du joueur avec les règles et les statistiques.
/// </summary>
[DataMember]
private Dictionary<(IRegles, Statistique), int> statistiques = new Dictionary<(IRegles, Statistique), int>();
@ -54,24 +53,23 @@ namespace CoreLibrary.Joueurs
Nom = nom;
}
/// <summary>
/// Connecte le joueur actuel avec les informations d'un autre joueur.
/// </summary>
/// <param name="joueur">Le joueur à partir duquel copier les informations.</param>
/// <returns>Renvoie le joueur actuel connecté.</returns>
/// <exception cref="JoueurDejaConnecteException">Lancée si le joueur est déjà connecté.</exception>
public Joueur SeConnecter(Joueur joueur)
public void SeConnecter(Joueur joueur)
{
if (EstConnecte)
throw new JoueurDejaConnecteException(this);
Nom = joueur.Nom;
statistiques = joueur.statistiques;
EstConnecte = true;
QuandJoueurSeConnecter(joueur);
}
QuandJoueurSeConnecter();
public void JouerPartie(Partie partie)
{
partie.PartieDemanderJoueurJouer += QuandDemanderJoueurJouer;
}
return this;
public virtual void QuandDemanderJoueurJouer(object? sender, PartieDemanderJoueurJouerEventArgs e)
{
if (e.Nom != Nom)
return;
}
/// <summary>
@ -80,14 +78,7 @@ namespace CoreLibrary.Joueurs
/// <returns>Renvoie une chaîne de caractères du nom du joueur.</returns>
public override string ToString() => Nom;
/// <summary>
/// Obtient 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>
/// <returns>Renvoie la valeur de la statistique.</returns>
public int Statistique(IRegles regles, Statistique statistique) =>
statistiques.GetValueOrDefault((regles, statistique), 0);
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.

@ -0,0 +1,106 @@
using CoreLibrary.Core;
using CoreLibrary.Evenements;
namespace CoreLibrary.Joueurs
{
public class Robot : Joueur
{
private static int nbRobots = 0;
private List<Code>? codesPossibles;
public Robot() :
base($"Naps {++nbRobots}")
{
}
public Robot(string nom) :
base(nom)
{
}
public override void QuandDemanderJoueurJouer(object? sender, PartieDemanderJoueurJouerEventArgs e)
{
if (e.Nom != Nom)
return;
if (codesPossibles == null)
{
codesPossibles = new List<Code>();
GenererTousCodesPossibles(e.Code.TailleMax);
}
SupprimerCodesImpossibles(e.Plateau);
for(int i = 0; i < e.Code.TailleMax; ++i)
e.Code.AjouterJeton(codesPossibles.ElementAt(0).Jetons[i]);
}
private void GenererTousCodesPossibles(int tailleCode)
{
Couleur[] couleurs = Enum.GetValues<Couleur>();
int nbLignes = (int)Math.Pow(couleurs.Length, tailleCode);
Jeton?[,] jetons = new Jeton?[nbLignes, tailleCode];
for(int indiceColonne = 0; indiceColonne < jetons.GetLength(1); ++indiceColonne)
{
int repetition = nbLignes / (int)Math.Pow(couleurs.Length, (indiceColonne + 1));
for (int indiceLigne = 0; indiceLigne < jetons.GetLength(0); ++indiceLigne)
{
jetons[indiceLigne, indiceColonne] = new Jeton(couleurs[(indiceLigne / repetition) % couleurs.Length]);
}
}
for (int i = 0; i < jetons.GetLength(0); ++i)
{
Code code = new Code(tailleCode);
for (int j = 0; j < jetons.GetLength(1); ++j)
{
code.AjouterJeton(jetons[i, j]!.Value);
}
codesPossibles!.Add(code);
}
}
private bool EstCodePossible(Plateau plateau, Code code)
{
for(int i = 0; i < plateau.Taille; ++i)
{
Code sonCode = new Code(code.TailleMax);
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)
)
return false;
}
return true;
}
private void SupprimerCodesImpossibles(Plateau plateau)
{
if (codesPossibles == null)
return;
List<int> indicesASupprimer = new List<int>();
for(int i = codesPossibles.Count - 1; i >= 0; --i)
{
if(!EstCodePossible(plateau, codesPossibles.ElementAt(i)))
indicesASupprimer.Add(i);
}
foreach (int indice in indicesASupprimer)
codesPossibles.RemoveAt(indice);
}
}
}

@ -2,7 +2,6 @@
using CoreLibrary.Joueurs;
using CoreLibrary.Regles;
using CoreLibrary.Statistiques;
using System.Text.RegularExpressions;
namespace CoreLibrary.Manageurs
{
@ -103,11 +102,11 @@ namespace CoreLibrary.Manageurs
{
partie.PartieDemanderJoueur += (sender, e) => Sauvegarder();
partie.PartieDebutPartie += (sender, e) => Sauvegarder();
partie.PartieNouveauTour += (sender, e) => Sauvegarder();
partie.PartieDemanderJoueurJouer += (sender, e) => Sauvegarder();
partie.PartiePasserLaMain += (sender, e) =>
{
DemanderJoueur(e.Joueur).IncrementerStatistique(partie.Regles, Statistique.CoupJoue);
DemanderJoueurExistant(e.Joueur)?.IncrementerStatistique(partie.Regles, Statistique.CoupJoue);
Sauvegarder();
};
@ -115,29 +114,23 @@ namespace CoreLibrary.Manageurs
{
if (e.Gagnants.Count == 1)
{
DemanderJoueur(e.Gagnants[0]).IncrementerStatistique(partie.Regles, Statistique.PartieGagnee);
DemanderJoueurExistant(e.Gagnants[0])?.IncrementerStatistique(partie.Regles, Statistique.PartieGagnee);
}
else
{
foreach (string gagnant in e.Gagnants)
DemanderJoueur(gagnant).IncrementerStatistique(partie.Regles, Statistique.PartieEgalite);
DemanderJoueurExistant(gagnant)?.IncrementerStatistique(partie.Regles, Statistique.PartieEgalite);
}
foreach (string perdant in e.Perdants)
{
DemanderJoueur(perdant).IncrementerStatistique(partie.Regles, Statistique.PartiePerdue);
DemanderJoueurExistant(perdant)?.IncrementerStatistique(partie.Regles, Statistique.PartiePerdue);
}
Sauvegarder();
};
}
/// <summary>
/// Demande un joueur avec son nom spécifié.
/// </summary>
/// <param name="nom">Nom du joueur que l'on souhaite trouver.</param>
/// <returns>Renvoie le joueur s'il a été trouvé. Sinon, crée un joueur avec le nom passé en paramètre.</returns>
public Joueur DemanderJoueur(string nom)
private Joueur? DemanderJoueurExistant(string nom)
{
foreach (Joueur joueur in joueurs)
{
@ -147,11 +140,19 @@ namespace CoreLibrary.Manageurs
}
}
Joueur nouveauJoueur = new Joueur(nom);
return null;
}
joueurs.Add(nouveauJoueur);
public Joueur DemanderJoueur(string nom)
{
Joueur? joueur = DemanderJoueurExistant(nom);
if (joueur == null)
{
joueur = new Joueur(nom);
joueurs.Add(joueur);
}
return nouveauJoueur;
return joueur;
}
}
}

@ -12,6 +12,7 @@ namespace CoreLibrary
/// </summary>
[DataContract]
[KnownType(typeof(ReglesClassiques))]
[KnownType(typeof(ReglesDifficiles))]
public class Partie : IEstPersistant
{
/// <summary>
@ -23,6 +24,7 @@ namespace CoreLibrary
/// Evénement déclencher lors du commencement d'une partie.
/// </summary>
public event EventHandler<PartieDebutPartieEventArgs>? PartieDebutPartie;
public event EventHandler<PartieDemanderJoueurJouerEventArgs>? PartieDemanderJoueurJouer;
/// <summary>
/// Evénement déclencher quand il s'agit d'un nouveau tour.
@ -49,33 +51,16 @@ namespace CoreLibrary
/// 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 de nouveau tour.
/// </summary>
private void QuandPartieNouveauTour() => PartieNouveauTour?.Invoke(this, new PartieNouveauTourEventArgs(Tour, joueurs.ElementAt(courant), plateaux.ElementAt(courant), new Code(Regles.TailleCode)));
/// <summary>
/// Méthode pour déclencher l'événement pour passer la main.
/// </summary>
private void QuandPartiePasserLaMain() => PartiePasserLaMain?.Invoke(this, new PartiePasserLaMainEventArgs(joueurs.ElementAt(courant)));
/// <summary>
/// Méthode pour déclencher l'événement si la partie est terminée.
/// </summary>
/// <param name="gagnants">Liste des joueurs gagnants.</param>
/// <param name="perdants">Liste des joueurs perdants.</param>
private void QuandPartieDemanderJoueurJouer(Code code) => PartieDemanderJoueurJouer?.Invoke(this, new PartieDemanderJoueurJouerEventArgs(Tour, Joueurs.ElementAt(courant), plateaux.ElementAt(courant), code, joueurs[Joueurs.ElementAt(courant)]));
private void QuandPartieNouveauTour(Code code) => PartieNouveauTour?.Invoke(this, new PartieNouveauTourEventArgs(Tour, Joueurs.ElementAt(courant), plateaux.ElementAt(courant), code, joueurs[Joueurs.ElementAt(courant)]));
private void QuandPartiePasserLaMain() => PartiePasserLaMain?.Invoke(this, new PartiePasserLaMainEventArgs(Joueurs.ElementAt(courant)));
private void QuandPartiePartieTerminee(IReadOnlyList<string> gagnants, IReadOnlyList<string> perdants) => PartiePartieTerminee?.Invoke(this, new PartiePartieTermineeEventArgs(gagnants, perdants));
/// <summary>
/// Liste des joueurs.
/// </summary>
[DataMember]
private readonly List<string> joueurs = new List<string>();
/// <summary>
/// Liste des plateaux.
/// </summary>
private readonly Dictionary<string, bool> joueurs = new Dictionary<string, bool>();
[DataMember]
private readonly List<Plateau> plateaux = new List<Plateau>();
@ -85,14 +70,8 @@ namespace CoreLibrary
[DataMember]
private int courant = 0;
/// <summary>
/// La liste des joueurs remplit.
/// </summary>
public IReadOnlyList<string> Joueurs => joueurs;
/// <summary>
/// Booléen pour suivre le statut de la partie.
/// </summary>
public IReadOnlyList<string> Joueurs => joueurs.Keys.ToList();
public IReadOnlyList<string> Robots => joueurs.Where(joueur => joueur.Value).Select(joueur => joueur.Key).ToList();
[DataMember]
public bool Termine { get; private set; } = false;
@ -131,9 +110,13 @@ namespace CoreLibrary
partie.PartieDemanderJoueur = null;
partie.PartieDebutPartie = null;
partie.PartieDemanderJoueurJouer = null;
partie.PartieNouveauTour = null;
partie.PartiePasserLaMain = null;
partie.PartiePartieTerminee = null;
foreach (string joueur in Joueurs)
(joueurs[joueur] ? new Joueur(joueur) : new Robot(joueur)).JouerPartie(this);
}
/// <summary>
@ -165,9 +148,11 @@ namespace CoreLibrary
/// <param name="e">L'instance de l'événement PlateauAjouterCodeEventArgs créée par Joueur.</param>
private void JoueurConnecte(object? sender, JoueurSeConnecterEventArgs e)
{
joueurs.Add(e.Nom);
joueurs.Add(e.Joueur.Nom, e.Joueur.GetType().Equals(typeof(Joueur)));
plateaux.Add(new Plateau(Regles.TailleCode, Regles.NbTour));
e.Joueur.JouerPartie(this);
if (joueurs.Count < Regles.NbJoueurs)
{
DemanderJoueur();
@ -201,7 +186,10 @@ namespace CoreLibrary
/// </summary>
private void NouveauTour()
{
QuandPartieNouveauTour();
Code code = new Code(Regles.TailleCode);
QuandPartieDemanderJoueurJouer(code);
QuandPartieNouveauTour(code);
}
/// <summary>
@ -244,9 +232,9 @@ namespace CoreLibrary
for (int i = 0; i < joueurs.Count; ++i)
{
if (plateaux.ElementAt(i).Victoire)
gagnants.Add(joueurs[i]);
gagnants.Add(Joueurs[i]);
else
perdants.Add(joueurs[i]);
perdants.Add(Joueurs[i]);
}
QuandPartiePartieTerminee(gagnants, perdants);

@ -47,6 +47,7 @@ namespace CoreLibrary.Persistance
return [];
Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), nomDossier));
var directory = Directory.GetCurrentDirectory();
if (!File.Exists(fichier))
return [];

@ -5,10 +5,12 @@
/// </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.
@ -24,5 +26,7 @@
/// Obtient la taille d'un code.
/// </summary>
int TailleCode { get; }
bool Equals(object? obj);
int GetHashCode();
}
}

@ -8,10 +8,12 @@ namespace CoreLibrary.Regles
[DataContract]
public class ReglesClassiques : IRegles
{
public int Indice => 1;
/// <summary>
/// Chaîne de caractères pour le nom des règles classiques.
/// </summary>
public string Nom => "Règles classiques";
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.
@ -27,5 +29,7 @@ namespace CoreLibrary.Regles
/// Taille du code maximale pour des règles classiques.
/// </summary>
public int TailleCode => 4;
public override bool Equals(object? obj) => obj == null ? false : obj is ReglesClassiques;
public override int GetHashCode() => Nom.GetHashCode();
}
}

@ -0,0 +1,17 @@
using System.Runtime.Serialization;
namespace CoreLibrary.Regles
{
[DataContract]
public class ReglesDifficiles : IRegles
{
public int Indice => 2;
public string Nom => "Règles difficiles";
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.";
public int NbJoueurs => 2;
public int NbTour => 12;
public int TailleCode => 6;
public override bool Equals(object? obj) => obj == null ? false : obj is ReglesDifficiles;
public override int GetHashCode() => Nom.GetHashCode();
}
}

@ -7,18 +7,27 @@
"Item1": {
"__type": "ReglesClassiques:#CoreLibrary.Regles"
},
"Item2": 3
"Item2": 0
},
"Value": 6
"Value": 2
},
{
"Key": {
"Item1": {
"__type": "ReglesClassiques:#CoreLibrary.Regles"
},
"Item2": 3
"Item2": 1
},
"Value": 2
"Value": 1
},
{
"Key": {
"Item1": {
"__type": "ReglesClassiques:#CoreLibrary.Regles"
},
"Item2": 2
},
"Value": 0
},
{
"Key": {
@ -27,7 +36,7 @@
},
"Item2": 3
},
"Value": 2
"Value": 5
}
]
},
@ -39,9 +48,27 @@
"Item1": {
"__type": "ReglesClassiques:#CoreLibrary.Regles"
},
"Item2": 3
"Item2": 0
},
"Value": 6
"Value": 1
},
{
"Key": {
"Item1": {
"__type": "ReglesClassiques:#CoreLibrary.Regles"
},
"Item2": 1
},
"Value": 5
},
{
"Key": {
"Item1": {
"__type": "ReglesClassiques:#CoreLibrary.Regles"
},
"Item2": 2
},
"Value": 2
},
{
"Key": {
@ -50,7 +77,39 @@
},
"Item2": 3
},
"Value": 1
"Value": 10
}
]
},
{
"Nom": "Camille",
"statistiques": [
{
"Key": {
"Item1": {
"__type": "ReglesClassiques:#CoreLibrary.Regles"
},
"Item2": 0
},
"Value": 3
},
{
"Key": {
"Item1": {
"__type": "ReglesClassiques:#CoreLibrary.Regles"
},
"Item2": 1
},
"Value": 5
},
{
"Key": {
"Item1": {
"__type": "ReglesClassiques:#CoreLibrary.Regles"
},
"Item2": 2
},
"Value": 6
},
{
"Key": {
@ -59,7 +118,7 @@
},
"Item2": 3
},
"Value": 1
"Value": 50
}
]
}

File diff suppressed because it is too large Load Diff

@ -3,15 +3,50 @@ using System.Globalization;
namespace MauiSpark.Convertisseurs
{
/// <summary>
/// Convertisseur de couleur qui implémente l'interface IValueConverter.
/// Cette classe permet de convertir des valeurs de type Couleur en valeurs de type Color (et vice versa).
/// </summary>
public class CouleurVersCouleurMAUI : IValueConverter
{
/// <summary>
/// Obtient la couleur rouge.
/// </summary>
public static Color Rouge { get; private set; } = Color.FromArgb("#F75353");
/// <summary>
/// Obtient la couleur verte.
/// </summary>
public static Color Vert { get; private set; } = Color.FromArgb("#53F769");
/// <summary>
/// Obtient la couleur bleue.
/// </summary>
public static Color Bleu { get; private set; } = Color.FromArgb("#535AF3");
/// <summary>
/// Obtient la couleur jaune.
/// </summary>
public static Color Jaune { get; private set; } = Color.FromArgb("#E9FE67");
/// <summary>
/// Obtient la couleur noire.
/// </summary>
public static Color Noir { get; private set; } = Color.FromArgb("#241E1E");
/// <summary>
/// Obtient la couleur blanche.
/// </summary>
public static Color Blanc { get; private set; } = Color.FromArgb("#FFFFFF");
/// <summary>
/// Convertit une valeur de type Couleur en une valeur de type Color.
/// </summary>
/// <param name="value">La valeur à convertir.</param>
/// <param name="targetType">Le type cible de la conversion.</param>
/// <param name="parameter">Un paramètre facultatif utilisé pour la conversion.</param>
/// <param name="culture">La culture à utiliser pour la conversion.</param>
/// <returns>Une valeur de type Color correspondant à la valeur de type Couleur.</returns>
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is not Couleur)
@ -36,6 +71,14 @@ namespace MauiSpark.Convertisseurs
}
}
/// <summary>
/// Convertit une valeur de type Color en une valeur de type Couleur.
/// </summary>
/// <param name="value">La valeur à convertir.</param>
/// <param name="targetType">Le type cible de la conversion.</param>
/// <param name="parameter">Un paramètre facultatif utilisé pour la conversion.</param>
/// <param name="culture">La culture à utiliser pour la conversion.</param>
/// <returns>Une valeur de type Couleur correspondant à la valeur de type Color.</returns>
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is not Color) return Couleur.Noir;

@ -3,23 +3,53 @@ using System.Globalization;
namespace MauiSpark.Convertisseurs
{
/// <summary>
/// Convertisseur d'indicateur en couleur qui implémente l'interface IValueConverter.
/// Cette classe permet de convertir des valeurs de type Indicateur en valeurs de type Color.
/// </summary>
public class IndicateurVersCouleurMAUI : IValueConverter
{
/// <summary>
/// Obtient la couleur noire.
/// </summary>
public static Color Noir { get; private set; } = Color.FromArgb("#000000");
/// <summary>
/// Obtient la couleur blanche.
/// </summary>
public static Color Blanc { get; private set; } = Color.FromArgb("#FFFFFF");
/// <summary>
/// Convertit une valeur de type Indicateur en une valeur de type Color.
/// </summary>
/// <param name="value">La valeur à convertir.</param>
/// <param name="targetType">Le type cible de la conversion.</param>
/// <param name="parameter">Un paramètre facultatif utilisé pour la conversion.</param>
/// <param name="culture">La culture à utiliser pour la conversion.</param>
/// <returns>Une valeur de type Color correspondant à la valeur de type Indicateur.</returns>
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is not Indicateur) return "black";
if (value is not Indicateur) return Noir;
switch (value)
{
case Indicateur.BonnePlace:
return "black";
return Noir;
case Indicateur.BonneCouleur:
return "white";
return Blanc;
default:
return "black";
return Noir;
}
}
/// <summary>
/// Convertit une valeur de type Color en une valeur de type Indicateur.
/// </summary>
/// <param name="value">La valeur à convertir.</param>
/// <param name="targetType">Le type cible de la conversion.</param>
/// <param name="parameter">Un paramètre facultatif utilisé pour la conversion.</param>
/// <param name="culture">La culture à utiliser pour la conversion.</param>
/// <returns>Non implémenté. Lance une NotImplementedException.</returns>
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();

@ -2,8 +2,21 @@
namespace MauiSpark.Convertisseurs
{
/// <summary>
/// Convertisseur de texte en texte en majuscules qui implémente l'interface IValueConverter.
/// Cette classe permet de convertir une chaîne de caractères en majuscules.
/// </summary>
public class TexteVersTexteMajuscule : IValueConverter
{
/// <summary>
/// Convertit une chaîne de caractères en majuscules.
/// </summary>
/// <param name="value">La valeur à convertir.</param>
/// <param name="targetType">Le type cible de la conversion.</param>
/// <param name="parameter">Un paramètre facultatif utilisé pour la conversion.</param>
/// <param name="culture">La culture à utiliser pour la conversion.</param>
/// <returns>Une chaîne de caractères en majuscules.</returns>
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is not string)
@ -12,6 +25,14 @@ namespace MauiSpark.Convertisseurs
return ((string)value).ToUpper();
}
/// <summary>
/// Non implémenté. Lance une NotImplementedException.
/// </summary>
/// <param name="value">La valeur à convertir.</param>
/// <param name="targetType">Le type cible de la conversion.</param>
/// <param name="parameter">Un paramètre facultatif utilisé pour la conversion.</param>
/// <param name="culture">La culture à utiliser pour la conversion.</param>
/// <returns>Non implémenté. Lance une NotImplementedException.</returns>
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();

@ -79,6 +79,9 @@
<Compile Update="Pages\ReglesPage.xaml.cs">
<DependentUpon>ReglesPage.xaml</DependentUpon>
</Compile>
<Compile Update="Pages\ClassementPage.xaml.cs">
<DependentUpon>ClassementPage.xaml</DependentUpon>
</Compile>
<Compile Update="Pages\VictoirePage.xaml.cs">
<DependentUpon>VictoirePage.xaml</DependentUpon>
</Compile>
@ -106,7 +109,7 @@
<MauiXaml Update="Pages\ReprendrePage.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Pages\TableauScore.xaml">
<MauiXaml Update="Pages\ClassementPage.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Pages\VictoirePage.xaml">
@ -121,9 +124,15 @@
<MauiXaml Update="Vues\ImageResultatVue.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Vues\IndicateurVue.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Vues\JetonVue.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Vues\ModeVue.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Vues\PartieCommenceeVue.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pages="clr-namespace:MauiSpark.Pages"
x:Class="MauiSpark.Pages.ClassementPage"
xmlns:vues="clr-namespace:MauiSpark.Vues"
Title="ClassementPage">
<ScrollView>
<VerticalStackLayout>
<FlexLayout Direction="Row" JustifyContent="SpaceAround" AlignContent="Center" VerticalOptions="Center" Margin="10, 50" >
<Image Source="star.png" WidthRequest="100" HorizontalOptions="End" VerticalOptions="Center" Margin="0"/>
<vues:TitreVue Texte="classement"/>
<Image Grid.Row="1" Source="star.png" WidthRequest="100" HorizontalOptions="Start" VerticalOptions="Center" Margin="0"/>
</FlexLayout>
<Grid RowDefinitions="*" ColumnDefinitions="*, 2*, *" Padding="50">
<Button x:Name="DiminuerRegles" Text="&lt;" Clicked="ChangerReglesPresse" VerticalOptions="Center" HorizontalOptions="Center"/>
<Label Grid.Column="1" x:Name="ReglesDifficiles" Text="{Binding Regles.Nom}" FontSize="Large" VerticalOptions="Center" HorizontalOptions="Center"/>
<Button x:Name="AugmenterRegles" Grid.Column="2" Text="&gt;" Clicked="ChangerReglesPresse" VerticalOptions="Center" HorizontalOptions="Center"/>
</Grid>
<ScrollView Orientation="Horizontal">
<VerticalStackLayout>
<Border Margin="20" StrokeThickness="2" StrokeShape="RoundRectangle 10">
<StackLayout
Orientation="Horizontal"
BindableLayout.ItemsSource="{Binding Titres}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Label Text="{Binding .}" FontSize="Medium" Margin="0, 20" WidthRequest="250" HorizontalTextAlignment="Center">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="StatistiquePressee"/>
</Label.GestureRecognizers>
</Label>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</Border>
<StackLayout BindableLayout.ItemsSource="{Binding Enfants}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Border Margin="20, 0" StrokeThickness="2" StrokeShape="RoundRectangle 10" Padding="0,20">
<StackLayout
Orientation="Horizontal"
BindableLayout.ItemsSource="{Binding Objets}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Label Text="{Binding .}" FontSize="Micro" WidthRequest="250" HorizontalTextAlignment="Center"/>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</Border>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</VerticalStackLayout>
</ScrollView>
</VerticalStackLayout>
</ScrollView>
</ContentPage>

@ -0,0 +1,137 @@
using CoreLibrary.Joueurs;
using CoreLibrary.Statistiques;
using CoreLibrary.Regles;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace MauiSpark.Pages
{
partial class Enfant
{
private readonly Classement classement;
public Joueur Joueur { get; set; }
public int Place => classement.Enfants.ToList().IndexOf(this) + 1;
public IEnumerable<int> Statistiques => Enum.GetValues<Statistique>()
.Select(statistique => Joueur.Statistique(classement.Regles, statistique));
public IEnumerable<string> Objets => new List<string>([$"{Place}", Joueur.Nom])
.Concat(Statistiques.Select(statistique => $"{statistique}"));
public Enfant(Joueur joueur, Classement classement)
{
this.classement = classement;
Joueur = joueur;
}
public override bool Equals(object? obj)
{
if (obj == null || obj is not Enfant)
return false;
return Joueur == ((Enfant)obj).Joueur;
}
public override int GetHashCode() => Joueur.GetHashCode();
}
partial class Classement : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
public void QuandProprieteChangee([CallerMemberName] string? propriete = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propriete));
private int indiceRegles = 0;
public IRegles Regles => ClassementPage.ToutesRegles.ElementAt(indiceRegles);
private Statistique statistique = Enum.GetValues<Statistique>().First();
public Statistique Statistique
{
get => statistique;
set
{
statistique = value;
QuandProprieteChangee(nameof(Enfants));
}
}
private bool inverser = true;
public bool Inverser {
get => inverser;
set
{
inverser = value;
QuandProprieteChangee(nameof(Enfants));
}
}
public IEnumerable<string> Titres => new List<string>(["Place", "Nom"]).Concat(
Enum.GetValues<Statistique>().Select(
statistique => string.Concat((Enum.GetName(typeof(Statistique), statistique) ?? "").Select(
(lettre, indice) => indice > 0 && char.IsUpper(lettre) ? $" {lettre}" : $"{lettre}")
)
)
);
public IEnumerable<Enfant> Enfants => Inverser ?
MauiProgram.Manageur.Joueurs
.OrderBy(joueur => joueur.Statistique(Regles, Statistique))
.Select(joueur => new Enfant(joueur, this)).Reverse() :
MauiProgram.Manageur.Joueurs
.OrderBy(joueur => joueur.Statistique(Regles, Statistique))
.Select(joueur => new Enfant(joueur, this));
public void IncrementerRegles(int valeur)
{
if ((indiceRegles += valeur) < 0)
indiceRegles = ClassementPage.ToutesRegles.Count() - 1;
else if (indiceRegles >= ClassementPage.ToutesRegles.Count())
indiceRegles = 0;
QuandProprieteChangee(nameof(Regles));
QuandProprieteChangee(nameof(Enfants));
}
}
public partial class ClassementPage : ContentPage
{
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);
public ClassementPage()
{
InitializeComponent();
NavigationPage.SetHasNavigationBar(this, false);
BindingContext = new Classement();
}
public void ChangerReglesPresse(object sender, EventArgs e)
{
((Classement)BindingContext).IncrementerRegles(sender == DiminuerRegles ? -1 : 1);
}
public void StatistiquePressee(object sender, EventArgs e)
{
if (sender is not Label || !Enum.IsDefined(typeof(Statistique), ((Label)sender).Text.Replace(" ", "")))
return;
Statistique statistique = Enum.Parse<Statistique>(((Label)sender).Text.Replace(" ", ""));
Classement classement = (Classement)BindingContext;
if (classement.Statistique == statistique)
{
classement.Inverser = !classement.Inverser;
return;
}
classement.Inverser = true;
classement.Statistique = statistique;
}
}
}

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:Views="clr-namespace:MauiSpark.Views"
x:Class="MauiSpark.Pages.ConnexionPage"
xmlns:vues="clr-namespace:MauiSpark.Vues"
Title="Connexion">
@ -37,10 +36,17 @@
</Grid>
</VerticalStackLayout>
<Grid Grid.Row="2" VerticalOptions="Center" RowDefinitions="*" ColumnDefinitions="*, *">
<Button
VerticalOptions="Center"
Grid.Row="2"
Text="Se connecter"
Clicked="QuandSeConnecterPresse"/>
<Button
Grid.Column="1"
VerticalOptions="Center"
Text="Robot"
Clicked="QuandRobotPresse"/>
</Grid>
</Grid>
</ContentPage>

@ -55,13 +55,26 @@ public partial class ConnexionPage : ContentPage
if (joueurDemande == null || indice == null)
return;
Joueur joueur;
if (string.IsNullOrEmpty(Nom.Text))
{
joueurDemande.SeConnecter(new Joueur($"Joueur {indice.Value}"));
joueur = new Joueur($"Joueur {indice.Value}");
}
else
{
joueurDemande.SeConnecter(MauiProgram.Manageur.DemanderJoueur(Nom.Text));
joueur = MauiProgram.Manageur.DemanderJoueur(Nom.Text);
}
joueurDemande.SeConnecter(joueur);
}
private void QuandRobotPresse(object sender, EventArgs e)
{
if (joueurDemande == null || indice == null)
return;
Robot robot = new Robot();
joueurDemande.SeConnecter(robot);
}
}

@ -5,16 +5,17 @@
xmlns:vues="clr-namespace:MauiSpark.Vues"
Title="ModePage">
<Grid
ColumnDefinitions="*"
RowDefinitions="*, *">
<ScrollView>
<StackLayout>
<vues:TitreVue Texte="mode de jeu"/>
<Button
x:Name="ReglesClassiques"
Grid.Row="1"
Text="Règles classiques"
Clicked="QuandReglesPresse"/>
</Grid>
<StackLayout BindableLayout.ItemsSource="{Binding .}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<vues:ModeVue Regles="{Binding .}"/>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</StackLayout>
</ScrollView>
</ContentPage>

@ -1,4 +1,3 @@
using CoreLibrary;
using CoreLibrary.Regles;
namespace MauiSpark.Pages;
@ -16,28 +15,11 @@ public partial class ModePage : ContentPage
{
NavigationPage.SetHasNavigationBar(this, false);
InitializeComponent();
}
BindingContext = typeof(IRegles).Assembly.GetTypes()
.Where(type => typeof(IRegles).IsAssignableFrom(type) && type.IsClass)
.Select(type => (Activator.CreateInstance(type) as IRegles)!)
.OrderBy(regles => regles.Indice);
/// <summary>
/// Méthode déclenchée lorsque le bouton des règles est pressé.
/// Crée une nouvelle partie selon les règles sélectionnées et démarre le jeu.
/// </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 QuandReglesPresse(Object sender, EventArgs e)
{
Partie partie;
if (sender.Equals(ReglesClassiques))
partie = MauiProgram.Manageur.NouvellePartie(new ReglesClassiques());
else
return;
partie.PartieDemanderJoueur += new ConnexionPage().QuandDemanderNom;
partie.PartieNouveauTour += new PlateauPage().QuandNouveauTour;
partie.PartiePartieTerminee += new VictoirePage().QuandPartieTerminee;
partie.Jouer();
InitializeComponent();
}
}

@ -36,11 +36,14 @@
<BindableLayout.ItemTemplate>
<DataTemplate>
<Label Text="O"/>
<vues:IndicateurVue Couleur="{Binding ., Converter={StaticResource IndicateurVersCouleurMAUI}}"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"/>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
<StackLayout
Orientation="Horizontal"
Grid.Column="1"
@ -112,13 +115,13 @@
<BoxView Grid.Row="1" Grid.ColumnSpan="6" HeightRequest="1" VerticalOptions="Center"/>
<vues:JetonVue Couleur="{x:Static conv:CouleurVersCouleurMAUI.Rouge}" Code="{Binding Source={x:Reference plateauPage}, Path=BindingContext.Code}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2"></vues:JetonVue>
<vues:JetonVue Couleur="{x:Static conv:CouleurVersCouleurMAUI.Vert}" Code="{Binding Source={x:Reference plateauPage}, Path=BindingContext.Code}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Column="2" Grid.Row="2" Grid.ColumnSpan="2"/>
<vues:JetonVue Couleur="{x:Static conv:CouleurVersCouleurMAUI.Bleu}" Code="{Binding Source={x:Reference plateauPage}, Path=BindingContext.Code}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Column="4" Grid.Row="2" Grid.ColumnSpan="2"/>
<vues:JetonVue Couleur="{x:Static conv:CouleurVersCouleurMAUI.Rouge}" EstJoueur="{Binding Source={x:Reference plateauPage}, Path=BindingContext.EstJoueur}" Code="{Binding Source={x:Reference plateauPage}, Path=BindingContext.Code}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2"/>
<vues:JetonVue Couleur="{x:Static conv:CouleurVersCouleurMAUI.Vert}" EstJoueur="{Binding Source={x:Reference plateauPage}, Path=BindingContext.EstJoueur}" Code="{Binding Source={x:Reference plateauPage}, Path=BindingContext.Code}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Column="2" Grid.Row="2" Grid.ColumnSpan="2"/>
<vues:JetonVue Couleur="{x:Static conv:CouleurVersCouleurMAUI.Bleu}" EstJoueur="{Binding Source={x:Reference plateauPage}, Path=BindingContext.EstJoueur}" Code="{Binding Source={x:Reference plateauPage}, Path=BindingContext.Code}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Column="4" Grid.Row="2" Grid.ColumnSpan="2"/>
<vues:JetonVue Couleur="{x:Static conv:CouleurVersCouleurMAUI.Jaune}" Code="{Binding Source={x:Reference plateauPage}, Path=BindingContext.Code}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2"/>
<vues:JetonVue Couleur="{x:Static conv:CouleurVersCouleurMAUI.Noir}" Code="{Binding Source={x:Reference plateauPage}, Path=BindingContext.Code}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Column="2" Grid.Row="3" Grid.ColumnSpan="2"/>
<vues:JetonVue Couleur="{x:Static conv:CouleurVersCouleurMAUI.Blanc}" Code="{Binding Source={x:Reference plateauPage}, Path=BindingContext.Code}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Column="4" Grid.Row="3" Grid.ColumnSpan="2"/>
<vues:JetonVue Couleur="{x:Static conv:CouleurVersCouleurMAUI.Jaune}" EstJoueur="{Binding Source={x:Reference plateauPage}, Path=BindingContext.EstJoueur}" Code="{Binding Source={x:Reference plateauPage}, Path=BindingContext.Code}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2"/>
<vues:JetonVue Couleur="{x:Static conv:CouleurVersCouleurMAUI.Noir}" EstJoueur="{Binding Source={x:Reference plateauPage}, Path=BindingContext.EstJoueur}" Code="{Binding Source={x:Reference plateauPage}, Path=BindingContext.Code}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Column="2" Grid.Row="3" Grid.ColumnSpan="2"/>
<vues:JetonVue Couleur="{x:Static conv:CouleurVersCouleurMAUI.Blanc}" EstJoueur="{Binding Source={x:Reference plateauPage}, Path=BindingContext.EstJoueur}" Code="{Binding Source={x:Reference plateauPage}, Path=BindingContext.Code}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Column="4" Grid.Row="3" Grid.ColumnSpan="2"/>
</Grid>
</Border>

@ -1,7 +1,6 @@
using CoreLibrary.Core;
using CoreLibrary.Evenements;
using CoreLibrary.Exceptions;
using CoreLibrary.Joueurs;
namespace MauiSpark.Pages;
@ -30,6 +29,7 @@ internal class Tour
/// 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.
@ -38,8 +38,9 @@ internal class Tour
public Tour(PartieNouveauTourEventArgs e)
{
Numero = $"Tour {e.Tour}";
Joueur = e.Joueur;
Joueur = e.Nom;
Code = e.Code;
EstJoueur = e.EstJoueur;
(IReadOnlyList<IReadOnlyList<Jeton>> jetons, IReadOnlyList < IReadOnlyList < Indicateur >> indicateurs) = e.Plateau.Grille;
@ -67,6 +68,7 @@ public partial class PlateauPage : ContentPage
{
private Code? code;
private Plateau? plateau;
private bool? estJoueur;
/// <summary>
/// Constructeur de la page du plateau de jeu.
@ -105,6 +107,7 @@ public partial class PlateauPage : ContentPage
code = e.Code;
plateau = e.Plateau;
estJoueur = e.EstJoueur;
BindingContext = new Tour(e);
}
@ -119,7 +122,7 @@ public partial class PlateauPage : ContentPage
{
try
{
if(code != null)
if(code != null && estJoueur.HasValue && estJoueur.Value)
code.SupprimerDernierJeton();
}
catch(CodeVideException)

@ -9,11 +9,16 @@
<ScrollView>
<StackLayout>
<vues:TitreVue Texte="Règles"/>
<Grid RowDefinitions="*,*" ColumnDefinitions="*,*">
<vues:IndicateurVue Couleur="White" WidthRequest="100" HeightRequest="100" />
<Label Grid.Row="1" FontSize="Medium" Text="Cette indicateur indique une bonne couleur" HorizontalOptions="Center"/>
<vues:IndicateurVue Grid.Column="1" Couleur="Black" WidthRequest="100" HeightRequest="100"/>
<Label Grid.Row="1" Grid.Column="1" FontSize="Medium" Text="Cette indicateur indique une bonne place" HorizontalOptions="Center"/>
</Grid>
<StackLayout BindableLayout.ItemsSource="{Binding .}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<vues:ReglesVue Titre="{Binding Titre}" Description="{Binding Description}" Margin="20"/>
<vues:ReglesVue Titre="{Binding Nom}" Description="{Binding Description}" Margin="20"/>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>

@ -1,43 +1,17 @@
namespace MauiSpark.Pages;
/// <summary>
/// Page affichant les règles du jeu.
/// </summary>
internal class Regles
{
/// <summary>
/// Obtient ou définit le titre des règles.
/// </summary>
public string Titre { get; init; } = "";
using CoreLibrary.Regles;
/// <summary>
/// Obtient ou définit la description des règles.
/// </summary>
public string Description { get; init; } = "";
}
namespace MauiSpark.Pages;
/// <summary>
/// Page affichant les règles du jeu.
/// </summary>
public partial class ReglesPage : ContentPage
{
private static readonly Regles reglesClassiques = new Regles()
{
Titre = "Règles classiques",
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>
/// Constructeur de la page affichant les règles du jeu.
/// Initialise les paramètres de navigation et les composants de la page.
/// </summary>
public ReglesPage()
{
NavigationPage.SetHasNavigationBar(this, false);
BindingContext = (Regles[])[
reglesClassiques
];
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,18 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pages="clr-namespace:MauiSpark.Pages"
x:Class="MauiSpark.Pages.TableauScore"
Title="TableauScore">
<ScrollView>
<VerticalStackLayout>
<FlexLayout Direction="Row" JustifyContent="SpaceAround" AlignContent="Center" VerticalOptions="Center" Margin="10, 50" >
<Image Source="star.png" WidthRequest="100" HorizontalOptions="End" VerticalOptions="Center" Margin="0"/>
<Label Text="Scoreboard" Style="{StaticResource TexteTitre}" Margin="0" />
<Image Grid.Row="1" Source="star.png" WidthRequest="100" HorizontalOptions="Start" VerticalOptions="Center" Margin="0"/>
</FlexLayout>
</VerticalStackLayout>
</ScrollView>
</ContentPage>

@ -1,11 +0,0 @@
namespace MauiSpark.Pages;
public partial class TableauScore : ContentPage
{
public TableauScore()
{
NavigationPage.SetHasNavigationBar(this, false);
InitializeComponent();
}
}

@ -29,7 +29,7 @@
Margin="20"
Padding="20">
<Label HorizontalOptions="Center" Text="{Binding Texte}"/>
<Label FontSize="Large" HorizontalOptions="Center" Text="{Binding Texte}"/>
</Border>
<Button

@ -16,8 +16,14 @@
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource TexteSombre}, Dark={StaticResource TexteClair}}"/>
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource FondSecondaireClair}, Dark={StaticResource FondSecondaireSombre}}" />
<Setter Property="FontSize" Value="Large"/>
<Setter Property="HeightRequest" Value="80"/>
<Setter Property="WidthRequest" Value="500"/>
<Setter Property="HeightRequest" Value="60"/>
<Setter Property="WidthRequest" Value="300"/>
</Style>
<Style x:Key="ButtonClassement" TargetType="Button">
<Setter Property="BorderColor" Value="{AppThemeBinding Light={StaticResource FondSecondaireClair}, Dark={StaticResource FondSecondaireSombre}}"/>
<Setter Property="WidthRequest" Value="150"/>
<Setter Property="FontSize" Value="20"/>
</Style>
<Style TargetType="Frame">

@ -11,6 +11,6 @@ public partial class BoutonClassementVue : ContentView
private void QuandClassementClique(Object? sender, EventArgs e)
{
Navigation.PushAsync(new TableauScore());
Navigation.PushAsync(new ClassementPage());
}
}

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiSpark.Vues.IndicateurVue"
x:Name="indicateurVue">
<Grid
x:Name="Grid"
SizeChanged="QuandTailleChangee"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<Rectangle
x:Name="Carre"
Fill="{Binding Couleur, Source={x:Reference indicateurVue}}">
</Rectangle>
</Grid>
</ContentView>

@ -0,0 +1,28 @@
using CoreLibrary.Core;
using MauiSpark.Convertisseurs;
using System.Globalization;
namespace MauiSpark.Vues;
public partial class IndicateurVue : ContentView
{
public static readonly BindableProperty CouleurProperty = BindableProperty.Create(nameof(Couleur), typeof(Color), typeof(IndicateurVue), default(Color));
public Color Couleur
{
get => (Color)GetValue(CouleurProperty);
set => SetValue(CouleurProperty, value);
}
public IndicateurVue()
{
InitializeComponent();
BindingContext = this;
}
private void QuandTailleChangee(object sender, EventArgs e)
{
double taille = Math.Min(Grid.Width, Grid.Height) / 2;
Carre.WidthRequest = Carre.HeightRequest = taille;
}
}

@ -9,6 +9,7 @@ public partial class JetonVue : ContentView
{
public static readonly BindableProperty CouleurProperty = BindableProperty.Create(nameof(Couleur), typeof(Color), typeof(JetonVue), default(Color));
public static readonly BindableProperty CodeProperty = BindableProperty.Create(nameof(Code), typeof(Code), typeof(JetonVue), null);
public static readonly BindableProperty EstJoueurProperty = BindableProperty.Create(nameof(EstJoueur), typeof(bool), typeof(JetonVue), true);
public Color Couleur
{
@ -22,6 +23,12 @@ public partial class JetonVue : ContentView
set => SetValue(CodeProperty, value);
}
public bool EstJoueur
{
get => (bool)GetValue(EstJoueurProperty);
set => SetValue(EstJoueurProperty, value);
}
public JetonVue()
{
InitializeComponent();
@ -36,7 +43,7 @@ public partial class JetonVue : ContentView
private void JetonPresse(object sender, EventArgs e)
{
if (Cercle == null || !sender.Equals(Cercle) || Code == null || Application.Current == null || Application.Current.MainPage == null)
if (Cercle == null || !sender.Equals(Cercle) || Code == null || Application.Current == null || Application.Current.MainPage == null || !EstJoueur)
return;
Couleur couleur = (Couleur)new CouleurVersCouleurMAUI().ConvertBack(((SolidColorBrush)Cercle.Fill).Color, typeof(Couleur), null, CultureInfo.InvariantCulture);

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiSpark.Vues.ModeVue"
x:Name="modeVue">
<Button
Text="{Binding Regles.Nom, Source={x:Reference modeVue}}"
Clicked="QuandReglesPresse"
Margin="0, 50"/>
</ContentView>

@ -0,0 +1,32 @@
using CoreLibrary;
using CoreLibrary.Regles;
using MauiSpark.Pages;
namespace MauiSpark.Vues;
public partial class ModeVue : ContentView
{
public static readonly BindableProperty ReglesProperty = BindableProperty.Create(nameof(Regles), typeof(IRegles), typeof(ModeVue), null);
public IRegles Regles
{
get => (IRegles)GetValue(ReglesProperty);
set => SetValue(ReglesProperty, value);
}
public ModeVue()
{
InitializeComponent();
}
private void QuandReglesPresse(Object sender, EventArgs e)
{
Partie partie = MauiProgram.Manageur.NouvellePartie(Regles);
partie.PartieDemanderJoueur += new ConnexionPage().QuandDemanderNom;
partie.PartiePartieTerminee += new VictoirePage().QuandPartieTerminee;
partie.PartieNouveauTour += new PlateauPage().QuandNouveauTour;
partie.Jouer();
}
}

@ -47,8 +47,8 @@ public partial class PartieCommenceeVue : ContentView, INotifyPropertyChanged
Partie partie = MauiProgram.Manageur.ChargerPartie(Partie);
partie.PartieDemanderJoueur += new ConnexionPage().QuandDemanderNom;
partie.PartieNouveauTour += new PlateauPage().QuandNouveauTour;
partie.PartiePartieTerminee += new VictoirePage().QuandPartieTerminee;
partie.PartieNouveauTour += new PlateauPage().QuandNouveauTour;
partie.Jouer();
}

Loading…
Cancel
Save