Programmer un morpion en ada

Discutez d'informatique ici !
Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

Programmer un morpion en ada

par Rockleader » 10 Nov 2012, 10:52

Bonjour à tous, et d'avance merci de votre aide, aujourd'hui je suis un peu paumé.
A priori, programmer un morpion, c'est quelque chose d'assez simple, mais là le TP nous impose une façon de faire et j'avoue ne pas vraiment la comprendre....Pour ma part j'aurais plutôt essayer de faire ça en utilisant un tableau, ici je me perd dans tout ce que l'on fait car je ne vois pas comment l'ensemble va se construire ni comment la procédure principale devra marcher.

(JE m'excuse pour la longueur du message, j'aurais bien utiliser la fonction spoil pour cacher les lignes de code et raccourcir le pavé mais elle semble ne pas être disponible sur le forum...)



========================================================
Je ne sais pas si ça à un rapport direct mais la programmation du morpion, mais voilà ce que l'on bous a faire fait


Une procédure qui permet de tracer une valeur entière qui prend en argument une chaine de caractère donnant le nom de la variable et un entier donnant sa valeur

Code: Tout sélectionner
procedure TraceVarInt (val:In Integer;x:In string) is
    begin
      put("variable ");put(x);put("=");put(val);
      new_line;
end TraceVarInt;



Une procédure qui réalise la même chose mais qui met en pause tant que l'utilisateur n'appuies pas sur une valeur du clavier.

Code: Tout sélectionner
procedure TraceVarIntPause (val:In Integer;x:In string) is
    varPause:Integer;
    begin
      put("variable ");put(x);put("=");put(val);
      new_line;
      put("Pause: Entrez un entier pour reprendre");new_line;
      get(varPause); --stoppe le prgme tant qu'une valeur n'est pas entrée
end TraceVarIntPause;


Une procédure qui petmet de saisir une valeur au clavier qui prend en argument un message d'invitation à la saisie et une variable entière pour stocker la saisie. La procédure affiche le message et saisit la variable

Code: Tout sélectionner
procedure saisirInt (x:In string) is
    val:Integer;
    begin
      put(x);
      get(val);
end saisirInt;


Une procédure qui afficher une valeur entière précédée d'un message, elle prend en argument une chaine de caractère et la valeur à afficher

Code: Tout sélectionner
procedure putStringInt(x:In string;val:Integer) is
    begin
      put(x);put(" vaut ");put(val);
end putStringInt;


======================================================


Ensuite commence la véritable partie du morpion

======================================================

La première partie consiste en l'affichage de la grille.

Je dois écrire une procédure qui affiche le bord supérieur de la grille et de même pour le bord inférieur.
Code: Tout sélectionner
procedure afficherBordSuperieur is
    begin
      put(" ^^^^^^^");new_line;
  end afficherBordSuperieur;

  procedure afficherBordInferieur is
    begin
      put(" vvvvvvv");new_line;
  end afficherBordInferieur;




On considère que le contenu d’une case de la grille est représenté par une valeur
entière : 0 si la case est vide, 1 si la case est occupée par un pion du joueur 1 et 2 si la case est
occupée par un pion du joueur 2. Selon le pion occupant une case, on fait le choix d’afficher à
l’écran une croix (‘X’) pour le joueur 1 et un rond (‘O’) pour le joueur 2.
Écrivez une procédure afficherLigne qui prend en argument trois entiers pour représenter le
contenu des cases de la ligne de la gauche vers la droite et affiche cette ligne à l’écran.

Code: Tout sélectionner
procedure afficherLigne (x,y,z:Integer) is
    begin
    if(x=0) then   
      put("");
    elsif(z = 1) then
      put("X >");
    else
      put("0 >");
    end if;
    new_line;
  end afficherLigne; 


Une procédure qui va afficher la séparation entre les lignes de cases

Code: Tout sélectionner
 procedure afficherSeparationLigne is
    begin
      put("");
      new_line;
  end afficherSeparationLigne;


Pour l’affichage de la grille, on va considérer maintenant que le
contenu des 9 cases de la grille est représenté par un entier de 9 chiffres, dont
chaque chiffre peut être 0 (case vide), 1 (case occupée par le joueur 1) ou 2 (case
occupée par le joueur 2). Ainsi, la grille affichée ci-contre est représentée par
l’entier 001210201 (mais cela ne sert à rien de chercher la correspondance !).
Ecrivez la procédure afficherGrille qui prend en argument une grille sous la forme
d’un entier. Pour ceci, vous utiliserez la procédure fournie extraireLigne (grille,
numLigne : in Integer; case1, case2, case3 : out Integer) qui retourne les valeurs
des 3 cases de la ligne numLigne de gauche à droite, sachant que la ligne du bas
porte le numéro 1, la ligne du milieu le numéro 2 et la ligne du haut le numéro 3.
^^^^^





vvvvv




