Constraint error..mais où...

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

constraint error..mais où...

par Rockleader » 08 Avr 2013, 22:34

J'ai fais plusieurs sous programmes, environ 400 lignes qui commencent à être volumineux donc. Tous testé un par un et qui marchait bien. Jusqu'à cette après-midi la partie marchait comme il fallait. Mais là, j'ai une erreur d'intervalle à priori sur des test de booleen, mais je ne vois pas pourquoi.





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

Voici la déclaration de toutes les constantes et sous types utilisé.

B_INF_LIGNE:constant integer:=1;
B_SUP_LIGNE:constant integer:=7;
B_INF_COLONNE:constant integer:=1;
B_SUP_COLONNE:constant integer:=7;
NB_TOUR_MAX:constant integer := 100;
NB_MAX_SAUT:constant integer :=10;

subtype IntervalleTour is integer range 1..NB_TOUR_MAX;
subtype IntervalleLigne is integer range B_INF_LIGNE..B_SUP_LIGNE;
subtype IntervalleColonne is integer range B_INF_COLONNE..B_SUP_COLONNE;

Type Plateau is array (IntervalleLigne,IntervalleColonne) of character; -- convention LiCo

Type Cases is record
l:IntervalleLigne; -- une case est donc représenté par deux chiffres
c:IntervalleColonne;
end record;







Je ne vais pas tout mettre; mais seulement les sous programmes principaux.
Je commence ainsi:
Code: Tout sélectionner
procedure jouerUnPvP is
      j1,j2:character;
      nbTour:IntervalleTour:=1;
      p:Plateau;
      fini:Boolean:=FALSE; --initialisé à FAUX pour boucler au début
   begin
      AffecterAvatarJoueur(j1,j2);
      initPlateau(p);
      AfficherPlateau(p);
      While (fini=FALSE) loop
         jouerUnTour(p,nbTour,j1,j2);
      FinDePartie(p,j1,j2,nbTour,fini);
      end loop;
   end jouerUnPVP;


Sachant que :

Code: Tout sélectionner
procedure AffecterAvatarJoueur(pJ1,pJ2:out character) is
      carac:character;
      test:Boolean:=FALSE;
   begin
      While (test=FALSE) loop
         put("Le joueur 1 choisit son pion (X/O):");
         get(carac);
        test:=AvatarJoueurEstValide(carac);
      end loop;
      if (carac='X') then
         pJ2:='O';
      else
         pJ2:='X';
      end if;
      pJ1:=carac;
   end AffecterAvatarJoueur;


procedure initPlateau(Matrice:out Plateau) is
   begin
      for l in IntervalleLigne loop
        for c in B_INF_COLONNE..B_INF_COLONNE+1 loop
            Matrice(l,c):='X';
         end loop;
      end loop;
      for l in IntervalleLigne loop
        for c in B_SUP_COLONNE-1..B_SUP_COLONNE loop
            Matrice(l,c):='O';
         end loop;
      end loop;
      for l in IntervalleLigne loop
        for c in B_INF_COLONNE+2..B_SUP_COLONNE-2 loop
            Matrice(l,c):=' ';
         end loop;
      end loop;
   end initPlateau;


procedure jouerUnTour(p:in out Plateau;nbTour:in out IntervalleTour;idJ1,idJ2:in character) is
  ci,cf:Cases;
  appartientJoueur,caseVide,aMarche,aSaute:Boolean;
      cpt:integer:=1;
      n:IntervalleTour;
      veutSauter:Boolean:=FALSE;
  begin
      n:=nbTour;
      DemandeOuJouerCases(ci,cf);
While (n=nbTour) loop
    if (nbTour mod 2 /=0) then --le numéro du tour pair/impair gère l'ID du joueur.
      appartientJoueur:=caseAppartientJoueur(p,ci,idJ2);
    else
      appartientJoueur:=caseAppartientJoueur(p,ci,idJ1);
    end if;
    caseVide:=estCaseVide(p,cf);
    if ((appartientJoueur) and (caseVide)) then
      aMarche:=MarcheValide(ci,cf);
      aSaute:=SautEstValide(p,ci,cf);
      if ((aMarche)and(veutSauter)) then -- au premier tour veutSauter est initialisé à FAUX.
     jouerCase(p,ci,cf);
     nbTour:=nbTour+1;
      elsif (aSaute) then
          jouerCase(p,ci,cf);
               cpt:=cpt+1;
               AfficherPlateau(p);
               veutSauter:=veutRessauter;
               if (veutSauter=TRUE) then
                  ci.l:=cf.l;
                  ci.c:=cf.c;
                  DemanderSautSuivant(cf);
               end if;
               if(cpt=10)or(veutSauter=FALSE) then
                     nbTour:=nbTour+1;
               end if;
      else
     put("Vous avez jouer une case invalide, dommage c'est au tour de votre adversaire");
     nbTour:=nbTour+1;
      end if;
    else
      put("Vous avez déclaré une case qui ne vous appartenait pas ou une destination non vide, dommage c'est au tour de l'adversaire");
      nbTour:=nbTour+1;
    end if;
    AfficherPlateau(p);
