Atelier : Jeu Puissance 4.


Prérequis : développement d'interfaces en Visual Basic, récursivité.

1
Développement de l'interface.

Le premier travail est de développer une interface semblable à celle représentée ci-contre :


2
Quelques structures de données essentielles.

Entre autres, on aura besoin des données suivantes :

Toutes ces données, qui représentent la situation du jeu à un moment donnée, doivent être regroupées dans un type défini par l'utilisateur : TJeu. Cela nous servira énormément lors de la réflexion de l'ordinateur.

3
Algorithme princial :
faire jouer deux joueurs humains.

Dans la procédure Sub Main d'un module (qui représentera le point d'entrée de votre programme, réalisez l'algorithme suivant (remarque : ce qui doit être à nouveau décomposé en fonction ou procédure est écrit en bleu. Ce qui peut être écrit directement en une ou deux instructions est écrit en noir) :

Afficher Form1
Initialiser le jeu
Répéter
  Faire Jouer le joueur courant
  Inverser le joueur courant
Jusqu'à ce que la partie soit finie
Afficher le résultat de la partie

Pour compléter ceci, vous devez écrire les procédures et fonctions suivantes :

A ce stade, votre programme devrait marcher avec deux joueurs humains.

Rappels sur... Programmer proprement !

Pour que votre programme soit lisible par vous, par le prof et par ceux qui sont susceptible de maintenir vos applications, n'oubliez pas les points suivants, tous fondamentaux :

  • utilisez des noms de variables explicites, quitte à les rallonger. Par exemple :
    • n'utilisez pas : i, j, k ; n , max ;
    • utilisez : iColonne, JoueurCourant, NiveauMaximum, CoupSaisi, etc. ;
  • Indentez le code
  • Commenter votre code. En général, un commentaire par fonction suffit.
  • En Visual Basic, l'option de compilation Option Explicit permet d'éliminer 50% des erreurs.

4
Préparer la réflexion de l'ordinateur :
adaptation des fonctions déjà écrites.

Pour gérer l'Intelligence Artificielle, l'ordinateur va en fait simuler tous les coups possibles (dans certaines limites...) pour trouver le meilleur coup.

Il va donc utiliser certaines de nos fonctions (effectuer, partie finie), mais en agissant dans des damiers virtuels et non pas dans le damier affiché à l'écran.

On doit donc modifier ces 2 fonctions de façon à ce qu'elles reçoivent en paramètre le damier (type TJeu) dans lequel elles agissent. Par exemple, le paramétrage complet de la fonction Effectuer sera :

Function Effectuer(Damier As TJeu, Joueur As Integer, Coup As Integer, Affiche as Boolean) As Boolean

Votre travail est de :

4
Réflexion de l'ordinateur :
écriture de la procédure récursive.

  Principes.

C'est au jaune, l'ordinateur, de jouer
Il va simuler ses 7 coups possibles (en jaune foncé ici)
Pour son 1er coup possible (puis pour tous les autres), il va simuler toutes les réponses possibles de l'adversaire (en rouge foncé ici). Pas génialce premier coup, c'est perdu !

Le principe de réflexion de l'ordinateur est le suivant :

Pour chacun de mes 7 coups possibles
  Pour chacune des 7 réponses possible de l'adversaire
    Pour chacune de mes 7 réponses possibles
      ...
(autant de fois que le niveau maximum de réflexion)
        Evaluer le damier résultant de ces simulation, lui donner un score

Remarques :

  Algorithme à retranscrire.

La fonction MeilleurCoup doit au final revoyer un coup (celui que l'ordinateur va jouer), mais dans les appels récursifs c'est uniquement le score qui nous intéresse. Pour réaliser ces deux choses en même temps, la fonction va en fait renvoyer la structure suivante :

Type TCoup
  Score as Integer
  Coup as Integer
End Type

L'algorithme est le suivant :

Function MeilleurCoup(ByVal(1) Damier, Joueur, NiveauCourant) As TCoup
  Si le NiveauCourant = le NiveauMaximum alors
    MeilleurCoup.Score = Evaluation
(2)(Damier, Joueur)
  Sinon
    Pour chacun des 7 coups (si le coup est possible)
      Effectuer
(3) le coup dans le damier virtuel reçu en paramètre
      Si le coup est gagnant
(4) alors
        Score = Maximum si le niveau est pair, Minimum si le niveau est impair.
      Sinon
        Score = MeilleurCoup
(5)(Damier, Joueur, NiveauCourant + 1)
      Fin Si
    Fin Pour
    MeilleurCoup.Score = maximum des scores ci-dessus si le niveau est pair (minimum sinon)
    MeilleurCoup.Coup = le coup correspondant
  Fin Si
Fin Function

  Fonction d'évaluation du damier.

Le but de cette fonction est de dire si un damier est à l'avantage du joueur qui a lancé ces simulations, ou non. Il faut même chiffrer cet avantage pour affiner la qualité de la réflexion.

Pour le Puissance 4, je n'ai personellement pas trouvé de fonction d'évaluation du damier satisfaisante. Mon programme renvoie systématiquement 0 !!! Ce qui veut dire qu'au bout des simulations, si aucun joueur n'a virtuellement gagné, l'ordinateur n'en tire aucune information pertinente.

A vous d'essayer de chiffrer la valeur d'un damier et de renvoyer le score correpondant. L'IA y gagnera énormément en efficacité.


Expliquez à l'ordinateur que ce damier
est à l'avantage du rouge !

5
Pour aller plus loin et accélérer l'IA :
Application du principe de l'Alpha-Bêta.

L'ordinateur n'est pas très rapide à réfléchir, vous n'arrivez peut-être même pas à 7 niveaux de profondeur dans l'exploration récusive.

Il existe un algorithme efficace pour l'accélérer, sans du tout y perdre en réflexion, c'est l'algorithme de l'alpha-bêta. Cet algorithme sert uniquement à éviter d'explorer certaines branches de la récursivité.

Cliquez sur le shéma pour avoir un tentative d'explication de l'Alpha-Bêta (appliquée au jeu de l'Awalé). Comprendre c'est une chose, le programmer c'en est une autre...


Sébastien PASTORE.