C'est donc à ce niveau là que je bloque, je n'arrive pas à mettre en relation tout ce que l'on à fait et je ne vois pas comment obtenir le programme final du morpion.


Je vous met la suite du TP, ainsi que les fonctions que l'on nous a donné en annexes, je crois que c’est surtout le fait que je ne comprenne pas comment marchent ces fonctions qui me perturvent le plus.


Ecrivez donc une procédure enregistrerCaseChoisie qui prend en argument une
grille (un entier) à mettre à jour et un numéro de joueur numJoueur (un autre entier).
Le comportement de la procédure consiste à demander au joueur numJoueur de choisir la case
dans laquelle il veut mettre sa marque, à vérifier que cette case est vide (sinon il faut lui demander
de choisir une nouvelle case) puis à ajouter la marque dans la grille.
Pour cela, on considère que chaque case est repérée par les chiffres 1 à 9 du pavé numérique du
clavier (7 étant la case supérieure gauche et 3 la case inférieure droite). Vous utiliserez les procédures fournies caseDejaOccupee(grille, lig, col : Integer) qui dit si la case de la ligne numéro
lig et de la colonne numéro col est déjà occupée ou pas et ajouterMarque(grille : in out Integer;
marque, lig, col : in Integer) qui met à jour la grille pour la case de coordonnées (lig, col) au moyen
de la marque 1 pour le joueur 1 et de la marque 2 pour le joueur 2. Attention, il vous faudra convertir
le numéro de touche du pavé numérique (entre 1 et 9) en un couple de coordonnées (lig, col)
sachant que la ligne 1 est celle des touches 1 à 3 et que la première colonne est celle des touches
1, 4, 7.




Ecrivez le programme principal qui affiche initialement une grille vide puis, tant que
la partie n’est pas terminée, fait jouer alternativement chacun des 2 joueurs et affiche la grille
actualisée. Le programme affiche également le résultat de la partie quand le jeu est terminé. Vous
utiliserez ici la fonction grilleVide qui retourne un entier correspondant à une grille vide et la fonction
ilYAUnGagnant(grille : Integer) qui retourne 1 ou 2 selon que le joueur 1 ou le joueur 2 a gagné, ou
0 sinon.






ET voilà toutes les fonctions annexes que je pourrais avoir besoin d'utiliser.

Code: Tout sélectionner
function grilleVide return Integer is
      -- retourne une grille vide
   begin
      return 0;
   end grilleVide;

   procedure extraireLigne(grille, numLigne : in Integer;
                           case1, case2, case3 : out Integer) is
      -- retourne les valeurs des 3 cases de la ligne extraite
      i : Integer := numLigne; -- indice de boucle sur les lignes
      tempo : Integer := grille;
      ligne : Integer; -- entier de 3 chiffres correspondant à une ligne
   begin
      while (i > 1) loop
         tempo := tempo / 1000;
         i := i - 1;
      end loop;
      ligne := tempo mod 1000;
      case1 := ligne mod 10;
      ligne := ligne / 10;
      case2 := ligne mod 10;
      ligne := ligne / 10;
      case3 := ligne;
   end extraireLigne;

   procedure extraireColonne(grille, numCol : in Integer;
                             case1, case2, case3 : out Integer) is
      -- retourne les valeurs des 3 cases de la colonne extraite
      i : Integer; -- indice de boucle sur les colonnes
      tempo : Integer := grille;
      ligne : Integer; -- entier de 3 chiffres correspondant à une ligne
   begin
      ligne := tempo mod 1000;
      i := numCol;
      while (i > 1) loop
         ligne := ligne / 10;
         i := i - 1;
      end loop;
      case3 := ligne mod 10;
      tempo := tempo / 1000;
      ligne := tempo mod 1000;
      i := numCol;
      while (i > 1) loop
         ligne := ligne / 10;
         i := i - 1;
      end loop;
      case2 := ligne mod 10;
      ligne := tempo / 1000;
      i := numCol;
      while (i > 1) loop
         ligne := ligne / 10;
         i := i - 1;
      end loop;
      case1 := ligne mod 10;
   end extraireColonne;

   procedure extraireDiagonale(grille, numDiag : in Integer;
                               case1, case2, case3 : out Integer) is
      -- retourne les valeurs des 3 cases de la diagonale extraite
      -- numDiag doit être 1 ou -1
      i : Integer; -- indice de boucle sur les colonnes
      tempo : Integer := grille;
      ligne : Integer; -- entier de 3 chiffres correspondant à une ligne
   begin
      ligne := tempo mod 1000;
      if numDiag = 1
      then i := 1;
      else i := 3;
      end if;
      while (i > 1) loop
         ligne := ligne / 10;
         i := i - 1;
      end loop;
      case3 := ligne mod 10;
      tempo := tempo / 1000;
      ligne := tempo mod 1000;
      i := 2;
      while (i > 1) loop
         ligne := ligne / 10;
         i := i - 1;
      end loop;
      case2 := ligne mod 10;
      ligne := tempo / 1000;
      if numDiag = 1
      then i := 3;
      else i := 1;
      end if;
      while (i > 1) loop
         ligne := ligne / 10;
         i := i - 1;
      end loop;
      case1 := ligne mod 10;
   end extraireDiagonale;

   procedure ajouterMarque(grille : in out Integer; marque, lig, col : in Integer) is
      -- ajouter dans la grille le symbole associé au joueur 1
      -- dans la case de coordonnées (lig, col).
      valMAJ : Integer;
   begin
      putStringInt("Le joueur ", marque);
      put(" a joué en ");
      putStringInt("(",lig);
      putStringInt(",",col);
      put(").");
      new_line;
      valMAJ := marque * (1000 ** (lig - 1)) * (10 ** (col - 1));
      grille := grille + valMAJ;
   end ajouterMarque;

   function caseDejaOccupee(grille, lig, col : Integer) return boolean is
      estOccupee : Boolean;
   begin
