public abstract class Carte { /// <summary> /// Constructeur protégé, seules les classes filles pourront l'appeler /// </summary> /// <param name="CheminDeLimage"></param> /// <param name="LesPoints"></param> protected Carte(string CheminDeLimage, int LesPoints) { CheminImage = CheminDeLimage; Points = LesPoints; } /// <summary> /// Chemin vers l'image de la face /// </summary> /// <remarks>C'est la couche Vue qui s'occupera de l'afficher</remarks> public string CheminImage {get; private set; }//private set, car seule l'instance peut affecter/modifier son image /// <summary> /// Nombre de points marqués avec cette carte /// </summary> public int Points { get; protected set; }//private set, car seule l'instance ou une instance dérivée peut affecter/modifier les points protected Joueur leJoueur; /// <summary> /// Prend la première carte de la pioche et la met dans la main d'un joueur /// </summary> /// <param name="LeJoueur"></param> public void Piocher(Joueur LeJoueur) { leJoueur = LeJoueur; //ToDo implémenter la pioche } /// <summary> /// Joue la carte /// </summary> protected void Jouer() { //ToDo implémenter le jeu } /// <summary> /// Jette une carte de la main du joueur vers la défausse /// </summary> public void Defausse() { //ToDo implémenter la défausse } }
//ToDo implémenter la défausse? C’est simple, nous n’avons pas encore défini ce qu’est un Joueur, la défausse et la pioche.
class Joueur { }
public class Kilometre:Carte { public Kilometre(string CheminDeLimage, int LesKilometres):base(CheminDeLimage, LesKilometres)//on appelle le constructeur de Carte { Distance = LesKilometres; } public int Distance { get; private set; } public new void Jouer() { base.Jouer();//appel du code de la classe mère } /// <summary> /// Réécriture de ToString pour afficher le nombre de kilomètres /// </summary> /// <returns></returns> public override string ToString() { return Distance.ToString() + " km"; } } public class Embuche:Carte { public Embuche(string CheminImage, TypeEmbuche LeType):base(CheminImage,0) { Type = LeType; } public TypeEmbuche Type { get; private set; } /// <summary> /// Une embûche est lancée à un autre joueur /// </summary> /// <param name="Cible"></param> public void Jouer(Joueur Cible) { //ToDo implémenter le jeu de l'embuche } /// <summary> /// Réécriture de ToString pour afficher le nom de l'embûche /// </summary> /// <returns></returns> public override string ToString() { return Type.ToString(); } } /// <summary> /// Enumération permettant de distinguer le type de chaque carte Embuche /// </summary> public enum TypeEmbuche { FeuRouge, LimitationVitesse, Crevaison, PanneEssence, Accident } public class Parade:Carte { public Parade(string CheminImage, TypeEmbuche LeType): base(CheminImage, 0) { EmbucheParee = LeType; } public TypeEmbuche EmbucheParee { get; private set; }//plutôt que de définir un lien entre un type de parade et le type d'embuche, il est aussi simple définir l'embuche parée /// <summary> /// Réécriture de ToString pour afficher le nom de la parade /// </summary> /// <returns></returns> public override string ToString() { switch(EmbucheParee) { case TypeEmbuche.Accident: return "Réparation"; case TypeEmbuche.Crevaison: return "Roue de secours"; case TypeEmbuche.FeuRouge: return "Feu vert"; case TypeEmbuche.LimitationVitesse: return "Fin de limitation"; case TypeEmbuche.PanneEssence: return "Station essence"; default: //on est obligé de mettre un default ou après le switch return quelque chose car ToString retourne un résultat, et même si on a testé toutes les options de TypeEmbuche, le compilateur considère qu'un cas non prévu pourrait se présenter et qu'il n'y aurait alors pas de résultat return "Erreur"; } } } public class Botte : Carte { public Botte(string CheminImage, TypeEmbuche LeType) : base(CheminImage, 100) { EmbucheImmunisee = LeType; } public TypeEmbuche EmbucheImmunisee { get; private set; } /// <summary> /// Cette méthode est quand la carte se joue elle-même /// </summary> public void CoupFourre() { this.Points += 300; Piocher(this.leJoueur); //ToDo implémenter le fait que ce soit au tour de ce joueur. } /// <summary> /// Réécriture de ToString pour afficher le nom de la botte /// </summary> /// <returns></returns> public override string ToString() { switch (EmbucheImmunisee) { case TypeEmbuche.Accident: return "As du volant"; case TypeEmbuche.Crevaison: return "Roue increvable"; case TypeEmbuche.FeuRouge: case TypeEmbuche.LimitationVitesse: return "Camion de pompier"; case TypeEmbuche.PanneEssence: return "Citerne d'essence"; } //on est obligé de mettre un default ou après le switch return quelque chose car ToString retourne un résultat, et même si on a testé toutes les options de TypeEmbuche, le compilateur considère qu'un cas non prévu pourrait se présenter et qu'il n'y aurait alors pas de résultat return "Erreur"; } }
static, je le traduis par l’expression classe partagée car statique n'est pas très parlant et qu'en VB.Net, le mot clé utilisé (shared) veut dire partagé.
cos = Math.Cos(10);
pi = Math.PI;
public class Joueur { public delegate void EvenementKilometres(Joueur LeJoueur, int Kilometres);//signature de l'évènement public event EvenementKilometres JaiGagne;//évènement signalant que la distance est atteinte public event EvenementKilometres DistanceDepassee;//évènement signalant que la distance est partagée public delegate void EvenementEmbuche(Joueur LeJoueur);//signature de l'évènement public event EvenementEmbuche EmbucheRecue;//évènement signalant une embuche reçue public event EvenementEmbuche CoupFourre;//évènement signalant un coup fourré public event EvenementEmbuche FiniMonTour;//évènement signalant que le joueur à fini son tour. public Joueur(string LeNom) { Nom = LeNom; DistanceParcourue = 0; Main = new List<Carte>(); Jeu = new ObservableCollection<Carte>();//initialisation de la collection Jeu.CollectionChanged += Jeu_CollectionChanged;//Abonnement à l'évènement signalant un changement } public string Nom { get; private set; } public List<Carte> Main { get; set; } public ObservableCollection<Carte> Jeu { get; set; } /// <summary> /// Propriété en lecture seule, dont la valeur est le résultat d'un calcul /// </summary> public int Points { get { int bonus = 0; //si un (ou plusieurs) joueur n'a pas pu poser de kilomètre, les autres marquent 500 points de bonus foreach(Joueur leJoueur in Moteur.Joueurs) { if (leJoueur == this) continue;//on passe à l'itération suivante if (leJoueur.DistanceParcourue == 0) bonus += 500;//on ajoute 500 au bonus pour se joueur sans distance } int lesPoints = 0; foreach(Carte laCarte in Jeu) { lesPoints += laCarte.Points;//grâce au polymorphisme, on peut additionner les points, peu importe le type de carte. } return lesPoints + bonus; } } public int DistanceParcourue { get; private set; } /// <summary> /// Traitements à faire après qu'une carte ait été ajoutée au jeu /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Jeu_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.Action != System.Collections.Specialized.NotifyCollectionChangedAction.Add) return; if (Jeu.Last() is Embuche)//si la dernière carte reçue est une embuche, car Jeu contient des Cartes { if (this.EmbucheRecue != null)//on vérifie que "quelqu'un" soit abonné à l'évènement this.EmbucheRecue(this);//on émet l'évènement Embuche lEmbuche = (Embuche)Jeu.Last();//pour travailler sur une Embuche, à partir d'une Carte, il faut "caster" (forcer la conversion) la Carte en Embuche //on regarde si le joueur dispose de la botte pour faire un coup fourré foreach (Carte laCarte in Main) { if (laCarte is Botte && ((Botte)laCarte).EmbucheImmunisee == lEmbuche.Type) { Botte laBotte = (Botte)laCarte; //on signale que l'on joue le coup fourré if (this.CoupFourre != null) this.CoupFourre(this); laBotte.CoupFourreParLeJoueur();//appelle la méthode qui va mettre le bonus de points Jouer(laBotte);//On joue la botte Jeu.Remove(lEmbuche);//on enlève l'embuche du jeu, ce qui va regénérer l'évènement Jeu_CollectionChanged, d'ou le premier test Moteur.Defausse.Add(lEmbuche);//on jette l'embuche à la défausse Pioche();//on pioche pour remplacer la botte break;//on sort du foreach, ça n'est pas la peine de continuer à cherche ce que l'on a déjà trouvé } } } else if (Jeu.Last() is Kilometre)//si la dernière carte est un kilomètre, on calcule la distance totale. { Kilometre km = (Kilometre)Jeu.Last(); DistanceParcourue = km + DistanceParcourue; if (DistanceParcourue == Moteur.DistanceAParcourir) { if (this.JaiGagne != null) this.JaiGagne(this,DistanceParcourue);//on émet l'évènement avec le paramètre correspondant à la signature. } else if (DistanceParcourue > Moteur.DistanceAParcourir) { if (this.DistanceDepassee != null) this.DistanceDepassee(this,DistanceParcourue); } } } /// <summary> /// Méthode permettant de jouer une Carte dans son jeu /// </summary> /// <param name="LaCarte"></param> /// <remarks>Si cette méthode était publique, on se jouerait une embuche à soi-même</remarks> private void Joue(Carte LaCarte) { Main.Remove(LaCarte);//On enlève la carte de la main Jeu.Add(LaCarte);//on ajoute la carte au jeu AnnonceFinTour(); } /// <summary> /// Méthode permettant de jouer un kilomètre /// </summary> /// <param name="Km"></param> /// <remarks>Je crée 3 surcharges pour être sûr qu'une embuche ne sera pas transmise en paramètre</remarks> public void Jouer(Kilometre Km) { Joue((Carte)Km); } /// <summary> /// Surcharge permettant de jouer une parade /// </summary> /// <param name="LaParade"></param> public void Jouer(Parade LaParade) { Joue((Carte)LaParade); } /// <summary> /// Surcharge permettant de jouer une botte /// </summary> /// <param name="LaParade"></param> public void Jouer(Botte LaBotte) { Joue((Carte)LaBotte); } /// <summary> /// Surcharge permettant de mettre une embuche à un adversaire /// </summary> /// <param name="Lembuche"></param> /// <param name="Cible"></param> public void Jouer(Embuche Lembuche, Joueur Cible) { if (Cible == this)//si le joueur cible est le joueur en cours, on génère une erreur throw new Exception("Le joueur ne peut pas se mettre une embuche à lui-même"); else { Main.Remove(Lembuche);//On enlève la carte de la main Cible.Jeu.Add(Lembuche);//on ajoute la carte au jeu du joueur cible } AnnonceFinTour(); } /// <summary> /// Pioche une carte /// </summary> public void Pioche() { Main.Add(Moteur.Pioche[0]);//pioche la première carte Moteur.Pioche.RemoveAt(0); } /// <summary> /// Défausse une carte /// </summary> /// <param name="LaCarte">Carte à défausser</param> public void Defausse(Carte LaCarte) { Moteur.Defausse.Add(LaCarte); Main.Remove(LaCarte); AnnonceFinTour(); } /// <summary> /// Annonce que le tour est terminé /// </summary> private void AnnonceFinTour() { if (this.FiniMonTour != null) this.FiniMonTour(this); } }
public static class Moteur { public delegate void EvenementProchainJoueur(Joueur LeJoueur);//signature de l'évènement public static event EvenementProchainJoueur ProchainJoueur;//évènement annonçant le joueur suivant public static event EvenementProchainJoueur PartieGagnee;//évènement annonçant qui a gagné public delegate void EvenementMoteurJeu();//signature de l'évènement public static event EvenementMoteurJeu NouvellePioche;//évènement annonçant la nouvelle pioche public static int DistanceAParcourir { get; set; } public static List<Joueur> Joueurs { get; set; } public static List<Carte> Defausse { get; set; } public static ObservableCollection<Carte> Pioche { get; set; } public static Joueur JoueurEnCours { get { return Joueurs[indexJoueur]; } } private static int indexJoueur; /// <summary> /// Initialise les éléments de jeu avant la première partie /// </summary> /// <param name="NomsJoueurs"></param> public static void InitPremierePartie(List<string> NomsJoueurs) { Defausse = new List<Carte>(); Pioche = new ObservableCollection<Carte>(); Pioche.CollectionChanged += Pioche_CollectionChanged; Joueurs = new List<Joueur>(); //Crée les joueurs et s'abonne aux évènements foreach (string joueur in NomsJoueurs) { Joueur j = new Joueur(joueur); j.CoupFourre += j_CoupFourre; j.DistanceDepassee += j_DistanceDepassee; j.JaiGagne += j_JaiGagne; j.FiniMonTour += j_FiniMonTour; Joueurs.Add(j); } DistanceAParcourir = Joueurs.Count > 3 ? 700 : 1000;//La distance à parcourir est 700 à partir de 4 joueurs, sinon 1000 NouvellePartie(); } /// <summary> /// Quand un joueur à finit, on passe au suivant /// </summary> /// <param name="LeJoueur"></param> static void j_FiniMonTour(Joueur LeJoueur) { JoueurSuivant(); } /// <summary> /// Signale la fin de la partie /// </summary> /// <param name="LeJoueur"></param> /// <param name="Kilometres"></param> private static void j_JaiGagne(Joueur LeJoueur, int Kilometres) { if (Moteur.PartieGagnee != null) Moteur.PartieGagnee(LeJoueur); } /// <summary> /// Démarre une nouvelle partie /// </summary> public static void NouvellePartie() { //génération des cartes List<Carte> toutesLesCartes = Kilometre.Generer(); toutesLesCartes.AddRange(Embuche.Generer()); toutesLesCartes.AddRange(Parade.Generer()); toutesLesCartes.AddRange(Botte.Generer()); //mélange des cartes Melanger(toutesLesCartes); //distribution des cartes 6 par joueur, une par une chacun son tour for (int i = 0; i < 6; i++) { for (int j = 0; j < Moteur.Joueurs.Count; j++) { Moteur.Joueurs[j].Pioche(); } } indexJoueur = 0; AnnonceProchainJoueur(); } private static List<int> indexJoueursDisqualifies = new List<int>(); /// <summary> /// Un joueur a dépassé la distance=> il est éliminé /// </summary> /// <param name="LeJoueur"></param> /// <param name="Kilometres"></param> static void j_DistanceDepassee(Joueur LeJoueur, int Kilometres) { indexJoueursDisqualifies.Add(Joueurs.IndexOf(LeJoueur));//on ajoute ce joueur dans la liste des joueurs disqualifiés } /// <summary> /// Change le joueur après un coup fourré /// </summary> /// <param name="LeJoueur"></param> private static void j_CoupFourre(Joueur LeJoueur) { indexJoueur = Joueurs.IndexOf(LeJoueur); AnnonceProchainJoueur(); } /// <summary> /// Annonce le joueur suivant /// </summary> private static void AnnonceProchainJoueur() { if (ProchainJoueur != null) ProchainJoueur(JoueurEnCours); } /// <summary> /// Surveille la pioche, et la refait à partir de la défausse quand elle est vide /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void Pioche_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.Action != System.Collections.Specialized.NotifyCollectionChangedAction.Remove) return; if (Pioche.Count == 0) { Melanger(Defausse); if (Moteur.NouvellePioche != null) Moteur.NouvellePioche(); } } /// <summary> /// Mélange les cartes et (re)crée la pioche /// </summary> /// <param name="Cartes"></param> private static void Melanger(List<Carte> Cartes) { Random rnd = new Random(); do { int index = rnd.Next(Cartes.Count);//génère un entier aléatoire compris entre 0 et Cartes.Count -1 Pioche.Add(Cartes[index]);//ajoute la carte à cet index dans la pioche Cartes.RemoveAt(index);//enlève la carte de la collection d'origine } while (Cartes.Count > 0); } /// <summary> /// Passe au joueur suivant /// </summary> private static void JoueurSuivant() { if (indexJoueur == Joueurs.Count - 1) indexJoueur = 0; else indexJoueur++; if (indexJoueursDisqualifies.Contains(indexJoueur))//si le joueur est disqualifié on passe au suivant de manière récursive JoueurSuivant(); else AnnonceProchainJoueur(); } }
public class Embuche:Carte { /// Code déjà écrit non retranscrit /// <summary> /// Méthode de classe qui génère la liste d'Embuches /// </summary> /// <returns></returns> public static List<Carte> Generer() { List<Carte> resultat = new List<Carte>(); for (int i = 0; i < 5; i++) { resultat.Add(new Embuche("Image du feu rouge", TypeEmbuche.FeuRouge)); } for (int i = 0; i < 4; i++) { resultat.Add(new Embuche("Image de la limitation de vitesse", TypeEmbuche.LimitationVitesse)); } for (int i = 0; i < 3; i++) { resultat.Add(new Embuche("Image de la panne d'essence", TypeEmbuche.PanneEssence)); } for (int i = 0; i < 3; i++) { resultat.Add(new Embuche("Image de la crevaison", TypeEmbuche.Crevaison)); } for (int i = 0; i < 3; i++) { resultat.Add(new Embuche("Image de l'accident", TypeEmbuche.Accident)); } return resultat; } } public class Parade:Carte { /// Code déjà écrit non retranscrit /// <summary> /// Méthode de classe qui génère la liste de Parades /// </summary> /// <returns></returns> public static List<Carte> Generer() { List<Carte> resultat = new List<Carte>(); for (int i = 0; i < 14; i++) { resultat.Add(new Parade("Image du feu vert", TypeEmbuche.FeuRouge)); } for (int i = 0; i < 6; i++) { resultat.Add(new Parade("Image de la fin de limitation", TypeEmbuche.LimitationVitesse)); } for (int i = 0; i < 6; i++) { resultat.Add(new Parade("Image de la station essence", TypeEmbuche.PanneEssence)); } for (int i = 0; i < 6; i++) { resultat.Add(new Parade("Image de la roue de secours", TypeEmbuche.Crevaison)); } for (int i = 0; i < 6; i++) { resultat.Add(new Parade("Image de la réparation", TypeEmbuche.Accident)); } return resultat; } } public class Botte : Carte { /// Code déjà écrit non retranscrit /// <summary> /// Cette méthode est appelée par le joueur en cas de coup fourré /// </summary> public void CoupFourreParLeJoueur() { this.Points += 300; } /// <summary> /// Méthode de classe qui génère la liste de Bottes /// </summary> /// <returns></returns> public static List<Carte> Generer() { List<Carte> resultat = new List<Carte>(); resultat.Add(new Botte("Image du camion de pompier", TypeEmbuche.FeuRouge)); resultat.Add(new Botte("Image de la citerne d'essence", TypeEmbuche.PanneEssence)); resultat.Add(new Botte("Image de la roue increvable", TypeEmbuche.Crevaison)); resultat.Add(new Botte("Image de l'as du volant", TypeEmbuche.Accident)); return resultat; } }
public class Kilometre:Carte { /// Code déjà écrit non retranscrit /// <summary> /// Méthode de classe qui génère la liste de Kilomètres /// </summary> /// <returns></returns> public static List<Carte> Generer() { List<Carte> resultat = new List<Carte>(); for (int i = 0; i < 10; i++) { resultat.Add(new Kilometre("Image 25 km", 25)); } for (int i = 0; i < 10; i++) { resultat.Add(new Kilometre("Image 50 km", 50)); } for (int i = 0; i < 10; i++) { resultat.Add(new Kilometre("Image 75 km", 75)); } for (int i = 0; i < 12; i++) { resultat.Add(new Kilometre("Image 100 km", 100)); } for (int i = 0; i < 4; i++) { resultat.Add(new Kilometre("Image 200 km", 200)); } return resultat; } /// <summary> /// Opérateur qui permet d'additionner deux Kilometre et de retourner un entier égal à la somme des distances. /// </summary> /// <param name="LUn"></param> /// <param name="LAutre"></param> /// <returns></returns> public static int operator +(Kilometre LUn, Kilometre LAutre) { return LUn.Distance + LAutre.Distance; } /// <summary> /// Opérateur qui permet d'additionner un Kilometre et un entier /// </summary> /// <param name="Km"></param> /// <param name="Entier"></param> /// <returns></returns> public static int operator +(Kilometre Km, int Entier) { return Km.Distance + Entier; } }
[Flags()] public enum TypeEmbuche { Aucune = 0, FeuRouge = 1, LimitationVitesse = 2, Crevaison = 4, PanneEssence = 8, Accident = 16 }
/// <summary> /// Réécriture de ToString pour afficher le nom de la botte /// </summary> /// <returns></returns> public override string ToString() { switch (EmbucheImmunisee) { case TypeEmbuche.Accident: return "As du volant"; case TypeEmbuche.Crevaison: return "Roue increvable"; case TypeEmbuche.FeuRouge | TypeEmbuche.LimitationVitesse: return "Camion de pompier"; case TypeEmbuche.PanneEssence: return "Citerne d'essence"; } //on est obligé de mettre un default ou après le swicth return quelque chose car ToString retourne un résultat, et même si on a testé toutes les options de TypeEmbuche, le compilateur considère qu'un cas non prévu pourrait se présenter et qu'il n'y aurait alors pas de résultat return "Erreur"; } /// <summary> /// Méthode de classe qui génère la liste de Bottes /// </summary> /// <returns></returns> public static List<Carte> Generer() { List<Carte> resultat = new List<Carte>(); resultat.Add(new Botte("Image du camion de pompier", TypeEmbuche.FeuRouge | TypeEmbuche.LimitationVitesse)); resultat.Add(new Botte("Image de la citerne d'essence", TypeEmbuche.PanneEssence)); resultat.Add(new Botte("Image de la roue increvable", TypeEmbuche.Crevaison)); resultat.Add(new Botte("Image de l'as du volant", TypeEmbuche.Accident)); return resultat; }
private void Jeu_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.Action != System.Collections.Specialized.NotifyCollectionChangedAction.Add) return; if (Jeu.Last() is Embuche)//si la dernière carte reçue est une embuche, car Jeu contient des Cartes { if (this.EmbucheRecue != null)//on vérifie que "quelqu'un" soit abonné à l'évènement this.EmbucheRecue(this);//on émet l'évènement Embuche lEmbuche = (Embuche)Jeu.Last();//pour travailler sur une Embuche, à partir d'une Carte, il faut "caster" (forcer la conversion) la Carte en Embuche //on regarde si le joueur dispose de la botte pour faire un coup fourré foreach (Carte laCarte in Main) { if (laCarte is Botte && ((Botte)laCarte).EmbucheImmunisee == lEmbuche.Type) { Botte laBotte = (Botte)laCarte; //on signale que l'on joue le coup fourré if (this.CoupFourre != null) this.CoupFourre(this); laBotte.CoupFourreParLeJoueur();//appelle la méthode qui va mettre le bonus de points Jouer(laBotte);//On joue la botte Jeu.Remove(lEmbuche);//on enlève l'embuche du jeu, ce qui va regénérer l'évènement Jeu_CollectionChanged, d'ou le premier test Moteur.Defausse.Add(lEmbuche);//on jette l'embuche à la défausse Pioche();//on pioche pour remplacer la botte return;//on sort de la méthode, ça n'est pas la peine de continuer à cherche ce que l'on a déjà trouvé } } EmbucheEnCours |= lEmbuche.Type;//on ajoute l'embûche if (lEmbuche.Type != TypeEmbuche.LimitationVitesse && !Immunite.HasFlag(TypeEmbuche.FeuRouge)) EmbucheEnCours |= TypeEmbuche.FeuRouge;//on ajoute un feu rouge pour que le joueur soit obligé de mettre un feu vert } else if (Jeu.Last() is Kilometre)//si la dernière carte est un kilomètre, on calcule la distance totale. { Kilometre km = (Kilometre)Jeu.Last(); DistanceParcourue = km + DistanceParcourue; if (DistanceParcourue == Moteur.DistanceAParcourir) { if (this.JaiGagne != null) this.JaiGagne(this,DistanceParcourue);//on émet l'évènement avec le paramètre correspondant à la signature. } else if (DistanceParcourue > Moteur.DistanceAParcourir) { if (this.DistanceDepassee != null) this.DistanceDepassee(this,DistanceParcourue); } } } private void Joue(Carte LaCarte) { if (LaCarte is Kilometre) { switch (EmbucheEnCours) { case TypeEmbuche.Aucune://on peut rouler break; case TypeEmbuche.LimitationVitesse://il n'y a aucune autre embûche if (((Kilometre)LaCarte).Distance > 50) { AnnonceCarteInterdite(LaCarte); return;//on ne peut pas dépasser 50 } break; default://s'il y a n'importe quelle autre embuche, on ne peut pas rouler AnnonceCarteInterdite(LaCarte); return; } if (((Kilometre)LaCarte).Distance == 200 && Jeu.OfType<Kilometre>().Count(k => k.Distance == 200) == 2) { //On ne peut pas joueur plus de 2 "200 km" //à noter pour cette recherche, au lieu d'imbriquer des boucles (comme plus haut), j'ai utilisé une requête Linq, qui filtre sur le type puis compte le nombre de "200 km" AnnonceCarteInterdite(LaCarte); return; } } else if(LaCarte is Parade) { Parade maParade = (Parade)LaCarte; if (!EmbucheEnCours.HasFlag(maParade.EmbucheParee)) { AnnonceCarteInterdite(LaCarte); return;//on ne peut pas parer une embuche que l'on ne subit pas } if (maParade.EmbucheParee == TypeEmbuche.FeuRouge && !(EmbucheEnCours == TypeEmbuche.FeuRouge || EmbucheEnCours == (TypeEmbuche.FeuRouge | TypeEmbuche.LimitationVitesse))) { AnnonceCarteInterdite(LaCarte); return;//on ne peut poser un feu vert qui si on est en "état" de feu rouge, ou feu rouge et limitation, toutes les autres embuches doivent avoir été parées avant } EmbucheEnCours ^= maParade.EmbucheParee; } else { //c'est forcément une botte, elle peut se poser n'importe quand même sans parer une embûche Botte laBotte = ((Botte)LaCarte); Immunite |= laBotte.EmbucheImmunisee;//immunise if (laBotte.EmbucheImmunisee.HasFlag(TypeEmbuche.FeuRouge)) { if (EmbucheEnCours.HasFlag(TypeEmbuche.FeuRouge)) EmbucheEnCours ^= TypeEmbuche.FeuRouge;//pare si besoin if (EmbucheEnCours.HasFlag(TypeEmbuche.LimitationVitesse)) EmbucheEnCours ^= TypeEmbuche.LimitationVitesse;//pare si besoin } else if (EmbucheEnCours.HasFlag(laBotte.EmbucheImmunisee)) EmbucheEnCours ^= laBotte.EmbucheImmunisee;//pare si besoin } Main.Remove(LaCarte);//On enlève la carte de la main Jeu.Add(LaCarte);//on ajoute la carte au jeu AnnonceFinTour(); } public void Jouer(Embuche Lembuche, Joueur Cible) { if (Cible == this)//si le joueur cible est le joueur en cours, on génère une erreur throw new Exception("Le joueur ne peut pas se mettre une embuche à lui-même"); bool condition1 = Cible.Immunite.HasFlag(Lembuche.Type);//on ne peut pas poser ni une embûche contre laquelle la cible est immunisée, bool condition2; if (Lembuche.Type == TypeEmbuche.LimitationVitesse) condition2 = Cible.EmbucheEnCours.HasFlag(TypeEmbuche.LimitationVitesse);//ni une limitation si elle y est déjà else condition2 = Cible.EmbucheEnCours != TypeEmbuche.Aucune && Cible.EmbucheEnCours != TypeEmbuche.LimitationVitesse;//ni les autres embûches s'il y a en déjà une (sauf la limitation) if (condition1 || condition2) { AnnonceCarteInterdite(Lembuche); } else { Main.Remove(Lembuche);//On enlève la carte de la main Cible.Jeu.Add(Lembuche);//on ajoute la carte au jeu du joueur cible AnnonceFinTour(); } }
public delegate void EvenementCarte(Joueur LeJoueur,Carte LaCarte); //signature de l'évènement, je déclare ce délégué en dehors de la classe, ainsi, il est visible dans tout l'espace de nom public class Joueur { public event EvenementCarte CarteInterdite; //évènement signalant que le joueur tente de poser une carte à l'encontre des règles. //Code déjà écrit non retranscrit /// <summary> /// Génère l'évènement /// </summary> private void AnnonceCarteInterdite(Carte LaCarte) { if (this.CarteInterdite != null) this.CarteInterdite(this, LaCarte); }
/// <summary> /// Transmet l'alerte qu'un joueur tente de joueur une carte "illégale" /// </summary> /// <param name="LeJoueur"></param> /// <param name="LaCarte"></param> static void j_CarteInterdite(Joueur LeJoueur, Carte LaCarte) { if (Moteur.CarteInterdite != null) Moteur.CarteInterdite(LeJoueur, LaCarte); }
/// <summary> /// Annonce le joueur suivant /// </summary> private static void AnnonceProchainJoueur() { JoueurEnCours.Pioche();//fait piocher le joueur suivant if (ProchainJoueur != null) ProchainJoueur(JoueurEnCours); }
public enum Difficulte { Facile, Normale, Difficile, Expert }
public Joueur(string LeNom) { Nom = LeNom; Main = new List<Carte>(); Jeu = new ObservableCollection<Carte>();//initialisation de la collection Jeu.CollectionChanged += Jeu_CollectionChanged;//Abonnement à l'évènement signalant un changement Niveau = Difficulte.Facile; NouvellePartie(); } public Joueur(string LeNom, Difficulte LeNiveau) { Nom = LeNom; Main = new List<Carte>(); Jeu = new ObservableCollection<Carte>();//initialisation de la collection Jeu.CollectionChanged += Jeu_CollectionChanged;//Abonnement à l'évènement signalant un changement Niveau = LeNiveau; NouvellePartie(); }
public Joueur(string LeNom):this(LeNom,Difficulte.Facile)//on appelle le constructeur plus complet avec une valeur par défaut { } public Joueur(string LeNom, Difficulte LeNiveau) { Nom = LeNom; Main = new List<Carte>(); Jeu = new ObservableCollection<Carte>();//initialisation de la collection Jeu.CollectionChanged += Jeu_CollectionChanged;//Abonnement à l'évènement signalant un changement Niveau = LeNiveau; NouvellePartie(); }
public abstract class Carte : IComparable<Carte> { //etc.
public int CompareTo(Carte other) { throw new NotImplementedException(); }
/// <summary> /// Propriété pour le tri /// </summary> public abstract int Ordre { get; } /// <summary> /// Implémentation de IComparable<Carte> /// </summary> /// <param name="other"></param> /// <returns></returns> public int CompareTo(Carte other) { return this.Ordre.CompareTo(other.Ordre); }
/// <summary> /// Implémentation de ordre dans Botte /// </summary> public override int Ordre { get { switch(EmbucheImmunisee) { case TypeEmbuche.Accident://As du Volant return 0; case TypeEmbuche.FeuRouge | TypeEmbuche.LimitationVitesse://Camion de Pompier return 1; case TypeEmbuche.PanneEssence://Citerne d'essence return 2; default: //il ne reste que la roue de secours return 3; } } }
Aucune = 0, FeuRouge = 8, LimitationVitesse = 16, Crevaison = 4, PanneEssence = 32, Accident = 2
/// <summary> /// Implémentation de ordre dans Embuche /// </summary> public override int Ordre { get { return (int)Type + 3; } }
/// <summary> /// Implémentation de ordre dans Parade /// </summary> public override int Ordre { get { if (EmbucheParee == TypeEmbuche.FeuRouge) return 4; else return (int)EmbucheParee + 4; } }
/// <summary> /// Implémentation de ordre Kilometre /// </summary> public override int Ordre { get { return Distance + 20; } }
Carte superieure = Jeu.FirstOrDefault(c => c.Ordre > LaCarte.Ordre);//on cherche la première carte dont l'ordre est supérieur à la carte jouée, si elle existe. if (superieure != null) Jeu.Insert(Jeu.IndexOf(superieure), LaCarte);//si la carte supérieure existe, on insère la carte jouée à l'index de la carte supérieure else Jeu.Add(LaCarte);//sinon on ajoute la carte jouée au jeu (donc à la fin)
e.NewStartingIndex
Publié par Whismeril. Dernière mise à jour le par vb95.
Ce document intitulé « La programmation Objet appliquée à .Net par l’exemple Partie 2 sur 3, en C# » issu de CodeS-SourceS (https://codes-sources.commentcamarche.net/) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Actualités, Avis de décès, Carte de voeux, Bricolage, Coloriages, Cinéma, Coiffure, Cuisine, Déco, Dictionnaire, Horoscope, Jeux en ligne, Programme TV, Recettes, Restaurant, SMIC, Test débit, Voyage, Signification prénom