jeu de morpion google
5/5 - (16 votes)

Si tu es en train de me lire, deux choses sont sûres, t’es un geek dans l’âme, et tu ne dis jamais non à un petit défi de programmation. Hé bien ça tombe bien parce qu’on va parler du jeu Morpion de Google (aussi appelé tic-tac-toe) ! Un véritable easter egg de Google qui apparaît dans les résultats de recherche. En cherchant tu peux aussi trouver d’autres jeux comme le solitaire.

 

Pourquoi Google nous offre-t-il ce cadeau de geek ?

Google est aussi le roi des “rich snippets“, ces petits plus qui te facilitent la vie direct dans les résultats de recherche. C’est le cas de notre Morpion, qui apparaît quand tu tapes “jeu Morpion” (parfois tu dois préciser “Google”) dans la barre de recherche et qui a été introduit le 27 août 2016. Pourquoi ? Parce que Google est cool, voilà tout.

 

Ok, mais comment ça fonctionne le Morpion ?

Google utilise des extraits enrichis pour ce faire. En gros, t’as une petite interface interactive qui te permet de jouer contre un ordinateur pas très futé ( enfin … si tu met en “impossible”, c’est vraiment impossible). Puis tu clic tout simplement.

 

jeu du morpion google

 

Créer un bot avec Python et Selenium pour jouer en mode automatique au jeu de morpion Google

Allez, maintenant, le fun commence ! Si tu te sens d’humeur hacker, pourquoi ne pas automatiser cette petite partie de Morpion ? T’emballe pas non plus, on reste dans le légal ! C’est juste pour le fun et la gloire.

 

 

Quels modules Python installer pour créer ce bot ?

 

import os
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import ElementClickInterceptedException, TimeoutException, NoSuchElementException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

 

A quoi servent toutes ces dépendances ?

 

1. import os

Alors, os c’est un module en Python qui te donne accès à des fonctionnalités dépendantes du système d’exploitation. “Genre quoi ?” me demanderas-tu. Eh bien, ça peut être pour manipuler les chemins de fichiers, les variables d’environnement, et plein d’autres trucs utiles quand tu bosses sur un bot.

 

2. from selenium import webdriver

webdriver, C’est le cœur de notre bot. Selenium, c’est une librairie en Python qui permet de contrôler un navigateur web comme si c’était toi derrière le clavier et la souris. Et webdriver, c’est le composant qui te permet de dire “Hé, navigateur, ouvre cette page, clique ici, remplis ce formulaire”. Bref, sans webdriver, pas de fiesta !

 

3. from selenium.webdriver.common.by import By

Ici, By est un petit outil bien pratique pour dire à Selenium comment tu veux sélectionner les éléments sur la page web. “Je veux cliquer sur le bouton dont l’id est ‘play'”.

 

4. from selenium.webdriver.common.action_chains import ActionChains

ActionChains c’est la classe qui va te permettre de faire des actions un peu plus complexes, comme du glisser-déposer, ou des séquences d’actions. “Je veux cliquer, attendre 3 secondes, puis taper du texte”. ActionChains est ton meilleur pote pour ça.

 

5. from selenium.common.exceptions import ElementClickInterceptedException, TimeoutException, NoSuchElementException

On entre dans le vif du sujet ! Ces trois exceptions sont là pour gérer les petits pépins qui peuvent survenir. Un élément qui ne peut pas être cliqué (ElementClickInterceptedException), une action qui prend trop de temps (TimeoutException), ou un élément introuvable (NoSuchElementException). Avec ces exceptions, ton bot est prêt à affronter les imprévus !

 

6. from selenium.webdriver.support.ui import WebDriverWait

WebDriverWait, c’est un peu le Gandalf de ton code. “Tu ne passeras pas… tant que l’élément n’est pas chargé !” C’est un moyen d’attendre qu’un élément soit prêt avant de continuer. Pas de précipitation, on attend que tout soit en place !

 

7. from selenium.webdriver.support import expected_conditions as EC