--      traceVarIntPause("modulo",(3 * (lig -1) + (col - 1)));
      estOccupee := (grille / (10 ** (3 * (lig -1) + (col - 1)))) mod 10 /= 0;
--      traceVarBool("estOccupee", estOccupee);
      return estOccupee;
   end CaseDejaOccupee;

   function ilYAUnGagnant(grille : Integer) return Integer is
      -- il y a un gagnant si toutes les cases d'une ligne sont égales
      -- ou si toutes les cases d'une colonne sont egales ou
      -- si toutes les diagonales d'une case sont egales.
      indice : Integer; -- indice de parcours des lignes, colonnes ou diag
      gagne : Boolean := false;
      rep, case1, case2, case3 : Integer;
   begin
      -- inspecter les lignes
      indice := 1;
      while not gagne and (indice < 3) loop
         extraireLigne(grille, indice, case1, case2, case3);
         gagne := (case1 = case2) and (case2 = case3) and (case1 /= 0);
         rep := case1;
         indice := indice + 1;
      end loop;
--      traceVarBool("gagne lignes", gagne);
--      putStringInt("rep",rep);
      -- inspecter les colonnes
      indice := 1;
      while not gagne and (indice < 3) loop
         extraireColonne(grille, indice, case1, case2, case3);
         gagne := (case1 = case2) and (case2 = case3) and (case1 /= 0);
         rep := case1;
         indice := indice + 1;
      end loop;
--      traceVarBool("gagne colonnes", gagne);
--      putStringInt("rep",rep);
       -- inspecter les diagonales
      indice := -1;
      while not gagne and (indice < 2) loop
         extraireDiagonale(grille, indice, case1, case2, case3);
         gagne := (case1 = case2) and (case2 = case3)  and (case1 /= 0);
         rep := case1;
         indice := indice + 2;
      end loop;
--      traceVarBool("gagne diag", gagne);
--      putStringInt("rep",rep);
      -- donner le résultat
      if gagne
      then return rep;
      else return 0;
      end if;
   end ilYAUnGagnant;



Merci à tous pour votre aide.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !



C.Ret
Membre Relatif
Messages: 497
Enregistré le: 02 Juil 2012, 13:33

par C.Ret » 10 Nov 2012, 11:09

Bonjour,

Etant donné le nombre de procédures et fonctions donné comme pré-requi pour cet excercice, il est clair que le sujet est de présenter la partie principale la plus adaptée qui les utilise toutes.

L'excercice consiste donc à bien analyser chacune de ces procédures, de bien comprendre ce qu'elle fait, quel sont ses arguments et quels est/sont son/ses résultat(s).

De dresser une sorte de cartographie qui montre comment elles peuvent s'emboiter ou se compléter: certaines concernent l'affichage, d'autre les entrés/sorties (l'interface homme-machine), d'autres des traitements qui peuvent servir aux diffèrentes étapes du jeu.

Une fois cette première analyse réalisée, il faut s'interresser à ce que doit faire le programme principal. C'est assez simple en fait, c'est juste une boucle.

Il faut donc, sur le papier bien structurer ce programme en décortiquant pas à pas les étapes du jeu.
Ensuite, très naturellement, on va utiliser les procèdures données en pré-requi pour réaliser chacune des étapes du programme principal.

C'est pour cela qu'il faut bien comprendre quels sont et à quoi servent les arguments de chacune des procèdure. Ces arguments seront les variables que manipule le programme principal.

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 10 Nov 2012, 11:28

Oui ça je sais, mais le problème, c'ets que je ne sais pas si j'ai correctement programmé ces sous procédures justement du fait que je ne comprends pas vraiment le lien qu'elles vont avoir entre elles.

ET surtout, ce n'est pas fini, sur la fin je coince encore avant la mise en place du programme principal qui lui est je l'accorde relativement simple à la place, ça sera une boucle qui continuera tant que la partie n'est pas fini à demander au jouer 1 et 2 de remplir une case.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

