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/Partie.cs

256 lines
8.5 KiB

using CoreLibrary.Persistance;
using CoreLibrary.Core;
using CoreLibrary.Evenements;
using CoreLibrary.Joueurs;
using CoreLibrary.Regles;
using System.Runtime.Serialization;
namespace CoreLibrary
{
/// <summary>
/// Classe représentant une partie.
/// </summary>
[DataContract]
[KnownType(typeof(ReglesClassiques))]
public class Partie : IEstPersistant
{
/// <summary>
/// Evénement déclencher quand il faut ajouter un joueur.
/// </summary>
public event EventHandler<PartieDemanderJoueurEventArgs>? PartieDemanderJoueur;
/// <summary>
/// Evénement déclencher lors du commencement d'une partie.
/// </summary>
public event EventHandler<PartieDebutPartieEventArgs>? PartieDebutPartie;
/// <summary>
/// Evénement déclencher quand il s'agit d'un nouveau tour.
/// </summary>
public event EventHandler<PartieNouveauTourEventArgs>? PartieNouveauTour;
/// <summary>
/// Evénement déclencher quand on passe la main au joueur suivant.
/// </summary>
public event EventHandler<PartiePasserLaMainEventArgs>? PartiePasserLaMain;
/// <summary>
/// Evénement déclencher quand 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 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 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>
[DataMember]
private readonly List<Plateau> plateaux = new List<Plateau>();
/// <summary>
/// Entier correspondant au joueur courant.
/// </summary>
[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>
[DataMember]
public bool Termine { get; private set; } = false;
/// <summary>
/// Entier correspondant au nombre de tour.
/// </summary>
[DataMember]
public int Tour { get; private set; } = 0;
/// <summary>
/// Regles utiliser dans la partie.
/// </summary>
[DataMember]
public IRegles Regles { get; private init; }
/// <summary>
/// Premier constructeur de partie.
/// </summary>
/// <param name="regles">Les règles de la partie.</param>
public Partie(IRegles regles)
{
Regles = regles;
}
/// <summary>
/// Deuxième constructeur de partie.
/// </summary>
/// <param name="partie">La partie à reprendre en cours.</param>
public Partie(Partie partie)
{
joueurs = partie.joueurs;
plateaux = partie.plateaux;
courant = partie.courant;
Tour = partie.Tour;
Regles = partie.Regles;
partie.PartieDemanderJoueur = null;
partie.PartieDebutPartie = null;
partie.PartieNouveauTour = null;
partie.PartiePasserLaMain = null;
partie.PartiePartieTerminee = null;
}
/// <summary>
/// Lance le déroulement de la partie.
/// </summary>
public void Jouer()
{
if (joueurs.Count != Regles.NbJoueurs)
DemanderJoueur();
else
DebutPartie();
}
/// <summary>
/// Demande un joueur.
/// </summary>
private void DemanderJoueur()
{
Joueur joueurDemande = new Joueur();
joueurDemande.JoueurSeConnecter += JoueurConnecte;
QuandPartieDemanderJoueur(joueurDemande);
}
/// <summary>
/// Connecte les joueurs à la partie.
/// </summary>
/// <param name="sender">La class qui appelle l'évenement; ici Joueur.</param>
/// <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);
plateaux.Add(new Plateau(Regles.TailleCode, Regles.NbTour));
if (joueurs.Count < Regles.NbJoueurs)
{
DemanderJoueur();
}
else
{
DebutPartie();
}
}
/// <summary>
/// Lance le début de la partie.
/// </summary>
private void DebutPartie()
{
if (Tour == 0)
++Tour;
foreach (Plateau plateau in plateaux)
{
plateau.PlateauAjouterCode += PlateauAjouterCode;
}
QuandPartieDebutPartie();
NouveauTour();
}
/// <summary>
/// Permet de changer de tour.
/// </summary>
private void NouveauTour()
{
QuandPartieNouveauTour();
}
/// <summary>
/// Ajoute un code au plateau.
/// </summary>
/// <param name="sender">La class qui appelle l'évenement; 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();
if (courant + 1 == joueurs.Count && (e.Plateau.Complet || plateaux.Any(plateau => plateau.Victoire)))
{
PartieTerminee();
}
else
{
if (courant + 1 == joueurs.Count)
{
++Tour;
courant = 0;
}
else
++courant;
NouveauTour();
}
}
/// <summary>
/// La partie est terminée.
/// </summary>
private void PartieTerminee()
{
Termine = true;
List<string> gagnants = new List<string>();
List<string> perdants = new List<string>();
for (int i = 0; i < joueurs.Count; ++i)
{
if (plateaux.ElementAt(i).Victoire)
gagnants.Add(joueurs[i]);
else
perdants.Add(joueurs[i]);
}
QuandPartiePartieTerminee(gagnants, perdants);
}
}
}