{ "cells": [ { "cell_type": "markdown", "metadata": { "toc": "true" }, "source": [ "# Table of Contents\n", "

1  But de ce notebook
2  Règles du Jap Jap
2.1  But du jeu
2.2  Début du jeu
2.3  Tour de jeu
2.4  Fin du jeu
3  Code du jeu
3.1  Code pour représenter une carte à jouer
3.2  Fin du jeu
3.3  Actions
3.4  Valider un coup
3.5  Jeu interactif
3.6  Etat du jeu
3.7  Lancement du jeu intéractif
4  Conclusion
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "----\n", "# But de ce notebook\n", "\n", "- Je vais expliquer les règles d'un jeu de carte, le \"Jap Jap\", qu'on m'a appris pendant l'été,\n", "- Je veux simuler ce jeu, en Python, afin de calculer quelques statistiques sur le jeu,\n", "- J'aimerai essayer d'écrire une petite intelligence artificielle permettant de jouer contre l'ordinateur,\n", "- Le but est de faire un prototype d'une application web ou mobile qui permettrait de jouer contre son téléphone !" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "----\n", "# Règles du *Jap Jap*\n", "\n", "## But du jeu\n", "- Le *Jap Jap* se joue à $n \\geq 2$ joueur-euse-s (désignées par le mot neutre \"personne\"), avec un jeu de $52$ cartes classiques (4 couleurs, 1 à 10 + vallet/dame/roi).\n", "- Chaque partie du *Jap Jap* jeu se joue en plusieurs manches. A la fin de chaque manche, une personne gagne et les autres marquent des points. Le but est d'avoir le moins de point possible, et la première personne a atteindre $90$ points a perdu !\n", "- On peut rendre le jeu plus long en comptant la première personne à perdre $x \\geq 1$ parties.\n", "\n", "## Début du jeu\n", "- Chaque personne reçoit 5 cartes,\n", "- et on révèle la première carte de la pioche.\n", "\n", "## Tour de jeu\n", "- Chaque personne joue l'une après l'autre, dans le sens horaire (anti trigonométrique),\n", "- A son tour, la personne a le choix entre jouer normalement, ou déclencher la fin de jeu si elle possède une main valant $v \\leq 5$ points (voir \"Fin du jeu\" plus bas),\n", "- Jouer normalement consiste à jeter *une ou plusieurs* ($x \\in \\{1,\\dots,5\\}$) cartes de sa main dans la défausse, et prendre *une* carte et la remettre dans sa main. Elle peut choisir la carte du sommet de la pioche (qui est face cachée), ou *une* des $x' \\in \\{1,\\dots,5\\}$ cartes ayant été jetées par la personne précédente, ou bien la première carte de la défausse si c'est le début de la partie.\n", "\n", "## Fin du jeu\n", "- Dès qu'une personne possède une main valant $v \\leq 5$ points, elle peut dire *Jap Jap !* au lieu de jouer à son tour.\n", " + Si elle est la seule personne à avoir une telle main de moins de $5$ points, elle gagne !\n", " + Si une autre personne a une main de moins de $5$ points, elle peut dire *Contre Jap Jap !*, à condition d'avoir *strictement* moins de points que le *Jap Jap !* ou le *Contre Jap Jap !* précédent. La personne qui remporte la manche est celle qui a eu le *Contre Jap Jap !* de plus petite valeur.\n", "- La personne qui a gagné ne marque aucun point, et les autres ajoutent à leur total actuel de point \n", "- Si quelqu'un atteint $90$ points, elle perd la partie." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "----\n", "# Code du jeu" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Code pour représenter une carte à jouer" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "coeur = \"♥\"\n", "treffle = \"♣\"\n", "pique = \"♠\"\n", "carreau = \"♦\"\n", "couleurs = [coeur, treffle, pique, carreau]" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "class Carte():\n", " def __init__(self, valeur, couleur):\n", " assert 1 <= valeur <= 13, \"Erreur : valeur doit etre entre 1 et 13.\"\n", " self.valeur = valeur\n", " assert couleur in couleurs, \"Erreur : couleur doit etre dans la liste {}.\".format(couleurs)\n", " self.couleur = couleur\n", " \n", " def __str__(self):\n", " val = str(self.valeur)\n", " if self.valeur > 10:\n", " val = {11: \"V\" , 12: \"Q\" , 13: \"K\"}[self.valeur]\n", " return \"{:>2}{}\".format(val, self.couleur)\n", " \n", " __repr__ = __str__\n", " \n", " def val(self):\n", " return self.valeur" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def valeur_main(liste_carte):\n", " return sum(carte.val() for carte in liste_carte)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "import random\n", "\n", "def nouveau_jeu():\n", " jeu = [\n", " Carte(valeur, couleur)\n", " for valeur in range(1, 13+1)\n", " for couleur in couleurs\n", " ]\n", " random.shuffle(jeu)\n", " return jeu" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/plain": [ "[ 7♣, 7♥, Q♦, 8♣, 1♠]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "35" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nouveau_jeu()[:5]\n", "valeur_main(_)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Fin du jeu" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour représenter la fin du jeu :" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "class FinDuneManche(Exception):\n", " pass" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "class FinDunePartie(Exception):\n", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Actions\n", "Pour représenter une action choisie par une personne :" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "class action():\n", " def __init__(self, typeAction=\"piocher\", choix=None):\n", " assert typeAction in [\"piocher\", \"choisir\", \"Jap Jap !\"]\n", " self.typeAction = typeAction\n", " assert choix is None or choix in [0, 1, 2, 3, 4]\n", " self.choix = choix\n", " \n", " def __str__(self):\n", " if self.est_piocher(): return \"Piocher\"\n", " elif self.est_japjap(): return \"Jap Jap !\"\n", " elif self.est_choisir(): return \"Choisir #{}\".format(self.choix)\n", "\n", " def est_piocher(self):\n", " return self.typeAction == \"piocher\"\n", "\n", " def est_choisir(self):\n", " return self.typeAction == \"choisir\"\n", "\n", " def est_japjap(self):\n", " return self.typeAction == \"Jap Jap !\"\n", "\n", "action_piocher = action(\"piocher\")\n", "action_japjap = action(\"Jap Jap !\")\n", "action_choisir0 = action(\"choisir\", 0)\n", "action_choisir1 = action(\"choisir\", 1)\n", "action_choisir2 = action(\"choisir\", 2)\n", "action_choisir3 = action(\"choisir\", 3)\n", "action_choisir4 = action(\"choisir\", 4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Valider un coup" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour savoir si une suite de valeurs est bien continue :" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "def suite_valeurs_est_continue(valeurs):\n", " vs = sorted(valeurs)\n", " differences = [ vs[i + 1] - vs[i] for i in range(len(vs) - 1) ]\n", " return all([d == 1 for d in differences])" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "False" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "suite_valeurs_est_continue([5, 6, 7])\n", "suite_valeurs_est_continue([5, 7, 8])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour valider un coup choisie par une personne :" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "def valide_le_coup(jetees):\n", " if jetees is None or not (1 <= len(jetees) <= 5):\n", " return False\n", " # coup valide si une seule carte !\n", " elif len(jetees) == 1:\n", " return True\n", " # si plus d'une carte\n", " elif len(jetees) >= 2:\n", " couleurs_jetees = [carte.couleur for carte in jetees]\n", " valeurs_jetees = sorted([carte.valeur for carte in jetees])\n", " # coup valide si une seule couleur et une suite de valeurs croissantes et continues\n", " if len(set(couleurs_jetees)) == 1:\n", " return suite_valeurs_est_continue(valeurs_jetees)\n", " # coup valide si une seule valeur et différentes couleurs\n", " elif len(set(valeurs_jetees)) == 1:\n", " return len(set(couleurs_jetees)) == len(couleurs_jetees)\n", " return False" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Exemples de coups valides :" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "valide_le_coup([Carte(4, coeur)])" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "valide_le_coup([Carte(4, coeur), Carte(5, coeur)])" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "valide_le_coup([Carte(4, coeur), Carte(5, coeur), Carte(3, coeur)])" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "valide_le_coup([Carte(4, coeur), Carte(5, coeur), Carte(3, coeur), Carte(2, coeur), Carte(6, coeur)])" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "valide_le_coup([Carte(4, coeur), Carte(4, carreau)])" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "valide_le_coup([Carte(4, coeur), Carte(4, carreau), Carte(4, pique)])" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "valide_le_coup([Carte(4, coeur), Carte(4, carreau), Carte(4, pique), Carte(4, treffle)])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Exemples de coups pas valides :" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "valide_le_coup([Carte(4, coeur), Carte(9, coeur)])" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "valide_le_coup([Carte(4, coeur), Carte(4, coeur), Carte(3, coeur)])" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "valide_le_coup([Carte(4, coeur), Carte(12, carreau)])" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "valide_le_coup([Carte(4, coeur), Carte(4, carreau), Carte(4, pique)])" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "valide_le_coup([Carte(4, coeur), Carte(4, carreau), Carte(4, pique), Carte(4, treffle)])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Jeu interactif\n", "On va utiliser les widgets ipython pour construire le jeu interactif !" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "# Voir https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Asynchronous.html#Waiting-for-user-interaction\n", "%gui asyncio" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "import asyncio\n", "\n", "def wait_for_change(widget, value):\n", " future = asyncio.Future()\n", " def getvalue(change):\n", " # make the new value available\n", " future.set_result(change.new)\n", " widget.unobserve(getvalue, value)\n", " widget.observe(getvalue, value)\n", " return future" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "import ipywidgets as widgets\n", "from IPython.display import display\n", "\n", "style = {\n", " 'description_width': 'initial',\n", "}\n", "style2boutons = {\n", " 'description_width': 'initial',\n", " 'button_width': '50vw',\n", "}\n", "style3boutons = {\n", " 'description_width': 'initial',\n", " 'button_width': '33vw',\n", "}\n", "style4boutons = {\n", " 'description_width': 'initial',\n", " 'button_width': '25vw',\n", "}\n", "style5boutons = {\n", " 'description_width': 'initial',\n", " 'button_width': '20vw',\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour savoir quoi jouer :" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "def piocher_ou_choisir_une_carte_visible():\n", " return widgets.ToggleButtons(\n", " options=[\"Une carte dans la pioche \", \"Une carte du sommet de la défausse \"],\n", " index=0,\n", " tooltips=[\"invisible\", \"visibles\"],\n", " icons=[\"question\", \"list-ol\"],\n", " description=\"Action ?\",\n", " style=style4boutons,\n", " )" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "c3bbc981b9ff453588a3ba326b7b9db4", "version_major": 2, "version_minor": 0 }, "text/plain": [ "ToggleButtons(description='Action ?', icons=('question', 'list-ol'), options=('Une carte dans la pioche ', 'Un…" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Choix : 0\n" ] } ], "source": [ "bouton = piocher_ou_choisir_une_carte_visible()\n", "display(bouton)\n", "print(\"Choix :\", bouton.index)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour savoir quoi jeter :" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[10♥, V♥, V♠]" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "exemple_de_main = [Carte(10, coeur), Carte(11, coeur), Carte(11, pique)]\n", "exemple_de_main" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "scrolled": true }, "outputs": [], "source": [ "def faire_japjap(main):\n", " return widgets.ToggleButton(\n", " value=False,\n", " description=\"Jap Jap ? ({})\".format(valeur_main(main)),\n", " button_style=\"success\",\n", " tooltip=\"Votre main vaut moins de 5 points, donc vous pouvez terminer la partie !\",\n", " icon=\"check\",\n", " style=style,\n", " )" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "7160585f2792460cbd7d1a8e22bc81e3", "version_major": 2, "version_minor": 0 }, "text/plain": [ "ToggleButton(value=False, button_style='success', description='Jap Jap ? (32)', icon='check', style=Descriptio…" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Choix : False\n" ] } ], "source": [ "b = faire_japjap(exemple_de_main)\n", "display(b)\n", "print(\"Choix :\", b.value)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "scrolled": true }, "outputs": [], "source": [ "def quoi_jeter(main):\n", " return widgets.SelectMultiple(\n", " options=main,\n", " index=[0],\n", " description=\"Quoi jeter ?\",\n", " style=style,\n", " )" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "4dad7172210240be98a08648c5b0d842", "version_major": 2, "version_minor": 0 }, "text/plain": [ "SelectMultiple(description='Quoi jeter ?', index=(0,), options=(10♥, V♥, V♠), style=DescriptionStyle(descrip…" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Choix : (0,)\n" ] } ], "source": [ "b = quoi_jeter(exemple_de_main)\n", "display(b)\n", "print(\"Choix :\", b.index)" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "from IPython.display import display" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "def valider_action():\n", " return widgets.ToggleButton(description=\"Valider l'action ?\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour savoir quoi piocher :" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[ V♠, 10♣]" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "exemple_de_visibles = [Carte(11, pique), Carte(10, treffle)]\n", "exemple_de_visibles" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [], "source": [ "def quoi_prendre(visibles):\n", " return widgets.ToggleButtons(\n", " options=visibles,\n", " #index=0,\n", " description=\"Prendre quelle carte du sommet ?\",\n", " style=style,\n", " )" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "scrolled": true }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "ac52dce9214b4e8ea5855c91c54b1f0e", "version_major": 2, "version_minor": 0 }, "text/plain": [ "ToggleButtons(description='Prendre quelle carte du sommet ?', options=( V♠, 10♣), style=ToggleButtonsStyle(des…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "quoi_prendre(exemple_de_visibles)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On va tricher et afficher les cartes avec `display(Markdown(...))` plutôt que `print`, pour les avoir en couleurs." ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[Alice] Cartes en main : [ 6♦, 5♠, V♣, V♠, 1♣]\n" ] }, { "data": { "text/markdown": [ "[Alice] Cartes en main : [ 6♦, 5♠, V♣, V♠, 1♣]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from IPython.display import Markdown\n", "print(\"[Alice] Cartes en main : [ 6♦, 5♠, V♣, V♠, 1♣]\")\n", "# avec de la couleurs\n", "display(Markdown(\"[Alice] Cartes en main : [ 6♦, 5♠, V♣, V♠, 1♣]\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Maintenant on peut tout combiner." ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "async def demander_action(visibles=None, main=None, stockResultat=None):\n", " display(Markdown(\"- Main : {} (valeur = {})\".format(main, valeur_main(main))))\n", " display(Markdown(\"- Sommet de la défausse {}\".format(visibles)))\n", " fait_japjap = False\n", " # 1.a. si on peut faire jap jap, demander si on le fait ?\n", " if valeur_main(main) <= 5:\n", " print(\"Vous pouvez faire Jap Jap !\")\n", " bouton3 = faire_japjap(main)\n", " validation = valider_action()\n", " display(widgets.VBox([bouton3, validation]))\n", " await wait_for_change(validation, 'value')\n", " # print(\" ==> Choix :\", bouton3.value)\n", " if bouton3.value:\n", " fait_japjap = True\n", " typeAction = \"Jap Jap !\"\n", " jetees = None\n", " # 1.b. quoi jouer\n", " if not fait_japjap:\n", " bouton1 = piocher_ou_choisir_une_carte_visible()\n", " validation = valider_action()\n", " display(widgets.VBox([bouton1, validation]))\n", " await wait_for_change(validation, 'value')\n", " piocher = bouton1.index == 0\n", " # print(\" ==> Choix :\", bouton1.value)\n", " # 2.a. si piocher, rien à faire pour savoir quoi piocher\n", " if piocher:\n", " print(\"Okay, vous piochez.\")\n", " typeAction = \"piocher\"\n", " choix = None\n", " # 2.b. si choisir carte\n", " else:\n", " typeAction = \"choisir\"\n", " print(\"Okay, vous choisissez dans le sommet de la défausse.\")\n", " if len(visibles) > 1:\n", " bouton2 = quoi_prendre(visibles)\n", " validation = valider_action()\n", " display(widgets.VBox([bouton2, validation]))\n", " await wait_for_change(validation, 'value')\n", " # print(\" ==> Choix :\", bouton2.index)\n", " choix = bouton2.index\n", " else:\n", " choix = 0\n", " # 3. choisir quoi jeter\n", " if typeAction != \"Jap Jap !\":\n", " if len(main) > 1:\n", " pas_encore_de_coup = True\n", " jetees = None\n", " bouton4 = quoi_jeter(main)\n", " validation = valider_action()\n", " display(widgets.VBox([bouton4, validation]))\n", " while pas_encore_de_coup or not valide_le_coup(jetees):\n", " await wait_for_change(validation, 'value')\n", " # print(\" ==> Choix :\", bouton4.index)\n", " jetees = bouton4.index\n", " pas_encore_de_coup = False\n", " if not valide_le_coup(jetees):\n", " print(\"ERREUR ce coup n'est pas valide, on ne peut pas se débarasser de cet ensemble de cartes {}.\".format(jetees))\n", " else:\n", " jetees = 0\n", " action_choisie = action(typeAction=typeAction, choix=choix)\n", " if stockResultat is not None:\n", " stockResultat[\"action_choisie\"] = action_choisie\n", " stockResultat[\"jetees\"] = jetees\n", " return action_choisie, jetees" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "code_folding": [ 0 ] }, "outputs": [], "source": [ "if False:\n", " stockResultat = {\"action_choisie\": None, \"jetees\": None}\n", "\n", " asyncio.ensure_future(\n", " demander_action(\n", " visibles=exemple_de_visibles,\n", " main=exemple_de_main,\n", " stockResultat=stockResultat,\n", " )\n", " )\n", "\n", " stockResultat" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "code_folding": [ 0 ] }, "outputs": [], "source": [ "def demander_action_et_donne_resultat(visibles=None, main=None):\n", " stockResultat = {\"action_choisie\": None, \"jetees\": None}\n", "\n", " asyncio.ensure_future(\n", " demander_action(\n", " visibles=visibles,\n", " main=main,\n", " stockResultat=stockResultat,\n", " )\n", " )\n", "\n", " return stockResultat[\"action_choisie\"], stockResultat[\"jetees\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Etat du jeu\n", "Maintenant on peut représenter un état du jeu." ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [], "source": [ "# on peut changer ici pour jouer moins longtemps !\n", "scoreMax = 90\n", "scoreMax = 10" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "code_folding": [ 1, 20, 31, 38, 44, 49, 53, 65 ] }, "outputs": [], "source": [ "class EtatJeu():\n", " def __init__(self, nbPersonnes=2, nomsPersonnes=None,\n", " scoreMax=scoreMax, malusContreJapJap=25, nbCartesMax=5):\n", " assert 2 <= nbPersonnes <= 5, \"Le nombre de personnes pouvant jouer doit etre entre 2 et 5.\"\n", " self.nbPersonnes = nbPersonnes\n", " self.nomsPersonnes = nomsPersonnes\n", " self.scoreMax = scoreMax\n", " self.malusContreJapJap = malusContreJapJap\n", " self.nbCartesMax = nbCartesMax\n", " # on initialise le stockage interne\n", " self.personnes = [personne for personne in range(nbPersonnes)]\n", " self.scores = [\n", " 0 for personne in self.personnes\n", " ]\n", " self.mains = [\n", " [ ] for personne in self.personnes\n", " ]\n", " self.visibles = []\n", " self.jeu = nouveau_jeu()\n", " \n", " def montrer_information_visibles(self):\n", " print(\"- Nombre de carte dans la pioche :\", len(self.jeu))\n", " print(\"- Cartes visibles au sommet de la défausse :\", len(self.visibles))\n", " for personne in self.personnes:\n", " nom = self.nomsPersonnes[personne] if self.nomsPersonnes is not None else personne\n", " main = self.mains[personne]\n", " score = self.scores[personne]\n", " print(\" + Personne {} a {} carte{} en main, et un score de {}.\".format(\n", " nom, len(main), \"s\" if len(main) > 1 else \"\", score)\n", " )\n", "\n", " def montrer_information_privee(self, personne=0):\n", " main = self.mains[personne]\n", " nom = self.nomsPersonnes[personne] if self.nomsPersonnes is not None else personne\n", " display(Markdown(\"[{}] Carte{} en main : {}\".format(nom, \"s\" if len(main) > 1 else \"\", main)))\n", " \n", " # --- Mécanique de pioche et distribution initiale\n", " \n", " def prendre_une_carte_pioche(self):\n", " if len(self.jeu) <= 0:\n", " raise FinDuneManche\n", " premiere_carte = self.jeu.pop(0)\n", " return premiere_carte\n", " \n", " def debut_jeu(self):\n", " self.distribuer_mains()\n", " premiere_carte = self.prendre_une_carte_pioche()\n", " self.visibles = [premiere_carte]\n", " \n", " def donner_une_carte(self, personne=0):\n", " premiere_carte = self.prendre_une_carte_pioche()\n", " self.mains[personne].append(premiere_carte)\n", " \n", " def distribuer_mains(self):\n", " self.mains = [\n", " [ ] for personne in self.personnes\n", " ]\n", " premiere_personne = random.choice(self.personnes)\n", " self.personnes = self.personnes[premiere_personne:] + self.personnes[:premiere_personne]\n", " for nb_carte in range(self.nbCartesMax):\n", " for personne in self.personnes:\n", " self.donner_une_carte(personne)\n", " \n", " # --- Fin d'une manche\n", " \n", " def fin_dune_manche(self):\n", " self.jeu = nouveau_jeu()\n", " self.debut_jeu()\n", " \n", " # --- Enchainer les tours de jeux\n", " \n", " async def enchainer_les_tours(self):\n", " try:\n", " indice_actuel = 0\n", " while len(self.jeu) > 0:\n", " # dans la même manche, on joue chaque tour, pour la personne actuelle\n", " personne_actuelle = self.personnes[indice_actuel]\n", " \n", " # 1. on affiche ce qui est public, et privé\n", " self.montrer_information_visibles()\n", " self.montrer_information_privee(personne_actuelle)\n", " \n", " # 2. on demande l'action choisie par la personne\n", " # action_choisie, jetees = demander_action_et_donne_resultat(\n", " action_choisie, jetees = await demander_action(\n", " visibles = self.visibles,\n", " main = self.mains[personne_actuelle],\n", " )\n", "\n", " # 3. on joue l'action\n", " self.jouer(\n", " personne = personne_actuelle,\n", " action = action_choisie,\n", " indices = jetees,\n", " )\n", " \n", " # personne suivante\n", " indice_actuel = (indice_actuel + 1) % self.nbPersonnes\n", " if len(self.jeu) <= 0:\n", " print(\"\\nIl n'y a plus de cartes dans la pioche, fin de la manche sans personne qui gagne.\")\n", " raise FinDuneManche\n", " except FinDuneManche:\n", " print(\"\\nFin d'une manche.\")\n", " fin_dune_manche()\n", " except FinDunePartie:\n", " print(\"\\n\\nFin d'une partie.\")\n", " \n", " # --- Un tour de jeu\n", " \n", " def jouer(self, personne=0, action=action_piocher, indices=None):\n", " print(\" ? Personne {} joue l'action {} avec les indices {} ...\".format(personne, action, indices)) # DEBUG\n", " if indices is not None:\n", " jetees = [ self.mains[personne][indice] for indice in indices ]\n", " assert valide_le_coup(jetees)\n", " # et on en prend une nouvelle\n", " if action.est_piocher():\n", " # soit celle face cachée en sommet de pioche\n", " premiere_carte = self.prendre_une_carte_pioche()\n", " display(Markdown(\"=> Vous piochez la carte {}.\".format(premiere_carte)))\n", " self.mains[personne].append(premiere_carte)\n", " if action.est_choisir():\n", " # soit une des cartes précedemment visibles\n", " choix = action.choix\n", " carte_choisie = self.visibles.pop(choix)\n", " display(Markdown(\"=> Vous récupérez la carte {}.\".format(carte_choisie)))\n", " self.mains[personne].append(carte_choisie)\n", " if action.est_japjap():\n", " # on vérifie que cette personne a bien un Jap Jap !\n", " valeur_du_premier_japjap = valeur_main(self.mains[personne])\n", " assert 1 <= valeur_du_premier_japjap <= 5\n", " gagnante = personne\n", " display(Markdown(\"=> Vous faites un Jap Jap, valant {} point{}.\".format(valeur_du_premier_japjap, \"s\" if valeur_du_premier_japjap > 1 else \"\")))\n", " contre_JapJap = False\n", "\n", " # on vérifie les valeurs des mains des autres personnes\n", " valeurs_mains = [valeur_main(main) for main in self.mains]\n", " plus_petite_valeur = min([valeurs_mains[autre_personne] for autre_personne in [ p for p in personnes if p != gagnante ]])\n", " if plus_petite_valeur < valeur_du_premier_japjap:\n", " print(\"CONTRE JAP JAP !\")\n", " # si une personne a un jap jap plus petit, la personne ne gagne pas\n", " contre_JapJap = True\n", " # la personne gagnante est la première (ordre du jeu) à obtenir le jap jap\n", " # de valeur minimale, et en cas d'égalité c'est la personne obtenant\n", " # cette valeur en le nombre minimal de cartes !\n", " gagnantes = [ p for p in personnes if valeurs_mains[p] == plus_petite_valeur ]\n", " print(\"Les autres personnes ayant un Jap Jap de plus petite valeur sont {} !\".format(gagnantes))\n", " nombre_min_carte = min([len(self.mains[p]) for p in gagnantes])\n", " gagnante = min([p for p in gagnantes if len(self.mains[p]) == nombre_min_carte])\n", " print(\"La personne gagnant la manche est {}.\".format(gagnante))\n", "\n", " # on marque les scores\n", " print(\"\\nOn marque les scores !\")\n", " print(\"==> La personne {} a gagné ! Avec un Jap Jap de valeur {} !\".format(gagnante, plus_petite_valeur))\n", " for autre_personne in [ p for p in personnes if p != gagnante ]:\n", " marque_point = valeur_main(self.mains[autre_personne])\n", " print(\"- La personne {} n'a pas gagné, et marque {} points\".format(autre_personne, marque_point))\n", " self.scores[autre_personne] += marque_point\n", " # si la personne s'est prise un contre jap jap, elle marque +25 et pas son total de cartes en main\n", " print(\"- La personne {} n'a pas gagné et a subi un CONTRE JAP JAP ! Elle marque +25 points.\")\n", " if contre_JapJap:\n", " self.scores[personne] -= valeur_main(self.mains[personne])\n", " self.scores[personne] += self.malusContreJapJap\n", " \n", " print(\"\\nA la fin de cette manche :\")\n", " for personne in self.personnes:\n", " nom = self.nomsPersonnes[personne] if self.nomsPersonnes is not None else personne\n", " score = self.scores[personne]\n", " print(\" + Personne {} a un score de {}.\".format(nom, score))\n", " \n", " # si un score est >= 90\n", " if max(self.scores) >= self.scoreMax:\n", " # quelqu'un a perdu cette partie !\n", " for personne in personnes:\n", " score = self.scores[personne]\n", " if score == max(self.scores):\n", " nom = self.nomsPersonnes[personne] if self.nomsPersonnes is not None else personne\n", " print(\"\\n==> La personne {} a perdu, avec un score de {}.\".format(nom, score))\n", " raise FinDunePartie\n", " raise FinDuneManche\n", " # on pose les cartes jetées\n", " self.visibles = jetees\n", " # et on enlève les cartes jetées de sa main\n", " nouvelle_main = self.mains[personne]\n", " for carte_jetee in jetees:\n", " nouvelle_main.remove(carte_jetee)\n", " # et ça continue" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Lancement du jeu intéractif" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [], "source": [ "jeu = EtatJeu(nomsPersonnes=[\"Alice\", \"Bob\"])" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [], "source": [ "jeu.debut_jeu()" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [], "source": [ "import asyncio" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/plain": [ ":72>>" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" }, { "name": "stdout", "output_type": "stream", "text": [ "- Nombre de carte dans la pioche : 41\n", "- Cartes visibles au sommet de la défausse : 1\n", " + Personne Bob a 5 cartes en main, et un score de 0.\n", " + Personne Alice a 5 cartes en main, et un score de 0.\n" ] }, { "data": { "text/markdown": [ "[Bob] Cartes en main : [ 9♠, 8♠, 1♥, 5♥, K♦]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "- Main : [ 9♠, 8♠, 1♥, 5♥, K♦] (valeur = 36)" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "- Sommet de la défausse [ 3♦]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "13c1c7ce72eb41f397417aa97ba40656", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(ToggleButtons(description='Action ?', icons=('question', 'list-ol'), options=('Une carte dans l…" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Okay, vous choisissez dans le sommet de la défausse.\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "eaea2fb46aa44d238d0beca09eb325e1", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(SelectMultiple(description='Quoi jeter ?', index=(0,), options=( 9♠, 8♠, 1♥, 5♥, K♦), style…" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ " ? Personne 1 joue l'action Choisir #0 avec les indices (4,) ...\n" ] }, { "data": { "text/markdown": [ "=> Vous récupérez la carte 3♦." ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "- Nombre de carte dans la pioche : 41\n", "- Cartes visibles au sommet de la défausse : 1\n", " + Personne Bob a 5 cartes en main, et un score de 0.\n", " + Personne Alice a 5 cartes en main, et un score de 0.\n" ] }, { "data": { "text/markdown": [ "[Alice] Cartes en main : [ 9♥, 8♦, Q♣, 9♣, 2♦]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "- Main : [ 9♥, 8♦, Q♣, 9♣, 2♦] (valeur = 40)" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "- Sommet de la défausse [ K♦]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "2e8e51b883f2434abb40c2c9417e45e1", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(ToggleButtons(description='Action ?', icons=('question', 'list-ol'), options=('Une carte dans l…" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Okay, vous piochez.\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "447c427f271b4825b163b8f5870e36a7", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(SelectMultiple(description='Quoi jeter ?', index=(0,), options=( 9♥, 8♦, Q♣, 9♣, 2♦), style…" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ " ? Personne 0 joue l'action Piocher avec les indices (2,) ...\n" ] }, { "data": { "text/markdown": [ "=> Vous piochez la carte 6♥." ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "- Nombre de carte dans la pioche : 40\n", "- Cartes visibles au sommet de la défausse : 1\n", " + Personne Bob a 5 cartes en main, et un score de 0.\n", " + Personne Alice a 5 cartes en main, et un score de 0.\n" ] }, { "data": { "text/markdown": [ "[Bob] Cartes en main : [ 9♠, 8♠, 1♥, 5♥, 3♦]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "- Main : [ 9♠, 8♠, 1♥, 5♥, 3♦] (valeur = 26)" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "- Sommet de la défausse [ Q♣]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "f086bec079ca4a64ae6727086c873168", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(ToggleButtons(description='Action ?', icons=('question', 'list-ol'), options=('Une carte dans l…" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Okay, vous piochez.\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "68dc433418af417483f0d3f84ff929b2", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(SelectMultiple(description='Quoi jeter ?', index=(0,), options=( 9♠, 8♠, 1♥, 5♥, 3♦), style…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "asyncio.ensure_future(jeu.enchainer_les_tours())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Conclusion" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.8" }, "toc": { "colors": { "hover_highlight": "#DAA520", "running_highlight": "#FF0000", "selected_highlight": "#FFD700" }, "moveMenuLeft": true, "nav_menu": { "height": "301.25px", "width": "251.5px" }, "navigate_menu": true, "number_sections": true, "sideBar": false, "threshold": 4, "toc_cell": true, "toc_position": { "height": "227.717px", "left": "1159px", "right": "20px", "top": "74px", "width": "257px" }, "toc_section_display": "block", "toc_window_display": true }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": { "0f9f2a30342d4d12baab3baf7f96435e": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "ToggleButtonModel", "state": { "button_style": "success", "description": "Jap Jap ? (32)", "icon": "check", "layout": "IPY_MODEL_752d5a531c8a46baacc03117cee842c1", "style": "IPY_MODEL_a8fc1a24a73a452696b0fe080d903738", "tooltip": "Votre main vaut moins de 5 points, donc vous pouvez terminer la partie !" } }, "15c911e08b634cbfb3c3096fceb8520e": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "ToggleButtonModel", "state": { "description": "Valider l'action ?", "layout": "IPY_MODEL_25fbd1496a874d3c8b3285610ce48d6c", "style": "IPY_MODEL_f1fc9323ea0048428f8967ffe7ed337f", "value": true } }, "16e8468df72b4d8b9a7a4d6dd2e856f6": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DescriptionStyleModel", "state": { "description_width": "initial" } }, "179383d71aec4d1a8184e21c6b6f9e5c": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "1f4b82de56934c509f6ec3fe500637c3": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "VBoxModel", "state": { "children": [ "IPY_MODEL_8293685294a94a7cb9fd6fa8c2ad482f", "IPY_MODEL_15c911e08b634cbfb3c3096fceb8520e" ], "layout": "IPY_MODEL_5035435d7fcc4736921596d11d2d4eca" } }, "25fbd1496a874d3c8b3285610ce48d6c": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "3a489c1f4e7c430687376d8b8d8b1725": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "46af7e5c28314cbfa1f4bd3734c7e7da": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "ToggleButtonModel", "state": { "description": "Valider l'action ?", "layout": "IPY_MODEL_179383d71aec4d1a8184e21c6b6f9e5c", "style": "IPY_MODEL_bbc3014ef85842129c8a4d69251d7b36", "value": true } }, "4f75e3000cf74d71be9a52c48df77ed7": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "ToggleButtonsModel", "state": { "_options_labels": [ "Une carte dans la pioche ", "Une carte du sommet de la défausse " ], "button_style": "", "description": "Action ?", "icons": [ "question", "list-ol" ], "index": 1, "layout": "IPY_MODEL_b897773332ad41d091d25dd1754341b9", "style": "IPY_MODEL_cd623ce10a4d4c46a83466b991ee6cb1", "tooltips": [ "invisible", "visibles" ] } }, "5035435d7fcc4736921596d11d2d4eca": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "6211d97a5d494078820c1439018c9caf": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "ToggleButtonsStyleModel", "state": { "button_width": "25vw", "description_width": "initial" } }, "6c9472bf2e9b424eaafaa654bb957f8c": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "713177feaee548558391237b1f581121": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "VBoxModel", "state": { "children": [ "IPY_MODEL_4f75e3000cf74d71be9a52c48df77ed7", "IPY_MODEL_46af7e5c28314cbfa1f4bd3734c7e7da" ], "layout": "IPY_MODEL_8ddf2bb711c54c52b12bcfa0cea19002" } }, "752d5a531c8a46baacc03117cee842c1": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "7be1588cfdae47a2bc41ece0d5ba2d7a": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "SelectMultipleModel", "state": { "_options_labels": [ "10♥", " V♥", " V♠" ], "description": "Quoi jeter ?", "index": [ 0 ], "layout": "IPY_MODEL_3a489c1f4e7c430687376d8b8d8b1725", "rows": 5, "style": "IPY_MODEL_16e8468df72b4d8b9a7a4d6dd2e856f6" } }, "8293685294a94a7cb9fd6fa8c2ad482f": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "SelectMultipleModel", "state": { "_options_labels": [ "10♦", " V♠", " 5♠", " 9♦", " 5♣" ], "description": "Quoi jeter ?", "index": [ 0, 3 ], "layout": "IPY_MODEL_6c9472bf2e9b424eaafaa654bb957f8c", "rows": 5, "style": "IPY_MODEL_e7ae141482b146629b6e13d83d9282de" } }, "8ddf2bb711c54c52b12bcfa0cea19002": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "a6242d3701494beaa279a8e2ba02c7b0": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "a8fc1a24a73a452696b0fe080d903738": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DescriptionStyleModel", "state": { "description_width": "initial" } }, "b897773332ad41d091d25dd1754341b9": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "bbc3014ef85842129c8a4d69251d7b36": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DescriptionStyleModel", "state": { "description_width": "" } }, "bdc494c7a8394d68a35f79598033bcd8": { "model_module": "@jupyter-widgets/base", "model_module_version": "1.1.0", "model_name": "LayoutModel", "state": {} }, "cd623ce10a4d4c46a83466b991ee6cb1": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "ToggleButtonsStyleModel", "state": { "button_width": "25vw", "description_width": "initial" } }, "d6054f63a4444cdca594f49cdcf68e5c": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "ToggleButtonsModel", "state": { "_options_labels": [ "Une carte dans la pioche ", "Une carte du sommet de la défausse " ], "button_style": "", "description": "Action ?", "icons": [ "question", "list-ol" ], "index": 0, "layout": "IPY_MODEL_bdc494c7a8394d68a35f79598033bcd8", "style": "IPY_MODEL_6211d97a5d494078820c1439018c9caf", "tooltips": [ "invisible", "visibles" ] } }, "d88fdc82c1434168a1c24db90b5c1a03": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "ToggleButtonsModel", "state": { "_options_labels": [ " V♠", "10♣" ], "button_style": "", "description": "Prendre quelle carte du sommet ?", "icons": [], "index": 0, "layout": "IPY_MODEL_a6242d3701494beaa279a8e2ba02c7b0", "style": "IPY_MODEL_e897ab6546d041f8a0cff056385ae3ce", "tooltips": [] } }, "e7ae141482b146629b6e13d83d9282de": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DescriptionStyleModel", "state": { "description_width": "initial" } }, "e897ab6546d041f8a0cff056385ae3ce": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "ToggleButtonsStyleModel", "state": { "button_width": "", "description_width": "initial" } }, "f1fc9323ea0048428f8967ffe7ed337f": { "model_module": "@jupyter-widgets/controls", "model_module_version": "1.4.0", "model_name": "DescriptionStyleModel", "state": { "description_width": "" } } }, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 2 }