{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "d65838d4",
   "metadata": {},
   "source": [
    "# Jeu de morpion en python\n",
    "\n",
    "## Afficher et stocker une grille 3 x 3\n",
    "\n",
    "On affichera (sous forme de texte pour faire simple) un grille contenant des symboles 'X' ou 'O' en fonction du joueur, et un espace si l'emplacement n'a pas encore été joué."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "5592aafb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-------------\n",
      "| X | O |   |\n",
      "-------------\n",
      "| O | X | O |\n",
      "-------------\n",
      "|   |   | X |\n",
      "-------------\n"
     ]
    }
   ],
   "source": [
    "# affichage d'une grille quelconque\n",
    "\n",
    "def affiche_grille():\n",
    "    print('-------------')\n",
    "    print('| X | O |   |')\n",
    "    print('-------------')\n",
    "    print('| O | X | O |')\n",
    "    print('-------------')\n",
    "    print('|   |   | X |')\n",
    "    print('-------------')\n",
    "\n",
    "affiche_grille()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "425820f1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# modèle de grille : une liste de liste indexée dans l'ordre ligne puis colonne\n",
    "# exemple :\n",
    "grille = [['X', 'O', ' '], ['O', 'X', 'O'], [' ', ' ', 'X']]\n",
    "\n",
    "# ainsi l'emplacement en bas à gauche sera à la position (2,0) et accessible ainsi : grille[2][0]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a83d3007",
   "metadata": {},
   "source": [
    "## 1- modifier *affiche_grille()* pour afficher une grille quelconque en paramètre"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "47d41e84",
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "affiche_grille() takes 0 positional arguments but 1 was given",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-3-e7f3f440edb1>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[1;31m# le résultat devra être :\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0maffiche_grille\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mgrille\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m: affiche_grille() takes 0 positional arguments but 1 was given"
     ]
    }
   ],
   "source": [
    "# le résultat devra être :\n",
    "affiche_grille(grille)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "96254b53",
   "metadata": {},
   "source": [
    "## 2- créer une fonction *gagnant()*\n",
    "\n",
    "Cette fonction prend une grille quelconque en paramètre, elle renvoie le symbole du gagnant s'il y en a un, et un espace sinon. Il faut vérifier les 3 alignements en colonne, les 3 alignements en ligne et les 2 diagonales."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "dc10d047",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "X\n"
     ]
    }
   ],
   "source": [
    "# sur notre exemple la fonction doit renvoyer :\n",
    "print(gagnant(grille))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e713e642",
   "metadata": {},
   "source": [
    "## 3- créer une fonction *valide()*\n",
    "\n",
    "Cette fonction vérifie si une position quelconque (c'est-à-dire une liste contenant les deux indices : lignes et colonnes) est valide pour jouer et renvoie vrai ou faux :\n",
    "les indices doivent être dans la grille (compris entre 0 et 2) et libre (la grille doit contenir un espace à cet endroit) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "2ece2cb8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "# sur notre exemple cette fonction doit renvoyer les valeurs suivantes :\n",
    "print(valide(grille, [3, 3]))\n",
    "print(valide(grille, [0, 2]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "13bcfd74",
   "metadata": {},
   "source": [
    "## 4- créer une fonction *position()*\n",
    "\n",
    "Cette fonction renvoie une position à partir de la saisie faite au clavier par le joueur (le symbole du joueur sera passé en paramètre).\n",
    "Le plus simple est de demander séparément les deux coordonnées X et Y (attention, ces indices doivent être des entiers) et les mettre dans une liste"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ef29f2e0",
   "metadata": {},
   "source": [
    "## 5- le programme de jeux\n",
    "\n",
    "Les tours de jeu alternent : les tours pairs sont ceux du joueur 0 ('X') et les tours impairs ceux du joueur 1 ('O'). \n",
    "Il vous faudra un compteur de tour. Il ne pourra pas y avoir plus de 9 tours.\n",
    "\n",
    "+ Commencez par créer une grille vide (ne contenant que des espaces),\n",
    "un compteur du nombre de tours joués (initialisé à 0), et la liste des deux symboles (des deux joueurs)\n",
    "\n",
    "+ Construisez une boucle qui demande une position de jeux (et l'enregistre si elle est valide) tant que personne n'a gagné et que le compteur est inférieur à 9. Il faudra vérifier la saisie pour s'assurer qu'elle est valide."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "19be2b16",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-------------\n",
      "| O | X | O |\n",
      "-------------\n",
      "|   | X |   |\n",
      "-------------\n",
      "| O | X | X |\n",
      "-------------\n",
      "\n",
      " ** le joueur X a gagné **\n"
     ]
    }
   ],
   "source": [
    "# programme principal à compléter\n",
    "grille = [[' ', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']]\n",
    "ncoup = 0\n",
    "symb = ['X', 'O']\n",
    "affiche_grille(grille)\n",
    "\n",
    "while (...) and (...):\n",
    "    tour = ncoup % 2\n",
    "    ...\n",
    "    ncoup = ncoup + 1\n",
    "    affiche_grille(grille)\n",
    "\n",
    "print(\"\\n ** le joueur \" + gagnant(grille) + \" a gagné **\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "14d0d36d",
   "metadata": {},
   "source": [
    "# Complément : jouer contre l'ordinateur\n",
    "\n",
    "L'ordinateur va jouer de manière simple :\n",
    "\n",
    "+ il joue la première position qu'il trouve qui lui permettrait de gagner\n",
    "+ si il n'en trouve pas, il jour la première position qu'il trouve qui permettrait à l'autre joueur de gagner au tour suivant\n",
    "+ si aucun des deux cas de figure précédent ne se produisent, il joue au hasard\n",
    "\n",
    "On pourra apporter des modifications non définitives à la grille, par exemple pour essayer des coups (et regarder leur intérêt avec la fonction *gagnant()*), attention à remettre ensuite un espace à la place du symbole que l'on aura essayé.\n",
    "\n",
    "Pour tirer une position au hasard vous pouvez vous inspirer du code suivant :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "5695635f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# tirer une position *pos* au hasard dans une liste de *positions* prédéfinies :\n",
    "from random import randint\n",
    "\n",
    "positions = [[0, 2], [2, 0], [2, 1]]\n",
    "taille = len(positions)\n",
    "qui = randint(0, taille-1)\n",
    "pos = positions[qui]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "6b986eba",
   "metadata": {},
   "outputs": [],
   "source": [
    "# fonction qui renvoie les coordonnées de jeux choisies par l'ordinateur\n",
    "def jouer(lig, moi, adv):\n",
    "    \n",
    "    # chercher un coup gagnant\n",
    "    for l in range(0,3):\n",
    "        for c in range(0,3): \n",
    "            # cherche une place libre\n",
    "            if lig[l][c] == ' ':\n",
    "                # regarder si elle me fait gagner - je la joue\n",
    "                lig[l][c] = moi\n",
    "                if gagnant(lig) == moi:\n",
    "                    lig[l][c] = ' '\n",
    "                    return([l, c])\n",
    "                lig[l][c] = ' '\n",
    "                    \n",
    "    # si je n'ai pas trouvé de coup gagant\n",
    "    for l in range(0,3):\n",
    "        for c in range(0,3): \n",
    "            # cherche une place libre\n",
    "            if lig[l][c] == ' ':\n",
    "                # regarder si elle fait gagner l'autre - je la joue\n",
    "                lig[l][c] = adv\n",
    "                if gagnant(lig) == adv:\n",
    "                    lig[l][c] = ' '\n",
    "                    return([l, c]) \n",
    "                lig[l][c] = ' '\n",
    "                    \n",
    "    # si pas de bonne place évidente : tirage au sort d'une place libre\n",
    "    libres = []\n",
    "    for l in range(0,3):\n",
    "        for c in range(0,3):\n",
    "            if lig[l][c] == ' ':\n",
    "                libres.append([l, c])\n",
    "    ou = randint(0, len(libres)-1)\n",
    "    return(libres[ou])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "35f56cd6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-------------\n",
      "| X |   |   |\n",
      "-------------\n",
      "| O | X |   |\n",
      "-------------\n",
      "| O |   |   |\n",
      "-------------\n",
      "[2, 2]\n"
     ]
    }
   ],
   "source": [
    "# vérification du bon fonctionnement 1\n",
    "lignes = [['X', ' ', ' '], ['O', 'X', ' '], ['O', ' ', ' ']]\n",
    "affiche_grille(lignes)\n",
    "print(jouer(lignes, 'X', 'O'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "cdc2c35c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-------------\n",
      "| X |   |   |\n",
      "-------------\n",
      "| O |   |   |\n",
      "-------------\n",
      "| O |   | X |\n",
      "-------------\n",
      "[1, 1]\n"
     ]
    }
   ],
   "source": [
    "# vérification du bon fonctionnement 2\n",
    "lignes = [['X', ' ', ' '], ['O', ' ', ' '], ['O', ' ', 'X']]\n",
    "affiche_grille(lignes)\n",
    "print(jouer(lignes, 'O', 'X'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "8dc12d00",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-------------\n",
      "| X |   |   |\n",
      "-------------\n",
      "| O |   |   |\n",
      "-------------\n",
      "| O | X |   |\n",
      "-------------\n",
      "[0, 1]\n"
     ]
    }
   ],
   "source": [
    "# vérification du bon fonctionnement 3\n",
    "lignes = [['X', ' ', ' '], ['O', ' ', ' '], ['O', 'X', ' ']]\n",
    "affiche_grille(lignes)\n",
    "print(jouer(lignes, 'X', 'O'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "4e5b9ba7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-------------\n",
      "| X | X |   |\n",
      "-------------\n",
      "|   | X |   |\n",
      "-------------\n",
      "| O | O | O |\n",
      "-------------\n",
      "\n",
      " ** le joueur O a gagné **\n"
     ]
    }
   ],
   "source": [
    "grille = [[' ', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']]\n",
    "ncoup = 0\n",
    "symb = ['X', 'O']\n",
    "affiche_grille(grille)\n",
    "\n",
    "while (gagnant(grille) == ' ') and (ncoup < 9):\n",
    "    tour = ncoup % 2\n",
    "    pos = []\n",
    "    if tour == 0: # tout de l'humain qui commence\n",
    "        pos = position(symb[tour])\n",
    "        while (not valide(grille, pos)) :\n",
    "            pos = position(symb[tour])\n",
    "    else:  # l'ordi est le joueur 1\n",
    "        pos = jouer(grille, symb[tour], symb[tour-1])\n",
    "    grille[pos[0]][pos[1]] = symb[tour]\n",
    "    ncoup = ncoup + 1\n",
    "    affiche_grille(grille)\n",
    "\n",
    "print(\"\\n ** le joueur \" + gagnant(grille) + \" a gagné **\")"
   ]
  }
 ],
 "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.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