C.Ret
Membre Relatif
Messages: 497
Enregistré le: 02 Juil 2012, 13:33

par C.Ret » 10 Nov 2012, 12:56

Ah! J'avais pas compris que toutes ces procèdures été de ton cru.

EN principe, on fait dans l'autre sens; on structure le programme, on le découpe en sous partie qui feront l'objet de sous-procèdures.

Mais, on ne découpe pas au hasard; il faut une cohérence et surtout un diagramme qui indique ce qui est transmit à chaque sous partie et sous quelle forme.

Donc, que peut-on faire pur d'aider ?

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 10 Nov 2012, 13:00

EN principe, on fait dans l'autre sens; on structure le programme, on le découpe en sous partie qui feront l'objet de sous-procèdures



Exactement, du coup c'est bien ça mon problème, tu me dis fais un morpion, à ma façon je le ferais, mais là on m'oblige à utiliser certaines méthode en employant des procédures que l'on me fait faire au préalable.




(Les seules procédures qui ne sont pas de moi sont celles que j'ai affichée en dernier, ce sont des procédures que je suis censé reprendre selon les consignes).


Hum, comment m'aider, je dirais que ce qui me bloque c'est que je comprends pas le schéma, je ne comprends pas la manière dont ses procédures sont censés s'agencer pour former le programme final...
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 10 Nov 2012, 13:06

Si tu ne vois aucun intérêt à utiliser ces procédures, je te conseille de coder toi même le morpion.

Et de voir après coup comment tu aurais pu utiliser les préocédures fournies.
la vie est une fête :)

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 10 Nov 2012, 14:10

fatal_error a écrit:Si tu ne vois aucun intérêt à utiliser ces procédures, je te conseille de coder toi même le morpion.

Et de voir après coup comment tu aurais pu utiliser les préocédures fournies.


Effectivement, j'y ai pensé un moment, mais je crois que ça ne plairait pas à mon enseignant =)