end loop;
end jouerUnTour;

procedure FinDePartie (p:in Plateau;idJ1,idJ2:in character;nbTour:in IntervalleTour;Fini:out Boolean) is
      n,n2:Integer:=0;
   begin
      Fini:=FALSE;
      if (nbTour = NB_TOUR_MAX) then
   Fini:=TRUE;
         put("Le nombre de tour maximum a été dépassé; c'est un match nul");
      else
            for l in B_INF_LIGNE..B_SUP_LIGNE loop
                for c in B_INF_COLONNE..B_INF_COLONNE+1 loop
                   if (p(l,c)='O') then
                      n:=n+1;
                     end if;
               end loop;
            end loop;
         if (n=14) then
            put("Le joueur utilisant les O a gagné la partie");
            Fini:=TRUE;
         end if;
       for l in B_INF_LIGNE..B_SUP_LIGNE loop
                for c in B_SUP_COLONNE-1..B_SUP_COLONNE loop
                   if (p(l,c)='X') then
                      n2:=n2+1;
                     end if;
               end loop;
            end loop;
         if (n2=14) then
            put("Le joueur utilisant les X a gagné la partie");
            Fini:=TRUE;
         end if;
      end if;
end FinDePartie;






Et voilà les ceux qui gèrent la validité d'une case joué.
Ce n'est pas très propre au sens où si l’identification d'une ligne change par exemple A B C D au lieu de 1 2 3 4 alors ça marche plus; mais je ne me soucis pas de ce problème là puisque j'impose l'envoi d'un entier.

Code: Tout sélectionner
function MarcheValide(caseInitiale:Cases;caseFinale:Cases) return Boolean is
  test:Boolean;
  begin
      if ((caseFinale.l = caseInitiale.l) and ((caseFinale.c = caseInitiale.c+1)or(caseFinale.c = caseInitiale.c-1))) then
   test:=TRUE;
      elsif ((caseFinale.c = caseInitiale.c) and ((caseFinale.l = caseInitiale.l+1)or(caseFinale.l = caseInitiale.l-1))) then
   test:=TRUE;
      elsif ((caseFinale.c = caseInitiale.c+1) and ((caseFinale.l = caseInitiale.l+1)or(caseFinale.l = caseInitiale.l-1))) then
   test:=TRUE;
      elsif ((caseFinale.c = caseInitiale.c-1) and ((caseFinale.l = caseInitiale.l+1)or(caseFinale.l = caseInitiale.l-1))) then
   test:=TRUE;
      else
   test:=FALSE;
      end if;
      return test;
  end MarcheValide;

  function SautEstValide(p:Plateau;ci:Cases;cf:Cases) return Boolean is
  test:Boolean;
  begin
    if ((cf.l = ci.l) and ((cf.c = ci.c+2) and (p(ci.l,ci.c+1)/=' '))) then
         test:=TRUE;
    elsif ((cf.l = ci.l) and ((cf.c = ci.c-2) and (p(ci.l,ci.c-1)/=' '))) then
         test:=TRUE;
    elsif ((cf.c = ci.c) and ((cf.l = ci.l+2) and (p(ci.l+1,ci.c)/=' '))) then
         test:=TRUE;
    elsif ((cf.c = ci.c) and ((cf.l = ci.l-2) and (p(ci.l-1,ci.c)/=' '))) then
   test:=TRUE;
    elsif ((cf.c = ci.c+2) and ((cf.l = ci.l-2) and (p(ci.l-1,ci.c+1)/=' '))) then
         test:=TRUE;
    elsif ((cf.c = ci.c+2) and ((cf.l = ci.l+2) and (p(ci.l+1,ci.c+1)/=' '))) then
   test:=TRUE;
    elsif ((cf.c = ci.c-2) and ((cf.l = ci.l+2) and (p(ci.l+1,ci.c-1)/=' '))) then
         test:=TRUE;
    elsif ((cf.c = ci.c-2) and ((cf.l = ci.l-2) and (p(ci.l-1,ci.c-1)/=' '))) then
   test:=TRUE;
    else
   test:=FALSE;
    end if;
    return test;
  end sautEstValide;






