You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mastermind/Sources/CoreLibrary/Core/Plateau.cs

139 lines
4.9 KiB

using CoreLibrary.Exceptions;
using CoreLibrary.Evenements;
using System.Runtime.Serialization;
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)
throw new TailleCodeException(tailleCode);
if (taillePlateau < 0)
throw new TailleGrilleException(taillePlateau);
TailleMax = taillePlateau;
TailleMaxCode = tailleCode;
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);
Couleur[] couleurs = Enum.GetValues<Couleur>();
while (!code.Complet)
{
code.AjouterJeton(
new Jeton(couleurs[RandomNumberGenerator.GetInt32(0, couleurs.Length)])
);
}
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)
throw new CodeIncompletException();
if (Complet)
throw new GrilleCompleteException();
codes.Add(code);
IReadOnlyList<Indicateur> indicateursCode = codeSecret.Comparer(code);
indicateurs.Add(indicateursCode.ToList());
if (!Victoire && indicateursCode.Count(indicateur => indicateur == Indicateur.BonnePlace) == TailleMaxCode)
Victoire = true;
QuandPlateauAjouterCode();
}
}
}