Si je peux faire une comparaison c'est comme si je te disais de résourdre un système par combinaison et qu'à la place tu le résolvais par substitution, le résultat final est le même (quoi qu'il y ait au niveau de la machine un coût différent pour le calcul), mais la méthode employée ne sera pas celle qui aura été demandé, donc au final le travail rendu ne sera pas ce qui était attendu par le prof....


Je préfère rester bloqué en essayant de faire à la façon dont on est guidé pour le TP. Quitte après à en faire un pour le plaisir à ma façon plus tard, mais je crois que si le prof veut nou faire faire comme ça c'est bien qu'il y a une raison, un type de raisonnement à acquérir à travers cet exercice.

Malgré tout j'ai quand même du mal à utiliser des procédures qui n'ont pas été écrites par moi même...
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

C.Ret
Membre Relatif
Messages: 497
Enregistré le: 02 Juil 2012, 13:33

par C.Ret » 10 Nov 2012, 14:30

Sans compter qu'apprendre à programmer sous ce type de contrainte (des procédure et structure de données imposées) c'est quelque part le quotidien des programmateur et developper professionels.

Car souvent quand on participe à un projet de développement informatique, on hérite de la façon de faire déjà en place et l'on doit faire ses preuves de cette façon avant de pouvoir imposer son style personnel.


Ce qui me gène pour pouvoir aider c'est que je ne vois pas ce qui est imposé et ce qui libre ou issu de ta production.

En fait, ce qu'il faudrait c'est définir et exprimer le besoin.

Coder le morpion à partir des 9 chiffre d'un entier est certainement justifier par une raison ou une autre (par exemple inclure ce programme dans un système d'IA ultérieur ou pour pouvpir par la suite faire une approche "mathématique" ou "statistique" du jeu !

Enfin quelque soit la raison, si le chaier des charges dit "coder la grille de jeu sur des entiers décimaux de neufs chiffres, c'est ok.

Ce qui manque quelque par c'est la correspondance; sans cela, nous ne pouvons pas vérifier si ta procédure traite ou crée convenablement les nombres entier pour en extraire ligne, colone , diagonale ou anti-diagonale...

Ensuite la boucle du programme principale peut avoir diffèrents aspects selon que se soit toujours (ou non) le 1er joueur qui commence, etc...


Il y a aussi le niveau de modularité demandé.

Il est clair que la procèdure (très courte) TraceVarInt est entièremetn contenue dans la procèdure TraceVarIntPause. De plus, si pour contunier après la pause de cette dernière il faut saisir un chiffre, pourquoi ne peut-elle pas être aussi construite à l'aide de la procèdure saisirInt

Au fait, pourquoi le nom de cette dernière procèdure ne commence-t-il pas par une majuscule comme semble le faire toutes les autres ?


C'est peut-être cela le but de cet excercice, apprendre à quitter ses petites manies de programmeur individuel pour apprendre à structurer, programmer sous contriantes et collectivement.

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 10 Nov 2012, 14:56

Je vous aurez bien mis le pdf tel quel pour que vous voyez l'énoncé, mais je peux pas insérer de pièces jointe...


Je vais me contenter d'un grossier copier coller. (Désolé pour la présentation grossière que ça va faire...) les premières procédures demandés, je les ai écrites moi mêmes ( je les ai donné dans mon premier message)
A la vue de ceci pensez vous que j'ai bien interpréter ce qui était demandé dans ces sous procédures de départ ?
Dans un second temps, si mes sous procédures codées sont bel et bien correcte, comment continuer à partir de la question 1.4 ?


Code: Tout sélectionner
L’objectif de ce TP est d’abord de développer quelques procédures qui nous seront utiles dans le
développement de programmes à venir (et qui auraient sans doute été utiles aussi dans les
développements passés !). Ces procédures concernent la trace et la mise au point de programmes
(Exercice 1), la saisie de valeurs et l’affichage de valeurs (Exercice2).
L’objectif de la deuxième partie est de développer un jeu de morpion. Pour la conception de ce jeu
et son algorithmique, les différentes questions du sujet vous accompagneront jusqu’à la solution
finale. Pour vous faciliter la tâche vis-à-vis de certaines parties, des fonctions et des procédures
annexes vous sont fournies dans un fichier auxiliaire.
Tous les fichiers sources nécessaires à la programmation de cet exemple se trouvent sur Moodle.

Exercice 1 - Trace

Question 1.1 : Ecrire et tester une procédure traceVarInt qui permet de tracer une valeur entière.
Elle prend en argument une chaîne de caractères donnant le nom de la variable et un entier pour sa
valeur. Le comportement de la procédure consiste à afficher la valeur précédée de son nom.
variable x = 4  variable cpt = 1

Question 1.2 : Ecrire et tester une procédure traceVarIntPause qui réalise le même comportement
que  traceVarInt à la différence que la procédure interrompt l’exécution du programme en
demandant à l’utilisateur d’appuyer sur une touche après affichage de la variable. L’interruption est
obtenue par une lecture de caractère (dont la valeur n’est pas utilisée).

Exercice 2 – Saisie et Affichage

Question 2.1 : Ecrire une procédure saisirInt qui permet de saisir au clavier une valeur entière. Elle
prend en argument une chaîne de caractères contenant le message d’invite pour la saisie et une
variable entière pour stocker la valeur saisie. Le comportement de la procédure consiste à afficher
le message et à saisir la variable.

Question  2.2 : Ecrire une procédure  putStringInt qui affiche une valeur entière précédée d’un
message. Elle prend en argument une chaîne de caractères contenant le message et la valeur
entière à afficher.

Le jeu du Morpion

L’implantation que nous vous proposons se décompose en 2 parties : d’une part, des sousprogrammes pour gérer l’affichage  et,  d’autre part, la gestion de la grille  3x3  et des coups des
joueurs. Toute l’implantation décrite dans ce sujet est une proposition ; vous pouvez implanter le jeu
d’une autre façon si cela est justifié.

Partie 1 – Affichage de la grille

On vous propose de représenter la grille par les lignes de caractères ci-contre (on
ne critique pas l’esthétique ;-)). Pour afficher la grille, nous allons la décomposer
en un bord supérieur, un bord inférieur, 3 lignes de cases séparées par 2 lignes de
séparateurs.

Question 1.1 : Ecrivez une procédure afficherBordSuperieur qui permet de tracer
le bord supérieur de la grille du morpion.
Sur le même principe, on peut écrire une procédure afficherBordInférieur.

Question 1.2 : On considère que le contenu d’une case de la grille est représenté par une valeur
entière : 0 si la case est vide, 1 si la case est occupée par un pion du joueur 1 et 2 si la case est
occupée par un pion du joueur 2. Selon le pion occupant une case, on fait le choix d’afficher à
l’écran une croix (‘X’) pour le joueur 1 et un rond (‘O’) pour le joueur 2.
Écrivez une procédure  afficherLigne qui prend en argument trois entiers pour représenter le
contenu des cases de la ligne de la gauche vers la droite et affiche cette ligne à l’écran.

Question 1.3 : Ecrivez  une procédure afficherSeparationLigne  qui affiche  la ligne de séparation
entre 2 lignes de cases.

Question 1.4 : Pour l’affichage  de la grille, on va considérer maintenant que le
contenu des 9 cases de la grille  est représenté par un entier de 9 chiffres, dont
chaque chiffre peut être 0 (case vide), 1 (case occupée par le joueur 1) ou 2 (case
occupée par le joueur 2). Ainsi,  la grille affichée ci-contre est représentée par
l’entier 001210201 (mais cela ne sert à rien de chercher la correspondance !).

