**** TP 2 **** Les images des cartes sont placées dans le fichier zip :download:`./resources.zip` dézipez le pour pouvoir les utiliser. Card ==== Toute classe doit posséder ses tests pour être sur que tout fonctionne bien avant d'être utilisé. Créez les deux fichiers dont le code est donné ci après et vérifiez que tous les tests passent en exécutant le fichier :file:`test_card.py` avec la bibliothèque :code:`py.test`. Puis ajoutez un test pour être sûr que l'as est bien plus grand que les autres cartes. cards.py ^^^^^^^^ .. code-block:: python class Card: SPADES = "spade" HEARTS = "heart" CLUBS = "club" DIAMONDS = "diamond" def __init__(self, value, color): self.value = value self.color = color def __str__(self): return "Card(" + str(self.value) + ", " + str(self.color) + ")" def __eq__(self, other): return self.value == other.value and self.color == other.color def __hash__(self): return hash((self.value, self.color)) def __lt__(self, other): return (other.value == 1 and self.value != 1) or 1 < self.value < other.value def __gt__(self, other): return (self.value == 1 and other.value != 1) or self.value > other.value > 1 def image(self): return "resources/Playing_card_" + self.color + "_" + str(self.value) + ".gif" test_card.py ^^^^^^^^^^^^ .. code-block:: python from cards import Card def test_str(): assert str(Card(1, Card.SPADES)) == 'Card(1, spade)' def test_card_equality(): assert Card(1, Card.SPADES) == Card(1, Card.SPADES) assert Card(1, Card.SPADES) != Card(1, Card.DIAMONDS) assert Card(1, Card.SPADES) != Card(13, Card.DIAMONDS) def test_card_lesser_than(): assert not Card(3, Card.SPADES) < Card(3, Card.SPADES) assert Card(2, Card.SPADES) < Card(3, Card.SPADES) def test_card_larger_than(): assert not Card(3, Card.SPADES) > Card(3, Card.SPADES) assert Card(3, Card.SPADES) > Card(2, Card.SPADES) def test_image(): assert Card(11, Card.DIAMONDS).image() == "resources/Playing_card_diamond_11.gif" UI == Le code suivant crée une carte selon ce qui est sélectionné dans les *option boxs*. Exécutez le code et comprenez comment tout ceci fonctionne. Assurez vous que vous avez bien dézipé le fichier :file:`resources.zip` pour que python trouve bien les différentes images. .. note:: Si ce code ne fonctionne pas c'es que vous êtes encore en python2 et pas en python3... Reportez vous à ``_ pour changer votre interpréteur par défaut. Au pire créez un nouveau projet et faites bien attention à ce que ce soit l'interpréteur python3 qui soit utilisé. .. code-block:: python from appJar import gui from cards import Card app = gui() app.addLabelOptionBox("color", [Card.DIAMONDS, Card.SPADES, Card.CLUBS, Card.HEARTS], 0, 0) app.addLabelOptionBox("value", [str(i) for i in range(1, 14)], 0, 1) def on_click(button): color = app.getOptionBox("color") value = app.getOptionBox("value") app.setImage("card_image", Card(int(value), color).image()) app.addButton("show card", on_click, 1, 0, 2) app.addImage("card_image", "resources/empty.gif", 2, 0, 2) app.go() Deck ==== A deck est un tas de cartes. Nous allons créer petit à petit cette classe en lui ajoutant des fonctionnalités. On commence ainsi par ajouter une classe vide dans le fichier :file:`cards.py` : .. code-block:: python class Deck: pass Et un test vide dans :file:`test_card.py` : .. code-block:: python from cards importDeck def test_deck_creation(): deck = Deck() assert deck != None Vérifiez que les tests passent. On va maintenant ajouter petit à petit les tests qui vont nous permettre d'ajouter des fonctionnalités à la classe. On va toujours suivre le même *pattern* : #. ajouter un test et le voir planter en exécutant tous les tests #. ajouter la fonctionnalité voulue à la classe #. exécutez les tests et voir le tout fonctionner. Ajout de cartes ^^^^^^^^^^^^^^^ Un deck est un conteneur. Il doit être vide à la création et on doit pouvoir lui ajouter des cartes. On commence par un test vérifiant que l'on a implémenté une une méthdoe :code:`__len__` permettant d'utiliser la commande :code:`len()` de python : .. code-block:: python def test_deck_empty_at_creation(): deck = Deck() assert len(deck) == 0 Une fois que le test passe, on ajoute un test qui vérifie que l'on peut ajouter une carte au deck : .. code-block:: python def test_add_card(): deck = Deck() deck.add(Card(1, Card.SPADES)) assert len(deck) == 1 Attention, un deck doit être une FIFO : on ajoute une carte au début du deck et on prend une carte à la fin. Voir des cartes ^^^^^^^^^^^^^^^ On veut créer deux méthodes, :code:`show_first` et :code:`show_last` qui montrent respectivement la première et la dernière carte du deck. Vous allez tester et implémenter ces deux méthodes. On commence par :code:`show_first` : .. code-block:: python def test_show_first(): deck = Deck() deck.add(Card(1, Card.SPADES)) deck.add(Card(2, Card.SPADES)) assert deck.show_first() == Card(2, Card.SPADES) Puis :code:`show_last` : .. code-block:: python def test_show_first(): deck = Deck() deck.add(Card(1, Card.SPADES)) deck.add(Card(2, Card.SPADES)) assert deck.show_last() == Card(1, Card.SPADES) Donner des cartes ^^^^^^^^^^^^^^^^^ La dernière méthode à implémenter est :code:`get` qui donne et enlève une carte du deck. On commence par tester le fait que l'on rend :code:`None` si le deck est vide: .. code-block:: python def test_get_empty_deck(): deck = Deck() assert deck.get() == None Puis que l'on récupère bien les carte dans l'ordre : .. code-block:: python def test_show_first(): deck = Deck() deck.add(Card(1, Card.SPADES)) deck.add(Card(2, Card.SPADES)) card = deck.get() assert card == Card(1, Card.SPADES) assert len(deck) == 1 UI : Deck ========= Ajout d'un deck ^^^^^^^^^^^^^^^ Modifiez le code de l'UI précédente pour que : * ce que l'on voit soit la première carte d'un deck (la dernière ajoutée) * que toutes les cartes soient ajoutées à ce deck lorsque l'on clique sur le bouton. * ajoutez un label qui donne le nombre de carte du deck. Dépot des cartes ^^^^^^^^^^^^^^^^ Ajoutez un bouton et un emplacement pour un autre deck. Lorsque l'on cliquera sur le deuxième bouton, on prendra la dernière carte du premier deck et on l'ajoutera au second.