Grosso modo; on peut dire que jouerUnPvP est la procédure principale.
Voici un exemple d'exécution:


Code: Tout sélectionner
Lors d'une partie joueur contre joueur, le joueur 1 choisit son pion. Le joueur 2 commence le jeu
Chaque joueur peut se déplacer dans une case voisine libre et peut également sauter par dessus un pion dans n'importe quelle direction
La partie prend fin lorsqu'un joueur a mis tous ces pions dans le camp adverse ou lorsque le nombre de tour dépasse la limite de 100
Lors d'une partie contre l'ordinateur, c'est au joueur de commencer.
Voulez vous jouer une partie joueur contre joueur (1) ou contre l'ordinateur (2) ? (1/2) 1

Le joueur 1 choisit son pion (X/O):X

   1 2 3 4 5 6 7
  ---------------
1 IXIXI I I IOIOI
  ---------------
2 IXIXI I I IOIOI
  ---------------
3 IXIXI I I IOIOI
  ---------------
4 IXIXI I I IOIOI
  ---------------
5 IXIXI I I IOIOI
  ---------------
6 IXIXI I I IOIOI
  ---------------
7 IXIXI I I IOIOI
  ---------------
Quelle case voulez vous déplacer ?
ligne:
1
 colone: 6

Où voulez-vous jouer ?ligne: 1
 colone: 5


raised CONSTRAINT_ERROR : mainsautemouton.adb:157 index check failed






Dan mon code, la ligne 157 correspond à :

elsif ((cf.c = ci.c) and ((cf.l = ci.l-2) and (p(ci.l-1,ci.c)/=' '))) then

de la fonction sautEstValide...alors qu'il ne s'agit même pas d'un saut mais d'une simple marche ici.






Le problème étant bien que je tape hors intervalle puisque lorsque l'utilisateur n'entre pas des cases correctes; un sous programmes fait passer un message d'erreur qui fait passer la main au joueur suivant.





Entre autre si je fais d'autre combinaison, certaines marchent:

Code: Tout sélectionner
Le joueur 1 choisit son pion (X/O):X

   1 2 3 4 5 6 7
  ---------------
1 IXIXI I I IOIOI
  ---------------
2 IXIXI I I IOIOI
  ---------------
3 IXIXI I I IOIOI
  ---------------
4 IXIXI I I IOIOI
  ---------------
5 IXIXI I I IOIOI
  ---------------
6 IXIXI I I IOIOI
  ---------------
7 IXIXI I I IOIOI
  ---------------
Quelle case voulez vous déplacer ?
ligne:
2
 colone: 1

Où voulez-vous jouer ?ligne: 2
 colone: 3