Ecrivez la procédure afficherGrille qui prend en argument une grille sous la forme
d’un entier. Pour  ceci, vous utiliserez la procédure fournie  extraireLigne (grille,
numLigne : in Integer; case1, case2, case3 : out Integer) qui retourne les valeurs
des 3 cases de la ligne numLigne de gauche à droite, sachant que la ligne du bas
porte le numéro 1, la ligne du milieu le numéro 2 et la ligne du haut le numéro 3.

Partie 2 – Organisation de la partie

Au cours d’une partie, chaque joueur joue à tour de rôle, il nous faut donc écrire une procédure qui
nous permettra de recueillir le choix des 2 joueurs alternativement, vérifier que ce choix est possible
et mettre à jour la grille en conséquence.

Question  2.1 : Ecrivez  donc  une procédure  enregistrerCaseChoisie qui  prend en argument une
grille (un entier) à mettre à jour et un numéro de joueur numJoueur (un autre entier).
Le comportement de la procédure consiste à demander au joueur numJoueur de choisir la case
dans laquelle il veut mettre sa marque, à vérifier que cette case est vide (sinon il faut lui demander
de choisir une nouvelle case) puis à ajouter la marque dans la grille.

Pour cela, on considère que chaque case est repérée par les chiffres 1 à 9 du pavé numérique du
clavier (7 étant la case supérieure gauche et 3 la case inférieure droite). Vous utiliserez les
^^^^^





vvvvv

^^^^^





vvvvv

procédures fournies caseDejaOccupee(grille, lig, col : Integer) qui dit si la case de la ligne numéro
lig et de la colonne numéro col est déjà occupée ou pas et  ajouterMarque(grille : in out Integer;
marque, lig, col : in Integer) qui met à jour la grille pour la case de coordonnées (lig, col) au moyen
de la marque 1 pour le joueur 1 et de la marque 2 pour le joueur 2. Attention, il vous faudra convertir
le numéro de touche du pavé numérique (entre 1 et 9) en un couple de coordonnées (lig, col)
sachant que la ligne 1 est celle des touches 1 à 3 et que la première colonne est celle des touches
1, 4, 7.

Question 2.2 : Ecrivez le programme principal qui affiche initialement une grille vide puis, tant que
la partie n’est pas terminée, fait jouer alternativement chacun des 2 joueurs et affiche la grille
actualisée. Le programme affiche également le résultat de la partie quand le jeu est terminé. Vous
utiliserez ici la fonction grilleVide qui retourne un entier correspondant à une grille vide et la fonction
ilYAUnGagnant(grille : Integer) qui retourne 1 ou 2 selon que le joueur 1 ou le joueur 2 a gagné, ou
0 sinon.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 10 Nov 2012, 15:09

Effectivement, j'y ai pensé un moment, mais je crois que ça ne plairait pas à mon enseignant =)

je t'ai pas dit de rendre ton programme codé par toi même.

Je t'ai dit de coder toi m;)mé et de comparer après comment tu aurais pu utiliser les procédures fournies.

Parce qu'à coup sûr si tu codes par toi même tu vas te rendre compte que tu réécris ce qui a déjà été fait.
la vie est une fête :)

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 10 Nov 2012, 15:12

Je pense pas nan, moi déjà, je pense que ça aurait été plus simple de présenter ça sous la forme d'un tableau de 9 variables correspondant au cases qui aurait été mis à jour petit à petit.

Et si j'essaye de faire le rapprochement entre ça et les fonction qu'on nous donne, alors oui ça pourrait ressembler, mais après dans la façon de le coder c'est une toute autre histoire je crois.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 10 Nov 2012, 15:18

Le conditionnel c'est mal.
la vie est une fête :)

C.Ret
Membre Relatif
Messages: 497
Enregistré le: 02 Juil 2012, 13:33

par C.Ret » 10 Nov 2012, 16:24

Exercice 1 - Trace

Question 1.1 : Ecrire et tester une procédure traceVarInt qui permet de tracer une valeur entière.

Code: Tout sélectionner
procedure traceVarInt ( val :In Integer; x :In string) is
  begin
    putStringInt("Variable " & x & "=",val);
  end TraceVarInt;


D'après l'exemple donné, le retour à la ligne est inutile. Sinon c'est conforme

Question 1.2 : Ecrire et tester une procédure qui permet de tracer une valeur entièrepuis d’appuyer sur une touche .

Code: Tout sélectionner
procedure traceVarIntPause ( val :In Integer ; x :In string) is
    Char : Character;
    Done : Boolean := False;
    begin
      TraceVerInt(val,x);
      put("#");
      while not(Done) loop
          Get_Immediate (Char, Done);
      end loop


Comme exemple donné, sans retour à la ligne.
La dièse c'est une astuce personnelle qui me rapèle qu'il faut appuyer sur une touche pour continuer. On peut mettre un texte comme tu as fait, mais très vite à l'utilisation cela rempli l'écran et on loupe ce que l'on devez y voir.


Exercice 2 – Saisie et Affichage

Question 2.1 : Ecrire une procédure saisirInt qui permet de saisir au clavier une valeur entière.