Ici, expected_conditions (qu’on abrège en EC parce qu’on est des flemmards), c’est une collection de conditions prêtes à l’emploi pour WebDriverWait. “Attends que le bouton soit cliquable”, “Attends que l’élément soit visible”. EC est là pour te faciliter la vie.

 

8. import time

Et enfin, time. Ce vieux module Python est là pour gérer tout ce qui est en rapport avec le temps. Besoin de faire une petite pause dans ton code ? time.sleep(1) et voilà, une seconde de répit. Parce que parfois, même un bot a besoin de souffler au cas ou tu savais pas !

 

bot fatigué

 

Le code source du bot détaillé

 

Définir une fonction pour prendre des captures d’écran

def take_screenshot(driver, name):

Ici, on crée une fonction appelée take_screenshot. Elle prend deux paramètres : driver, qui est notre navigateur automatisé, et name, le nom qu’on veut donner à notre capture d’écran.

 

Préparer le dossier de destination

screenshot_folder = "screenshots"
if not os.path.exists(screenshot_folder):
    os.makedirs(screenshot_folder)

On définit un dossier pour stocker nos captures d’écran, et on le crée s’il n’existe pas déjà. Comme ça, toutes nos captures seront bien rangées au même endroit.

 

Prendre la capture d’écran et la sauvegarder

driver.save_screenshot(os.path.join(screenshot_folder, f"{name}.png"))

Enfin, on dit à notre navigateur de prendre une capture d’écran et de la sauvegarder dans le dossier qu’on vient de préparer, avec le nom qu’on a choisi.

 

Configurer le navigateur et accéder au jeu de morpion

driver = webdriver.Chrome()
driver.get("https://www.google.com/search?q=jeu+morpion+google")

On initialise notre navigateur Chrome et on lui dit d’aller sur la page Google pour chercher le jeu de Morpion.

 

Accepter les conditions d’utilisation de Google

consent_button = driver.find_element(By.CSS_SELECTOR, "button[id='W0wltc']")
consent_button.click()

Ensuite, on trouve le bouton pour accepter les conditions d’utilisation de Google (oui, on est tous un peu flemmards et on ne les lit jamais) et on clique dessus.

 

Capture d’écran

take_screenshot(driver, "apres_consentement")

 

Laisser le temps au jeu de se charger

time.sleep(3)

Et on termine avec une petite pause de 3 secondes, le temps que tout se charge correctement et que le jeu soit prêt à être joué.

 

La boucle infinie

while True:

Ici, on commence par dire à l’ordinateur : “Tant que tu as de l’énergie, continue de jouer !” C’est une boucle infinie qui ne s’arrêtera que si on décide manuellement de stopper le script.

 

Parcourir le plateau de jeu

for row in range(3):
    for col in range(3):

Ensuite, on fait deux boucles pour parcourir toutes les cases du Morpion. La première boucle (avec row) va de 0 à 2 et représente les lignes, et la deuxième boucle (avec col) va aussi de 0 à 2 et représente les colonnes.

 

Tentons de cliquer sur une case

try:
    cell = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.CSS_SELECTOR, f"td[data-col='{col}'][data-row='{row}']"))
    )
    ActionChains(driver).move_to_element(cell).click().perform()
    print(f"Clic sur la case ({row}, {col}) : OK \n")
    time.sleep(1)

Là, ça se corse un peu. On dit au navigateur : “Hé, tu vois cette case du Morpion située à la ligne row et à la colonne col ? Essaye de cliquer dessus !” Si la case est prête à être cliquée en moins de 10 secondes, on clique. Puis, on attend une petite seconde avec time.sleep(1), histoire de laisser le temps au jeu de se mettre à jour.

 

Gérer les petits soucis

except ElementClickInterceptedException:
    print(f"La case ({row}, {col}) a été interceptée par un autre élément, on passe à la suivante.")
except TimeoutException:
    print(f"La case ({row}, {col}) n'était pas cliquable dans le temps imparti.")