Vous avez déclaré une case qui ne vous appartenait pas ou une destination non vide, dommage c'est au tour de l'adversaire (normal puisque c'est le joueur 2 qui commence).

   1 2 3 4 5 6 7
  ---------------
1 IXIXI I I IOIOI
  ---------------
2 IXIXI I I IOIOI
  ---------------
3 IXIXI I I IOIOI
  ---------------
4 IXIXI I I IOIOI
  ---------------
5 IXIXI I I IOIOI
  ---------------
6 IXIXI I I IOIOI
  ---------------
7 IXIXI I I IOIOI
  ---------------
Quelle case voulez vous déplacer ?
ligne:
2
 colone: 1

Où voulez-vous jouer ?ligne: 2
 colone: 3


   1 2 3 4 5 6 7
  ---------------
1 IXIXI I I IOIOI
  ---------------
2 I IXIXI I IOIOI
  ---------------
3 IXIXI I I IOIOI
  ---------------
4 IXIXI I I IOIOI
  ---------------
5 IXIXI I I IOIOI
  ---------------
6 IXIXI I I IOIOI
  ---------------
7 IXIXI I I IOIOI
  ---------------
Voulez vous ressauter une case ? (o/n)n

   1 2 3 4 5 6 7
  ---------------
1 IXIXI I I IOIOI
  ---------------
2 I IXIXI I IOIOI
  ---------------
3 IXIXI I I IOIOI
  ---------------
4 IXIXI I I IOIOI
  ---------------
5 IXIXI I I IOIOI
  ---------------
6 IXIXI I I IOIOI
  ---------------
7 IXIXI I I IOIOI
  ---------------
Quelle case voulez vous déplacer ?
ligne:
1
 colone: 7

Où voulez-vous jouer ?ligne: 1
 colone: 5


raised CONSTRAINT_ERROR : mainsautemouton.adb:151 index check failed



Désolé pour ce post; mais je dois bien avouer que j'y comprends plus rien là. Le programme marchait pourtant bien tout à l'heure...et je ne crois pas avoir rien changé depuis...
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !



Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 12:39

par Dlzlogic » 08 Avr 2013, 23:32

Bonsoir,
L'une des difficultés de l'informatique est qu'il faut sans arrêt se remettre en cause. Ca se manifeste principalement par l'art du debug.
On peut chercher très longtemps après une erreur, mais dans tous les cas il faut la trouver. Il y a plusieurs techniques pour y arriver, il faut les connaitre et les utiliser soi-même.
J'ai deux exemples précis en mémoire, une équipe parfaitement compétente demandait à ses utilisateurs de leur relater tous les cas où une certaines erreur survenait, l'autre exemple, deux développeurs on passé 8 jours à trouver une erreur. Dans les deux cas, c'était des gens parfaitement compétents.
Alors un conseil, trouvez votre erreur vous-même, remettez-vous en cause à chaque ligne, c'est la seule façon d'apprendre l'informatique.
400 lignes, c'est vraiment très peu. La difficulté réelle viendra quand vous aurez un programme de plusieurs dizaines de milliers de lignes, écrites depuis plusieurs mois, voire plusieurs années et que vous tomber sur un bug. Il faudra bien le trouver. Alors exercez-vous avec votre programme de quelques centaines de lignes.
Bon courage.

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

par Rockleader » 08 Avr 2013, 23:36

Bien sur, je planche dessus; mais il faut que je "debuggue" tout ça avant mercredi soir; donc si je pouvais avoir une aide auxiliaire^^parce que bon, j'ai pas toutes mes journées à plancher dessus. Et là je bosse dessus en soirée; mais demain je vais être HS...
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Membre Légendaire
Messages: 6610
Enregistré le: 22 Nov 2007, 12:00

par fatal_error » 09 Avr 2013, 06:29

index failed -> bad index in array: soit -1 soit trop grand...

ligne: 157
Code: Tout sélectionner
elsif ((cf.c = ci.c) and ((cf.l = ci.l-2) and (p(ci.l-1,ci.c)/=' ')))


ci.l-2 ca sent mauvais.

PS:
c'est franchement rapide de debugger ce genre de subtilités. T'as la ligne qui est précisée, t'as juste à afficher la valeur des variables lors de l'expression :/

PS2:
tu as bien fait de pas mettre tout ton code, pour rester positif! :jap:
la vie est une fête :)

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

par Rockleader » 09 Avr 2013, 11:26

fatal_error a écrit:PS2:
tu as bien fait de pas mettre tout ton code, pour rester positif! :jap:


Mode kikoo on
Ouai enfin un compliment :zen: !!!
Mode kikoo off




Plus sérieusement, oui c'est vrai, je n'avais pas les idées très claires hier soir, je vais essayer de caler quelques affichages pour voir où se situe l'erreur. (Ok là c'est ligne 157; mais pour une autre combinaison de case ça serait une autre ligne de code qui planterait...)


Donc va falloir que j'essaie de refaire des affichages partout.

c'est rageant, on veut enlever une poussière d'un édifice, et en l'enlevant tout l'édifice ou presque s'écroule --'

*Vive la prog :we: *


Bon j'ai que 400 lignes de codes je vais pas me plaindre.
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, 18:42

par Rockleader » 09 Avr 2013, 18:10

Bien,

j'ai testé pas mal d'affectation pour le programme de marche et il semble fonctionner comme je le veux.

Je me suis attaqué au test de ma fonction qui détermine la validité d'un saut.

EN faisant une batterie de test du genre

ci:=(xi,yi);
cf:=(xf,yf);

EN donnant des valeurs précises bien sur.

Puis en faisant un affichage de ma fonction SautEstValide.


Pour ci(1,1) et cf (1,3) j'ai un TRUE.
Ce qui est donc bien normal.


Si je change et que je met volontairement un saut impossible qui ne rentre dans aucun cas

ci(1,1) et cf (1,2)

J'ai mon constraint error index check failed qui revient. Le soucis vient donc bien de cette fonction.
Je peux donc limiter mes recherches à ceci:

Code: Tout sélectionner
function SautEstValide(p:Plateau;ci:Cases;cf:Cases) return Boolean is
  test:Boolean;
  begin
    if ((cf.l = ci.l) and ((cf.c = ci.c+2) and (p(ci.l,ci.c+1)/=' '))) then
         test:=TRUE;
    elsif ((cf.l = ci.l) and ((cf.c = ci.c-2) and (p(ci.l,ci.c-1)/=' '))) then
         test:=TRUE;
    elsif ((cf.c = ci.c) and ((cf.l = ci.l+2) and (p(ci.l+1,ci.c)/=' '))) then
         test:=TRUE;
    elsif ((cf.c = ci.c) and ((cf.l = ci.l-2) and (p(ci.l-1,ci.c)/=' '))) then
   test:=TRUE;
    elsif ((cf.c = ci.c+2) and ((cf.l = ci.l-2) and (p(ci.l-1,ci.c+1)/=' '))) then
         test:=TRUE;
    elsif ((cf.c = ci.c+2) and ((cf.l = ci.l+2) and (p(ci.l+1,ci.c+1)/=' '))) then
   test:=TRUE;
    elsif ((cf.c = ci.c-2) and ((cf.l = ci.l+2) and (p(ci.l+1,ci.c-1)/=' '))) then
         test:=TRUE;
    elsif ((cf.c = ci.c-2) and ((cf.l = ci.l-2) and (p(ci.l-1,ci.c-1)/=' '))) then
   test:=TRUE;
    else
   test:=FALSE;
    end if;
    return test;
  end sautEstValide;


Pour le test précédent je pense avoir compris ce qui s'est passé. On m'indique la ligne 153 (le 2ème elsif).
on a ci.l = cf.l = 1 et pour la seconde partie du test; il cherche si cf.c = ci.c-2 AUtrement dit si 2=1-2.
Ce n’est pas le cas; donc en soit mon algo est bon je ne devrais pas rentrer dans ce cas là. Seulement il fait quand même le test pour vérifier. ET au cours du test il tape hors intervalle avec un résultat de -1. Et donc il crache logiquement.



Maintenant il faut que je solutionne ça. Je pourrais tout bêtement allonger l'intervalle; ainsi je ne devrais plus avoir de soucis; mais ça ne suivrait pas la logique; le test marcherait mais mon intervalle ne serait plus vraiment l'intervalle des lignes.



Peut être dois je travailler de façon indépendante sur un intervalle pour le test et sur un autre lorsque je traite réellement mes lignes ou cases.
En gros je garde mon intervalleLigne 1..7 et idem pour les colonnes.

Et je rajoute pour le test un intervalleTestLigne et colonne -1..8




Votre avis ? Est ce que cette solution pourrait marcher ? Si oui, n'y a t'il pas mieux à faire ? Parce que ça me donne un peu l'impression de forcer le truc pour que ça rentre dans mon algo et j'aime pas trop ça.


Encore une fois désolé si mes questions vous paraissent terriblement stupides; une nouvelle fois merci pour votre aide. Je suis simplement dans une période où j'essaie de structurer au mieux mes algo.

Je n'aime pas déjà ce que j'ai fait au niveau des condition de cette fonction, j'ai traité tout les cas un par un (heureusement que mon plateau fait pas 100 cases :ptdr: ) J'aurais du faire un truc plus générique; mais je voyais pas trop comment faire un algo correct là dessus donc j'ai jouer la courte sécurité; quitte à y revenir plus tard.


Bref je m'égare là.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 12:39

par Dlzlogic » 09 Avr 2013, 18:38

Bon, si j'ai bien compris votre pion est à une position et le joueur veut le mettre à une position "destination".
Or cette destination doit être à l'intérieur du jeu, donc (0il est indispensable que ce test soit fait avant toute vérification du genre "occupé ou pas".
Les shitch case sont assez efficaces pour ce genre de truc.
Quand vous ferez ce type de test sur des rater, il y a des centaines de lignes et de colonnes. C'est beaucoup plus amusant.

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

par Rockleader » 09 Avr 2013, 19:14

Dlzlogic a écrit:Bon, si j'ai bien compris votre pion est à une position et le joueur veut le mettre à une position "destination".
Or cette destination doit être à l'intérieur du jeu, donc (0<x<8 ET 0<y<8)
il est indispensable que ce test soit fait avant toute vérification du genre "occupé ou pas".
Les shitch case sont assez efficaces pour ce genre de truc.
Quand vous ferez ce type de test sur des rater, il y a des centaines de lignes et de colonnes. C'est beaucoup plus amusant.