Code: Tout sélectionner
procedure saisirInt ( x :In String, val :Out Integer) is
    rep : Float := 0.1;
    begin
      loop
         put(x);put(" ?  ");
         get(rep);
         val=Integer(rep);
         exit when float(var)=rep ;
         put("Merci de saisir une valeur entière.");
         newline;
      end loop
end saisirInt;


L'énoncé ne précise pas ce qu'il faut faire si l'on entre autre-chose qu'un entier.
J'ai donc fait à ma façon un petit test de contrôle.

Par contre, que devient var une fois que l'utilisateur l'a sasie ? NE doit-elle pas être transmise au programme appelant la procèdure ?
Cela ne rappèle pas l'utilisation de In et Out ?

Ou alors on écrit unefonction:
Code: Tout sélectionner
function saisirInt ( x :In String) is
    rep : Float := 0.1;
    val : Integer;
    begin
      loop
         put(x);put(" ?  ");
         get(rep);
         val=Integer(rep);
         exit when float(var)=rep ;
         put("Merci de saisir une valeur entière.");
         newline;
      end loop
      return val;
end saisirInt;




Question 2.2 : Ecrire une procédure putStringInt qui affiche une valeur entière précédée d’un message.

Code: Tout sélectionner
procedure putStringInt(x:In string;val:Integer) is
    begin
      put(x);put(val);
end putStringInt;


J'ai retiré la chaine " vaut ", car cette procèdure doit certainemetn rester très "neutre" et permettre par exemple d'a fficher :
"Le score du joueur A est 1"


Le jeu du Morpion

Partie 1 – Affichage de la grille


Question 1.1 : Ecrivez une procédure afficherBordSuperieur qui permet de tracer
le bord supérieur de la grille du morpion.
Sur le même principe, on peut écrire une procédure afficherBordInférieur.

Code: Tout sélectionner
procedure afficherBordSuperieur is
    begin
      put(" ^^^^^^^");new_line;
end afficherBordSuperieur;

procedure afficherBordInferieur is
    begin
      put(" vvvvvvv");new_line;
end afficherBordInferieur;


RAS.

Question 1.2 : Écrivez une procédure afficherLigne qui prend en argument trois entiers pour représenter le contenu des cases de la ligne de la gauche vers la droite et affiche cette ligne à l’écran.

Code: Tout sélectionner
procedure afficherLigne (case_g,case_c,case_d:Integer) is

   procedure afficherSymbCase( code:Integer) is
       begin
        case code is
           when 0 => put(" ");
           when 1 => put("X");
           when 2 => put("O");
        end case;

   procedure afficherSepaCase is
       begin
           put ("|");
    end afficherSepaCase;
   
    end afficherSymboleCase

    begin
    put("");
    new_line;
end afficherLigne; 


C'est pas plus facile de structurer et d'éviter les répétitions ?
Cela donne surtout un code plus lisible et plus propre.
J'ai fait comme Fatal-Error le suggère: utiliser des variable lisible qui rapèlent ce à quoi elle servent.

Question 1.3 : Ecrivez une procédure afficherSeparationLigne qui affiche la ligne de séparation entre 2 lignes de cases.

Code: Tout sélectionner
procedure afficherSeparationLigne is
    begin
      put("");
      new_line;
  end afficherSeparationLigne;

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 10 Nov 2012, 18:16

Je viens que de faire tilt, les procédures que j'ai fabriqués dans la premières partie sont utilisées par les fonction et procédures que l'on a pré donné...du coup je comprends un peu mieux ce que font ces procédures.


J'ai commencé par afficher la grille vide au début.

j'indique que le jouer 1 commence à jouer. Je lui demande dans quelle ligne et clone il veut jouer. Grace à la fonction que l'on nous donne la valeur de la grille est ainsi mise à jour et en l'imprimant j'ai la bonne place

(malgré le fait un peu gênant que la ligne 1 soit celle du bas, mais bon admettons que j'aie l'esprit mal tourné =))


Donc maintenant il ne me reste qu'à faire boucler en incluant le joueur 2 et un test permettant de savoir si on ne rejoue pas sur une grille déjà existante.


Je vois un peu mieux comment ça tourne, je vous recontacte si jamais je ne trouve pas la solution avant demain !








Une question par contre, je n'utilise que trois fichiers de sources, entrree_sorties; procedures_utiles et annexe_morpion.

(annexe_morpion étant tout simplement le package dans lequel je range toutes les fonctions faites dans la partie 1 pour ne pas surcharger les déclaration du code du morpion) Et procedures utiles étant la liste de procédures données plus haut (extraireLigne etc etc)