Mais parfois, ça ne se passe pas comme prévu. Si un autre élément vient se mettre devant notre case, on l’ignore et on passe à la suivante. Si la case ne devient pas cliquable assez vite, on l’ignore aussi. Dans les deux cas, on affiche un petit message pour savoir ce qu’il s’est passé.

 

La partie est finie, on recommence !

time.sleep(1)
try:
    replay_button = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.CSS_SELECTOR, "g-raised-button[role='button']"))
    )
    replay_button.click()
    print("Partie terminée, clic sur Rejouer : OK")
except NoSuchElementException:
    print("Bouton Rejouer non trouvé")
except TimeoutException:
    print("Le bouton Rejouer n'était pas cliquable dans le temps imparti.")

Une fois qu’on a tenté notre chance sur toutes les cases, on attend une seconde, et on cherche le bouton “Rejouer” pour lancer une nouvelle partie. Si le bouton est trouvé et cliquable, on clique. Sinon, on affiche un message d’erreur.

 

Code source complet du bot qui joue au Morpion Google

# Importer le module os pour interagir avec le système d'exploitation
import os
# Importer webdriver de selenium pour automatiser les actions dans le navigateur
from selenium import webdriver
# Importer By pour définir comment sélectionner les éléments dans la page
from selenium.webdriver.common.by import By
# Importer ActionChains pour réaliser des actions complexes comme le drag and drop
from selenium.webdriver.common.action_chains import ActionChains
# Importer des exceptions spécifiques pour gérer les erreurs potentielles
from selenium.common.exceptions import ElementClickInterceptedException, TimeoutException, NoSuchElementException
# Importer WebDriverWait pour attendre qu'un élément soit prêt à être manipulé
from selenium.webdriver.support.ui import WebDriverWait
# Importer expected_conditions comme EC pour définir des conditions d'attente spécifiques
from selenium.webdriver.support import expected_conditions as EC
# Importer le module time pour manipuler le temps (pauses, etc.)
import time

# Définir une fonction pour prendre une capture d'écran et la sauvegarder
def take_screenshot(driver, name):
    # Définir le dossier où sauvegarder les captures d'écran
    screenshot_folder = "screenshots"
    # Créer le dossier s'il n'existe pas déjà
    if not os.path.exists(screenshot_folder):
        os.makedirs(screenshot_folder)
    # Prendre la capture d'écran et la sauvegarder dans le dossier défini
    driver.save_screenshot(os.path.join(screenshot_folder, f"{name}.png"))

# Initialiser le navigateur Chrome
driver = webdriver.Chrome()
# Accéder à la page de recherche Google pour le jeu de morpion
driver.get("https://www.google.com/search?q=jeu+morpion+google")
# Trouver et cliquer sur le bouton pour accepter les conditions d'utilisation de Google
consent_button = driver.find_element(By.CSS_SELECTOR, "button[id='W0wltc']")
consent_button.click()
take_screenshot(driver, "apres_consentement")

# Attendre 3 secondes pour s'assurer que la page ait le temps de se charger complètement
time.sleep(3)