Plutot 1..7 en fait comme intervalle.

La vérification que la case est compris dans cet intervalle n'a en réalité pas besoin d'être faite puisque si autre chose est entré; ça crashe et on obtient le constraint error de tout à l'heure.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 07:03

par ampholyte » 10 Avr 2013, 08:11

Rockleader a écrit:La vérification que la case est compris dans cet intervalle n'a en réalité pas besoin d'être faite puisque si autre chose est entré; ça crashe et on obtient le constraint error de tout à l'heure.


Il est vraiment recommandé de faire le test que Dzlogic a indiqué.

Imagine que tu utilises un logiciel de math (pour l'exemple) et que tu traces une courbe sur [1, 7]. Si tu veux la valeur de y pour x = 33 (par exemple), tu préfèrerais avoir un message d'erreur du style, x doit appartenir à [1, 7] et pouvoir poursuivre, plutôt qu'une grosse erreur qui crash le programme puis devoir le relancer, re-rentrer ta fonction, retracer la courbe ....

Dans le cas actuel, ton programme plante dès que tu obtiens le constrain error et tu es obligé de le relancer. Une simple condition te permet d'afficher une erreur sans pour autant fermer ton programme.

Comprends-tu ?

PS : Il faut toujours supposer que l'utilisateur est le plus stupide du monde surtout lors du debug (quoique même en release on peut tomber sur des cas :mur:) et donc tester les solutions extrèmes qui peuvent survenir (même si dans le comportement "normal" du programme on est pas censé tombé dessus).

----------------------------------
Concernant ta fonction, pourquoi ne pas stocker dans un tableau les possibilités de l'état TRUE;

Par exemple si je veux tester les cases autour d'une case k donnée, j'aurais simplement à faire :

tab = [(-1, 0), (-1, -1), (-1, 1), (0, 1), (0, -1), (1, 0), (1, 1), (1, -1)]

J'aurais simplement à addition les coordonnées de ma case k avec les différents éléments de ce tableau pour obtenir les coordonnées des points qui m'intéressent.

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

par Rockleader » 10 Avr 2013, 10:25

J'ai opté pour le changement d'intervalle


Dans mes constantes en gros j'avais B_INF = 1 et B_SUP=7

Mon nouvel intervalle est donc B_INF-2..B_SUP+2

Et comme c'est pas très propre à coté de ça je vais rajouter la fonction qui testera bien que les cases entré sont comprises dans l'intervalle 1..7.

Il n'y a que pour le test de saut que j'ai besoin de sortir de l'intervalle donc...


Merci pour vos conseils.

Pour ce qui est du tableau; j'y avais pensé; mais j'ai préféré gérer ça à travers une fonction, peut être à tord...
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 12:39

par Dlzlogic » 10 Avr 2013, 11:11

ampholyte a écrit:Concernant ta fonction, pourquoi ne pas stocker dans un tableau les possibilités de l'état TRUE;

Par exemple si je veux tester les cases autour d'une case k donnée, j'aurais simplement à faire :

tab = [(-1, 0), (-1, -1), (-1, 1), (0, 1), (0, -1), (1, 0), (1, 1), (1, -1)]

J'aurais simplement à addition les coordonnées de ma case k avec les différents éléments de ce tableau pour obtenir les coordonnées des points qui m'intéressent.

Bonjour Ampholyte,
Tien, c'est marrant, moi aussi je fais comme ça. Et quand on travaille avec des pavée de raster 9x9 par exemple, tout devient simple.

Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 07:03

par ampholyte » 10 Avr 2013, 12:45

Dlzlogic a écrit:Bonjour Ampholyte,
Tien, c'est marrant, moi aussi je fais comme ça. Et quand on travaille avec des pavée de raster 9x9 par exemple, tout devient simple.


[HS]
Salut =),

J'en ai fait l'expérience sur un jeu de la vie 3D à développer. J'ai utilisé 2 méthodes :

==> La méthode du bourrin : 1000 lignes de codes pour tester toutes les possibilités (quelques heures pour tout vérifier) :marteau:

==> 40 lignes de codes avec la technique du tableau (moins de 30min et beaucoup plus facile à vérifier) !

Cette expérience m'a permis de comprendre qu'il fallait toujours réfléchir un peu avant de se lancer dans le code. J'ai perdu beaucoup de temps sur la première méthode alors qu'en réfléchissant 15 min avant de me lancer j'aurais gagné quelques heures pour faire autre chose =).