Lorsque je compile après un changement, le temps de compilation avoisine les 2 minutes ! Alors, je suis bien patient, mais je trouve quand même ça énorme pour exécuter des opération pour une machine, d'autant plus que j'ai eu avant les vacances un tp de math info sur lequel j'ai pu comparer le temps d'exécution des calculs réalisées par diverses méthodes, et même les très gros calculs pouvait se faire bien plus rapidement en moins de trois secondes.
Je veux bien croire qu'ici le nombre de variables soit plus important, mais quand même....
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

C.Ret
Membre Relatif
Messages: 497
Enregistré le: 02 Juil 2012, 13:33

par C.Ret » 10 Nov 2012, 19:49

Désolé pour la compilation, mais cela fait longtemps que je n'ai plus utiliser ADA sur PC.

Les délais me paraissent long, peut-être est-ce dû au fait que les ressources sont partagées sur un serveur ? En fait, c'est la limite lecture/ecriture autorisée par "client" qui peut dans certains cas (comme ceux d'un serveur partagé par plusieurs centaines d'étudiant) expliqué le peu de performance.
Alors, que la salle de TP est peut-être mieux équipée (ou non bridée).

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 10 Nov 2012, 22:37

Bah non pas du tout parce que les fichiers sources je les ai téléchargés ils sont donc sur mon pc, je ne vais pas les chercher sur le net à chaque fois que je compile.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

C.Ret
Membre Relatif
Messages: 497
Enregistré le: 02 Juil 2012, 13:33

par C.Ret » 10 Nov 2012, 22:40

Voilà qui met à mal mon hypothèse; il s'agit donc bien d'un environnement de développement stand-alone sans utilisation d'un serveur.

quand j'étais étudiant, nous n'avions pas de PC individuel, nous programmion sur des stations de travail relié à un serveur (pour la compilation) et un main-frame (pour exécuter nos programmes). Alors il y avait des délais, surtout les soirs (et le nuits) quand nous étions quelques centaines à soumettre nos codes au(x) serveur(s).

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 11 Nov 2012, 00:22

Oui, là on peut comprendre facilement que le temps d'attente soit long si le serveur est saturé. Mais là tout est en local sur le disque donc il n'y a aucune raison pour que ça se passe ainsi.


Enfin bon, deux minutes ça reste encre acceptable, je devrais pas trop m'énerver contre la machine :)



Si toutefois quelqun aurait une explication à cela =)
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 19:42

par Rockleader » 11 Nov 2012, 11:19

Bon, j'ai avancé, le programme boucle correctement, le joueur 1 commence à jouer, suivi du deux.
Si un joueur rejoue une case joué, le programme lui demande de rejouer.
ET ce tant qu'il n'y a pas un gagnant.



Mon soucis vient de ma boucle, si un joueur gagne tout va bien^^mais si personne gagne ce qui est souvent le cas au morpion, il me faut une fonction qui soit capable de me dire combien de case il reste de libre afin de pouvoir stopper la boucle lorsqu'il n'y a plus de case libre.


Je pensais utiliser un simple compteur qui s'arrêterait de boucler à 9, mais ça parait un peu primaire comme solution nan ?
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Modérateur
Messages: 6610
Enregistré le: 22 Nov 2007, 13:00

par fatal_error » 11 Nov 2012, 12:13

il me faut une fonction qui soit capable de me dire combien de case il reste de libre

non.
Il te faut une fonction capable de te dire si il reste une case de libre (ce qui est différent).

Pour tester si il reste une case de libre, généralement, tu regardes ta grille et tu regardes s'il y a une case libre.

Pour l’affichage de la grille, on va considérer maintenant que le
contenu des 9 cases de la grille est représenté par un entier de 9 chiffres, dont
chaque chiffre peut être 0 (case vide), 1 (case occupée par le joueur 1) ou 2 (case
occupée par le joueur 2)

tu peux boucler sur ta grille en faisant un extraireLigne, et regarder si chaque case est jouée.

Ou tu peux directement opérer sur l'entier à coup de modulo...ou ajouter un compteur.

L'idéal, c'est de réutiliser les primitives qui te sont fournies. à savoir tu fais ta fonction
Code: Tout sélectionner
isGridTotallyPlayed :
pour toutes les lignes
  extraireLigne(case1,case2,case3)
  if(case1==vide ou case2==vide ou case3==vide) return false;
  return true
finpour
fin isGridTotallyPlayed

c'est mieux parce que : en stockant le nombre de coup joués tu es redondant dans l'information. Si tu modifies la grille il faut modifier le compteur. (donc si tu stockes pas de compteur c'est mieux de ce point de vue là).
Gérer directement l'entier à coup de modulo, c'est contraire à l'esprit du TP qui te fournit les primitives pour ne pas avoir à t'occuper de l'encodage de l'entier.
la vie est une fête :)

 

Retourner vers ϟ Informatique

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 10 invités

Tu pars déja ?



Fais toi aider gratuitement sur Maths-forum !

Créé un compte en 1 minute et pose ta question dans le forum ;-)
Inscription gratuite

Identification

Pas encore inscrit ?

Ou identifiez-vous :

Inscription gratuite