{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ef960830",
   "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": 20,
   "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": 21,
   "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": "5c73f372",
   "metadata": {},
   "source": [
    "## 1- modifier *affiche_grille()* pour afficher une grille quelconque en paramètre"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "7672dd25",
   "metadata": {},
   "outputs": [],
   "source": [
    "# affichage d'une grille passée en paramètre\n",
    "\n",
    "def affiche_grille(lig):\n",
    "    print('-------------')\n",
    "    print('|', lig[0][0],'|', lig[0][1], '|', lig[0][2], '|')\n",
    "    print('-------------')\n",
    "    print('|', lig[1][0],'|', lig[1][1], '|', lig[1][2], '|')\n",
    "    print('-------------')\n",
    "    print('|', lig[2][0],'|', lig[2][1], '|', lig[2][2], '|')\n",
    "    print('-------------')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "f3b14011",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-------------\n",
      "| X | O |   |\n",
      "-------------\n",
      "| O | X | O |\n",
      "-------------\n",
      "|   |   | X |\n",
      "-------------\n"
     ]
    }
   ],
   "source": [
    "# le résultat devra être :\n",
    "affiche_grille(grille)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c685ecf8",
   "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": 24,
   "id": "f47be254",
   "metadata": {},
   "outputs": [],
   "source": [
    "# si trois symboles alignés, renvoie le symbole gagnant, sinon un espace\n",
    "def gagnant(lig):\n",
    "    for i in range(0,3):\n",
    "        #ligne\n",
    "        if lig[i][0] != ' ' and lig[i][0] == lig[i][1] and lig[i][0] == lig[i][2]:\n",
    "            return(lig[i][0])\n",
    "        #col\n",
    "        if lig[0][i] != ' ' and lig[0][i] == lig[1][i] and lig[0][i] == lig[2][i]:\n",
    "            return(lig[0][i])\n",
    "    #diagonale 1\n",
    "    if lig[0][0] != ' ' and lig[0][0] == lig[1][1] and lig[0][0] == lig[2][2]:\n",
    "        return(lig[0][0])\n",
    "    #diagonale 2\n",
    "    if lig[0][2] != ' ' and lig[0][2] == lig[1][1] and lig[0][2] == lig[2][0]:\n",
    "        return(lig[0][2])\n",
    "    return(' ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "37490f95",
   "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": "1cefa48d",
   "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": 7,
   "id": "a76cc0ee",
   "metadata": {},
   "outputs": [],
   "source": [
    "# peut on jouer à la position (plig, pcol)\n",
    "def valide(lig, pos):\n",
    "    # vérifier la validité des indices\n",
    "    plage = [0,1,2]\n",
    "    if (pos[0] in plage) and (pos[1] in plage):\n",
    "    # vérifier que c'est libre (contient un ' ')\n",
    "        return(lig[pos[0]][pos[1]] == ' ')\n",
    "    return(False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "1479eb1c",
   "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": "ff077299",
   "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": "code",
   "execution_count": 9,
   "id": "e782fb52",
   "metadata": {},
   "outputs": [],
   "source": [
    "def position(s):\n",
    "    print(\"Au tour du joueur \" + s)\n",
    "    l = int(input('indice de ligne : '))\n",
    "    c = int(input('indice de col : '))\n",
    "    p = [l,c]\n",
    "    return(p)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "96291f95",
   "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": 10,
   "id": "19be2b16",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-------------\n",
      "|   |   |   |\n",
      "-------------\n",
      "|   |   |   |\n",
      "-------------\n",
      "|   |   |   |\n",
      "-------------\n",
      "Au tour du joueur X\n",
      "indice de ligne : 5\n",
      "indice de col : 4\n",
      "Au tour du joueur X\n",
      "indice de ligne : 1\n",
      "indice de col : 1\n",
      "-------------\n",
      "|   |   |   |\n",
      "-------------\n",
      "|   | X |   |\n",
      "-------------\n",
      "|   |   |   |\n",
      "-------------\n",
      "Au tour du joueur O\n",
      "indice de ligne : 2\n",
      "indice de col : 1\n",
      "-------------\n",
      "|   |   |   |\n",
      "-------------\n",
      "|   | X |   |\n",
      "-------------\n",
      "|   | O |   |\n",
      "-------------\n",
      "Au tour du joueur X\n",
      "indice de ligne : 0\n",
      "indice de col : 1\n",
      "-------------\n",
      "|   | X |   |\n",
      "-------------\n",
      "|   | X |   |\n",
      "-------------\n",
      "|   | O |   |\n",
      "-------------\n",
      "Au tour du joueur O\n",
      "indice de ligne : 2\n",
      "indice de col : 0\n",
      "-------------\n",
      "|   | X |   |\n",
      "-------------\n",
      "|   | X |   |\n",
      "-------------\n",
      "| O | O |   |\n",
      "-------------\n",
      "Au tour du joueur X\n",
      "indice de ligne : 0\n",
      "indice de col : 0\n",
      "-------------\n",
      "| X | X |   |\n",
      "-------------\n",
      "|   | X |   |\n",
      "-------------\n",
      "| O | O |   |\n",
      "-------------\n",
      "Au tour du joueur O\n",
      "indice de ligne : 2\n",
      "indice de col : 2\n",
      "-------------\n",
      "| X | X |   |\n",
      "-------------\n",
      "|   | X |   |\n",
      "-------------\n",
      "| O | O | O |\n",
      "-------------\n",
      "\n",
      " ** le joueur O a gagné **\n"
     ]
    }
   ],
   "source": [
    "# programme principal\n",
    "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 = position(symb[tour])\n",
    "    while (not valide(grille, pos)) :\n",
    "        pos = position(symb[tour])\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é **\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "becd966b",
   "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": 11,
   "id": "19f530a4",
   "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": 12,
   "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": 13,
   "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": 14,
   "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": 15,
   "id": "53397e1b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-------------\n",
      "| X |   |   |\n",
      "-------------\n",
      "| O |   |   |\n",
      "-------------\n",
      "| O | X |   |\n",
      "-------------\n",
      "[2, 2]\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": 16,
   "id": "6b0d3490",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-------------\n",
      "|   |   |   |\n",
      "-------------\n",
      "|   |   |   |\n",
      "-------------\n",
      "|   |   |   |\n",
      "-------------\n",
      "Au tour du joueur X\n",
      "indice de ligne : 1\n",
      "indice de col : 1\n",
      "-------------\n",
      "|   |   |   |\n",
      "-------------\n",
      "|   | X |   |\n",
      "-------------\n",
      "|   |   |   |\n",
      "-------------\n",
      "-------------\n",
      "|   |   |   |\n",
      "-------------\n",
      "|   | X |   |\n",
      "-------------\n",
      "|   |   | O |\n",
      "-------------\n",
      "Au tour du joueur X\n",
      "indice de ligne : 2\n",
      "indice de col : 1\n",
      "-------------\n",
      "|   |   |   |\n",
      "-------------\n",
      "|   | X |   |\n",
      "-------------\n",
      "|   | X | O |\n",
      "-------------\n",
      "-------------\n",
      "|   | O |   |\n",
      "-------------\n",
      "|   | X |   |\n",
      "-------------\n",
      "|   | X | O |\n",
      "-------------\n",
      "Au tour du joueur X\n",
      "indice de ligne : 1\n",
      "indice de col : 0\n",
      "-------------\n",
      "|   | O |   |\n",
      "-------------\n",
      "| X | X |   |\n",
      "-------------\n",
      "|   | X | O |\n",
      "-------------\n",
      "-------------\n",
      "|   | O |   |\n",
      "-------------\n",
      "| X | X | O |\n",
      "-------------\n",
      "|   | X | O |\n",
      "-------------\n",
      "Au tour du joueur X\n",
      "indice de ligne : 0\n",
      "indice de col : 2\n",
      "-------------\n",
      "|   | O | X |\n",
      "-------------\n",
      "| X | X | O |\n",
      "-------------\n",
      "|   | X | O |\n",
      "-------------\n",
      "-------------\n",
      "|   | O | X |\n",
      "-------------\n",
      "| X | X | O |\n",
      "-------------\n",
      "| O | X | O |\n",
      "-------------\n",
      "Au tour du joueur X\n",
      "indice de ligne : 0\n",
      "indice de col : 0\n",
      "-------------\n",
      "| X | O | X |\n",
      "-------------\n",
      "| X | X | O |\n",
      "-------------\n",
      "| O | X | O |\n",
      "-------------\n",
      "\n",
      " ** le joueur   a gagné **\n"
     ]
    }
   ],
   "source": [
    "from IPython.display import clear_output\n",
    "\n",
    "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",
    "\n",
    "    affiche_grille(grille)\n",
    "\n",
    "print(\"\\n ** le joueur \" + gagnant(grille) + \" a gagné **\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5208e4af",
   "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.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