Comme quoi c'est en forgeant qu'on devient forgeron :D

[/HS]

@Rockleader : Tu peux toujours essayer les deux méthodes. Je peux également te dire que la relecture est beaucoup plus simple lorsque tu passes par un tableau (débogguer 800 lignes de if/else pour trouver où est le + 1 manquant ou le -1 c'est assez fastidieux :D).

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

par Rockleader » 10 Avr 2013, 14:07

ampholyte a écrit:[HS]
@Rockleader : Tu peux toujours essayer les deux méthodes. Je peux également te dire que la relecture est beaucoup plus simple lorsque tu passes par un tableau (débogguer 800 lignes de if/else pour trouver où est le + 1 manquant ou le -1 c'est assez fastidieux :D).



Bien d'accord avec toi^^

Toutefois là j'ai enfin un truc qui marche, donc je ne vais pas y retoucher, ou du moins pas pour le rendu que je dois faire demain. Ce qui ne m’empêchera pas d'essayer de bidouiller quelques trucs sur mes temps libres.


Me reste plus qu'à faire une ia un peu plus développé que la mienne :)
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Membre Légendaire
Messages: 6610
Enregistré le: 22 Nov 2007, 12:00

par fatal_error » 10 Avr 2013, 17:59

Imagine que tu utilises un logiciel de math (pour l'exemple) et que tu traces une courbe sur [1, 7]. Si tu veux la valeur de y pour x = 33 (par exemple), tu préfèrerais avoir un message d'erreur du style, x doit appartenir à [1, 7] et pouvoir poursuivre, plutôt qu'une grosse erreur qui crash le programme puis devoir le relancer, re-rentrer ta fonction, retracer la courbe ....

en fait ya pas trop de rapport.

Dans ton logiciel, tu autorises l'utilisateur à rentrer n'importe quoi.

Mais rien ne t'interdis de ne pas l'autoriser à rentrer n'importe quoi. La particularité, c'est l'IHM.
Par défaut, le comportement associé, c'est si tu peux, alors t'as le droit, donc il faut gérer des entrées farfelues (style il rentre a, au lieu d'un nombre)

Par ligne de commande, si tu dis : saisis un chiffre entre 1 et 10 et qu'il saisit a, c'est pas ton problème.
la vie est une fête :)

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

par Rockleader » 10 Avr 2013, 18:37

D'ailleurs fatal, je me posais des questions là dessus.


Je lui demande de saisir un nombre, mais comme tu dis il peut être pas très fut fut et faire autre chose, auquel cas j'ai un message d'erreur qui va faire planter le programme.
Mais ne serait il pas possible de personnaliser un message d'erreur afin que le programme ne plante pas nécessairement ?

Je pense que c'est possible mais je n'ai aucune idée de la façon dont il faut faire ça.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Membre Légendaire
Messages: 6610
Enregistré le: 22 Nov 2007, 12:00

par fatal_error » 10 Avr 2013, 18:43

je connais pas assez l'ada donc je sais pas.
la vie est une fête :)

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

par Rockleader » 10 Avr 2013, 18:51

fatal_error a écrit:je connais pas assez l'ada donc je sais pas.



Ok; néanmoins ce genre d'opération doit être faisable peu importe dans quel langage.
Bon, merci pour votre aide et vos conseils.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 07:03

par ampholyte » 10 Avr 2013, 23:28

fatal_error a écrit:Par ligne de commande, si tu dis : saisis un chiffre entre 1 et 10 et qu'il saisit a, c'est pas ton problème.


Pas d'accord, le but d'un développeur est de sécuriser un maximum son code. Personnellement je pars du principe que si un programme provoque un crash, il n'est pas terminé, ni sécurisé.

Si on part sur ce que tu dis, alors pour prendre un exemple extrême exprès, je développe un site avec base de donnée, je n'ai pas besoin de sécuriser mes formulaires vu que l'utilisateur n'a pas à envoyer de requête javascript / SQL pour récupérer l'ensemble des login / mdp des utilisateurs.

De la même manière, lorsque tu parles de sécuriser l'IHM comment est-ce que tu procèdes ?
Tu vas déjà définir une borne min/max sur tes inputs pour que l'utilisateur puisse choisir entre 1 et 10 par exemple ==> La création de l'objet Inputs est blindé derrière et est testé afin que l'utilisateur ne puisse pas choisir 11, abc, -39, \o/ dans les inputs ou alors la nouvelle valeur est écrasée par l'ancienne valeur.

Sans IHM c'est à toi de gérer toutes les conditions pour que ton programme ne plante pas. Imagine ton OS plante car tu as fait une manipulation que n'était pas prévu et qui provoque l'effacement intégrale de ton disque dur, ne vas-tu pas râler sur les développeurs de cet OS car ils n'ont pas blindé le système ? Ou est-ce de ta responsabilité ?

Je pense franchement qu'il faut tout de suite prendre les bonnes habitudes et blinder son code en traitant les données d'entrées d'un utilisateur peut importe le programme. Un programme qui crache dès que l'on sort des conditions de tests est un mauvais programme et un programme non terminé.

Désolé pour le pavé un peu HS pour le coup mais il vaut mieux être clair dans la façon de voir les choses.

PS : Personnellement, lorsque je teste un programme (de quelqu'un d'autre ou de perso) je vérifie et je teste hors condition d'utilisation normale. Cela me permet de savoir si le programme peut-être ou non digne de confiance => et puis pourquoi ne pas vérifier s'il n'y aurait pas de fuite de mémoire qui pourrait endommager le système ? N'as-tu jamais fait une erreur de frappe, oublié de déverrouiller Verr Maj et donc envoyer un "é" à la place d'un "2" ?


Je lui demande de saisir un nombre, mais comme tu dis il peut être pas très fut fut et faire autre chose, auquel cas j'ai un message d'erreur qui va faire planter le programme.
Mais ne serait il pas possible de personnaliser un message d'erreur afin que le programme ne plante pas nécessairement ?


Tu peux simplement faire une condition sur les valeurs max / min :

Code: Tout sélectionner
variable a;
do {
    a = lireEntree();

    Si a  11 :
        AfficherMessage("Valeur incorrect, veuillez choisir un nombre entre 0 et 11");
} while (a  11);   



On redemande à l'utilisateur de ressaisir une valeur attendue dans l'intervalle 0, 11. C'est quelques choses d'assez courants si tu connais les limites de ton intervalle.

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

par Rockleader » 11 Avr 2013, 00:34

Pas si évident que ça ce que tu dis amphiolite.

Ton test en lui même ne marche pas si l'utilisateur n'entre pas un nombre.

Et dans le cas où il entre un nombre, je ne peut pas dire pour les autres langages mais en ada, j'aurais beau faire une boucle de ce type qui redemandera l'entrée tant qu'elle n'est pas dans l'intervalle, le programme me sortira quand même un constraint error car il devra en lisant au clavier affecter une vaeur qui n’est pas censé pouvoir être pris en charge.


Ce que je veux dire c'est que sur l'intervalle des entier -oo;+oo

TU peux faire boucler tant que tu n'ets pas dans 1;11 par exemple.

Mais si tu crée un sous type intervalle en lui même qui fait 1..11
Tu demande l'affectation à l'utilisateur d'une variable appartenant à l'intervalle. Si tu entre 0, ça va crash même si tu as une protection de boucle.


D'où l'interêt de gérer les data_error je suis bien d'accord; mais à mon niveau j'en suis incapable.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Membre Légendaire
Messages: 6610
Enregistré le: 22 Nov 2007, 12:00

par fatal_error » 11 Avr 2013, 06:38

Pas d'accord, le but d'un développeur est de sécuriser un maximum son code

certainement pas.

ce type de comportemenet amène souvent à des usines a gaz.

Si en entrée on te dit que ton paramètre est une chaine escapée, tu ne la retestes pas avant de faire ton insertion en bdd. Si ta chaine est dite quelconque, alors tu l'échappes.

Si tu as des (void*) et qu'on te dit que c'est un la sérialisation d'un string, (spécifié dans le cahier des charges de ta fonction), alors tu n'as pas à tester que c'est bien là la sérial d'un string.

Vérifier les fuites mémoires ca n'a rien à voir avec blinder son code. Ca s'appèle savoir coder.

Tester le programme pour des cas que le programme ne doit pas satisfaire, c'est ballo. Attention de pas tout confondre. Si on veut que ton programme gère les erreurs, alors tu gères les erreurs, si tu le veux pas, tu t'embêtes pas!!!!!


Donc définitivement non tu n'as pas à faire de la prog défensive si c'est pas exigé. Et rien ne l'exige quand tu codes pour toi. Qui plus est sur un projet minime.
la vie est une fête :)

 

Retourner vers ϟ Informatique

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 4 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