# Boucle infinie pour jouer indéfiniment
while True:
    # Parcourir chaque ligne de la grille de morpion
    for row in range(3):
        # Parcourir chaque colonne de la grille de morpion
        for col in range(3):
            # Essayer de cliquer sur chaque cellule de la grille
            try:
                # Attendre que la cellule soit cliquable et la stocker dans la variable 'cell'
                cell = WebDriverWait(driver, 10).until(
                    EC.element_to_be_clickable((By.CSS_SELECTOR, f"td[data-col='{col}'][data-row='{row}']"))
                )
                # Cliquer sur la cellule
                ActionChains(driver).move_to_element(cell).click().perform()
                # Imprimer un message confirmant le clic
                print(f"Clic sur la case ({row}, {col}) : OK \n")
                # Attendre 1 seconde avant de continuer
                time.sleep(1)
            # Gérer le cas où un élément bloque le clic
            except ElementClickInterceptedException:
                # Imprimer un message indiquant que la cellule est bloquée
                print(f"La case ({row}, {col}) a été interceptée par un autre élément, on passe à la suivante.")
            # Gérer le cas où la cellule n'est pas cliquable dans le temps imparti
            except TimeoutException:
                # Imprimer un message indiquant que la cellule n'est pas cliquable
                print(f"La case ({row}, {col}) n'était pas cliquable dans le temps imparti.")

    # Attendre 1 seconde à la fin de chaque partie
    time.sleep(1)
    # Essayer de cliquer sur le bouton pour rejouer
    try:
        # Attendre que le bouton 'Rejouer' soit cliquable et le stocker dans la variable 'replay_button'
        replay_button = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, "g-raised-button[role='button']"))
        )
        # Cliquer sur le bouton 'Rejouer'
        replay_button.click()
        # Imprimer un message confirmant le clic sur 'Rejouer'
        print("Partie terminée, clic sur Rejouer : OK")
    # Gérer le cas où le bouton 'Rejouer' n'est pas trouvé
    except NoSuchElementException:
        # Imprimer un message indiquant que le bouton 'Rejouer' n'est pas trouvé
        print("Bouton Rejouer non trouvé")
    # Gérer le cas où le bouton 'Rejouer' n'est pas cliquable dans le temps imparti
    except TimeoutException:
        # Imprimer un message indiquant que le bouton 'Rejouer' n'est pas cliquable
        print("Le bouton Rejouer n'était pas cliquable dans le temps imparti.")

 

Comment améliorer le bot ?

On a décortiqué chaque ligne, chaque commande, et maintenant, tu dois te sentir un peu comme Neo dans Matrix, voyant le code source de la réalité, non ?

Neo dans Matrix

Mais en réalité, notre bot, il est plutôt comme ça :

Sinok

il est sympa, il fait le job, mais il pourrait être un peu plus futé. Actuellement, il clique partout, sans réfléchir, comme un gamin hyperactif lâché dans un magasin de bonbons. Et si on le rendait un peu plus stratégique ?

 

5 étapes pour améliorer le bot pour augmenter les chances de gagner au morpion de Google

1. Stratégie de Jeu : Pour le moment, le bot joue de manière aléatoire. On pourrait le rendre plus malin en implémentant un algorithme de minimax, typiquement utilisé pour les jeux à deux joueurs comme le morpion. Le minimax permettrait au bot de calculer le meilleur coup possible à chaque tour. Il existe des tonnes de tutoriels là-dessus, donc si tu as envie de mettre les mains dans le cambouis, fonce !

2. Apprentissage Automatique : Pourquoi pas entraîner un modèle de machine learning pour jouer au morpion ? Des frameworks comme TensorFlow ou PyTorch pourraient t’aider. Attention, ça risque d’être un peu “exagéré” pour un simple jeu de morpion, mais qui sait, tu pourrais créer le prochain AlphaGo du morpion !

3. Interface Utilisateur : Pourquoi ne pas développer une petite interface graphique avec Tkinter ou PyQt pour rendre les interactions avec le bot plus user-friendly ?

4. Gestion des Erreurs : Notre bot est plutôt robuste, mais on pourrait toujours améliorer sa gestion des erreurs. Par exemple, ajouter des logs plus détaillés ou des tentatives de récupération en cas d’erreur pourrait être un plus.

5. Optimisation du Code : Enfin, une petite session de refactoring ne fait jamais de mal. Peut-être qu’il y a des parties du code qui pourraient être optimisées ou écrites de manière plus pythonique.

 

Pour finir, j’espère que t’as kiffé la balade autant que moi, et que t’as réussi à piger deux-trois trucs sur ce petit bot joueur de morpion. N’hésites pas à l’améliorer et à le partager 😉

Et si tu as vraiment kiffé la création de ce p’tit bot, hésites pas à jeter un oeil sur le tuto qui te permet de créer un script de surveillance de backlinks.