Program Jeu_de_memoire_couleur;
  uses crt,graph;
  var a,code,pilote,mode:integer;
  sequence: array[1..100] of integer;
  w,nom:string;
  reussi:boolean;
  const
  x = 255;
  y = 173;
  f = 427;
  c = cyan;
  r = 50;
  b = 0;

   tableau: array[1..11] of Record
    frequence,couleur,forme,posx,posy,dimx,dimy: integer; numero:char;
    end = (
      (frequence: 256; couleur: yellow; forme: 0; posx: 335; posy: 50; dimx: 255; dimy:153; numero:'9'),
      (frequence: 288; couleur: green; forme: 0; posx: 335; posy: 253; dimx: x; dimy:y; numero:'3'),
      (frequence: 320; couleur: blue; forme: 0; posx: 50; posy: 50; dimx: x; dimy:y; numero:'7'),
      (frequence: 341; couleur: red; forme: 0; posx: 50; posy: 253; dimx: x; dimy:y; numero:'1'),
      (frequence: 384; couleur: black; forme: 1; posx: 320; posy: 238; dimx: 100; dimy:100; numero:'.'),
      (frequence: 384; couleur: magenta; forme: 1; posx: 320; posy: 238; dimx: 90; dimy:90; numero:'5'),
      (frequence: f; couleur: black; forme: 1; posx: b; posy: b; dimx: r+2; dimy:r+2; numero:'.'),
      (frequence: f; couleur: c; forme: 1; posx: 320; posy: 70; dimx: r; dimy:r; numero:'8'),
      (frequence: f; couleur: c; forme: 1; posx: 320; posy: 406; dimx: r; dimy:r; numero:'2'),
      (frequence: f; couleur: c; forme: 1; posx: 80; posy: 238; dimx: r; dimy:r; numero:'4'),
      (frequence: f; couleur: c; forme: 1; posx: 560; posy: 238; dimx: r; dimy:r; numero:'6')
    );
    bouton:array[1..9] of integer = (1,2,3,4,6,8,9,10,11);

{Trace les boutons de chacun des niveaux}
Procedure Trace(var p:integer; couleurson:boolean; num:integer);
var s:integer;
begin
  For s:=1 to p do
    begin
      if (couleurson=true) or (tableau[s].couleur=black) then
      setfillstyle(1,tableau[s].couleur); (*Trace les boutons avec leur couleur originale*)
      if s=num then
      setfillstyle(1,white); (*Trace le bouton choisi en blanc*)
      if (couleurson<>true) and (tableau[s].couleur<>black) and (s<>num) then  setfillstyle(1,1); (*Trace en bleu*)
      if tableau[s].Forme=0 then (*Trace les rectangles*)
      bar(tableau[s].posx,tableau[s].posy,tableau[s].posx+x,tableau[s].posy+y)
      else if (s=7) then (*Trace les cercles noirs*)
      for a:=8 to 11 do begin
        setcolor(black);
        setfillstyle(1,black);
        fillellipse(tableau[a].posx,tableau[a].posy,tableau[s].dimx+10, tableau[s].dimy+10);
        end
      else begin
      setcolor(black);
      fillellipse(tableau[s].posx,tableau[s].posy,tableau[s].dimx,tableau[s].dimy);
      end;
    end;
  (*Ecrit le pointage*)
  setcolor(yellow);
  rectangle(450,440,550,478);
  settextstyle(3,0,1);
  settextjustify(1,1);
  outtextxy(500,445,'POINTAGE');
end;
(*FIN DE TRACE*)

(*Trace les rectangles pour le menu*)
procedure damier;
var e:integer;
begin
  For e:=1 to 5 do
  begin
    delay(100);
    setfillstyle(1,e);
    bar((15+125*(e-1)),15,(125*e),92);
    bar(15+125*(e-1),(getmaxy-92),125*e,(getmaxy-15));
    bar(15,15+92*(e-1),125,92*e);
    bar((getmaxx-125),15+92*(e-1),(getmaxx-15),92*e);
  end;
end;
(*Fin de damier*)

(*Presente le nom du jeu et demande d"entrer le nom*)
Procedure debut;
begin
  cleardevice;
  settextjustify(1,1);
  settextstyle(3,0,6);
  setcolor(magenta);
  outtextxy(((getmaxx)div 2),200,'SOPHIE SAYS');
  settextstyle(3,0,1);
  outtextxy(((getmaxx)div 2),250,'Realise par Sophie Dagenais');
  settextstyle(3,0,1);
  outtextxy(((getmaxx)div 2),300,'Entrez votre nom');
  readln(nom);
  outtextxy(((getmaxx)div 2),350,' Appuyez sur une touche pour commencer');
  damier;
  readln;
  cleardevice;
end;
(*Fin de debut*)

(*Donne les instructions*)
Procedure instructions;
var long,larg,n,s,t,z:integer; a:string;
begin
  cleardevice;
  damier;
  setcolor(magenta);
  settextstyle(3,0,6);
  settextjustify(1,1);
  settextstyle(3,0,1);
  setcolor(white);
  outtextxy(((getmaxx) div 2),110,'INSTRUCTIONS pour ' +nom); (*Premiere partie des instructions*)
  setcolor(magenta);
  outtextxy(((getmaxx) div 2),145,'Le but du jeu est de repeter');
  outtextxy(((getmaxx) div 2),165,'la sequence de couleur');
  outtextxy(((getmaxx) div 2),185,'qui apparaitra a l"ecran.');
  outtextxy(((getmaxx) div 2),205,'Pour ce faire utilisez les');
  outtextxy(((getmaxx) div 2),225,'touches de 1 a 9. La partie ');
  outtextxy(((getmaxx) div 2),245,'se terminera quand vous ferez');
  outtextxy(((getmaxx) div 2),265,' une erreur. Chaque ');
  outtextxy(((getmaxx) div 2),285,'sequence correctement repetee');
  outtextxy(((getmaxx) div 2),305,'vous rapportera un point');
  outtextxy(((getmaxx) div 2),325,'Bonne chance ' + nom + '!!!');
  setcolor(white);
  outtextxy(((getmaxx) div 2),345,'Appuyez sur enter pour la suite');
  readln;
  cleardevice;
  damier;
  setcolor(magenta);
  settextstyle(3,0,6);
  settextjustify(1,1);
  settextstyle(3,0,1);
  setcolor(white);
  outtextxy(((getmaxx) div 2),130,'INSTRUCTIONS (suite) pour ' +nom);
  setcolor(magenta);
  outtextxy(((getmaxx) div 2),165,'Pour vous faciliter la tache,');
  outtextxy(((getmaxx) div 2),185,'Utilisez les numeros a droite');
  outtextxy(((getmaxx) div 2),205,'sur le clavier.');
  setfillstyle(1,1);
  For long:= 1 to 3 do (*Dessine les touches tu clavier a utiliser*)
    For larg:= 1 to 3 do
      bar(240+30*long,205+30*larg,260+30*long,225+30*larg);
  larg:=1;
  s:=7;
  t:=s+2;
  For z:= 1 to 3 do begin
    long:=1;
    For n:= s to t do begin (*Inscrit les numeros sur les cases du clavier*)
      str(n,a);
      outtextxy(250+30*long,215+30*larg,a);
      long:=long+1;
    end;
    s:=s-3;
    t:=s+2;
    larg:=larg+1;
  end;
  outtextxy(((getmaxx) div 2),325,'Leur emplacement correspond a celui des');
  outtextxy(((getmaxx) div 2),345,'boutons. Bonne chance ' + nom + '!!!');
  setcolor(white);
  outtextxy(((getmaxx) div 2),365,'Appuyez sur enter pour retourner au menu');
  readln;
end;
(*Valide ce que l"usager a entre au clavier*)
Procedure choix (var nc,bt:integer; cs:boolean);
var touche:char; i,num,g:integer;
begin
  g:=0;
  reussi:=true;
  repeat
    repeat
      touche:=upcase(readkey); (*Lit ce que l"usager entre*)
      num:=0;
      for i:=1 to bt do
        if tableau[bouton[i]].numero=touche then num:=bouton[i]; (*Verifie si le numero correspond a un bouton*)
    until (num>0);
    g:=g+1;
    trace(bt,cs,num); (*Dessine la touche pesee en blanc*)
    sound(tableau[num].frequence);
    delay(500);
    num:=0;
    trace(bt,cs,num); (*Redessine la touche pesee avec sa couleur*)
    nosound;
    delay(200);
    if touche <> tableau[bouton[sequence[g]]].numero then
      reussi:=false; (*Verifie si la touche pesee correspond a la touche affichee aleatoirement*)
  until (reussi=false) or (g=nc);
end;
(*Sort de choix*)

(*Affiche le pointage avec un commentaire des que l"usager rate*)
procedure affiche_pointage (i:integer; w:string);
begin
  setcolor(white);
  settextstyle(3,0,6);
  settextjustify(1,1);
  outtextxy(((getmaxx) div 2),15,'GAME OVER');
  settextstyle(3,0,2);
  setcolor(magenta);
  if i=0 then outtextxy(((getmaxx) div 2),55,' 0 point c"est vraiment pas fort ' + nom + '!')
  else if i<=5 then
  outtextxy(((getmaxx) div 2),55,w +' points c"est vraiment pas fort ' + nom + '!')
  else if (i>5) and (i<=10) then
  outtextxy(((getmaxx) div 2),55,w +' points c"est correct ' + nom + '!')
  else if (i>10) and (i<=20) then
  outtextxy(((getmaxx) div 2),55,w + ' points c"est pas pire ' + nom + '!')
  else
  outtextxy(((getmaxx) div 2),55,w +' points c"est excellent ' + nom + '!' );
end;
(*Fin de affiche pointage*)

(*Ensemble des commandes pour faire fonctionner chacun des niveaux*)
Procedure joue_niveau(cs:boolean; pt,bt,del:integer);
var num,i,n,f:integer; A:char;
begin
  num:=0; (*Trace le niveau*)
  cleardevice;
  trace(pt,cs,num);
  setcolor(white);
  settextstyle(3,0,3);
  settextjustify(1,1);
  outtextxy(((getmaxx)div 2),200,'Appuyez sur');
  outtextxy(((getmaxx)div 2),240,'une touche');
  A:=readkey;
  cleardevice;
  trace(pt,cs,num);
  n:=1;
  repeat
    delay(del);
    randomize;
    sequence[n]:=(random(bt-1)+1); (*Genere une sequence aleatoire*)
    for i:=1 to n do begin
      num:=bouton[sequence[i]];
      trace(pt,cs,num); (*Colore en blanc la touche correspondant au numero genere aleatoirement*)
      if cs=true then
      sound(tableau[num].frequence);
      delay(500);
      num:=0;
      trace(pt,cs,num); (*Redessine la touche avec sa couleur originale*)
      nosound;
      delay(200);
    end;
    choix(n,pt,cs); (*Envoie les information necessaires a la validation des touches pesees par l"usager*)
    n:=n+1;
    if reussi=true then (*Si la bonne touche a ete appuyee, ajoute un point*)
    begin
      str(i,w);
      setfillstyle(1,black);
      bar(470,460,530,477);
      setcolor(magenta);
      settextstyle(3,0,1);
      outtextxy(500,464,w);
    end;
  until reussi=false; (*Sort de la boucle lorsque l"usager fait une erreur*)
  For f:=300 downto 200 do begin (*Fait jouer un son indiquant a l"usager qu"il a rate*)
    sound(f);
    delay(20); end;
  nosound;
  delay(500);
  repeat
    affiche_pointage(i,w); (*Allume a repetition la touche qui aurait du etre appuyee par l"usager*)
    num:=bouton[sequence[i]];
    trace(pt,cs,num);
    affiche_pointage(i,w);
    delay(500);
    num:=0;
    trace(pt,cs,num);
    affiche_pointage(i,w);
    delay(500);
  until keypressed;
  nosound;
end;
(*Fin de joue_niveau*)

(*Propose de jouer au niveau facile, moyen ou difficile*)
Procedure jeux;
var A:char; cs:boolean; pt,bt,del:integer;
begin
  cleardevice;
  damier;
  settextjustify(1,1);
  settextstyle(3,0,6);
  outtextxy(((getmaxx) div 2),130,'JEU');
  settextstyle(3,0,2);
  outtextxy(((getmaxx) div 2),230,'1 Facile');
  outtextxy(((getmaxx) div 2),280,'2 Moyen');
  outtextxy(((getmaxx) div 2),330,'3 Difficile');
  repeat
    A:=upcase(readkey);
  until (A='1') or (A='2') or (A='3'); (*Envoie a la procedure joue_niveau les parametres pour chacun des niveaux*)
  if (A='1') then begin cs:=true; pt:=6; bt:=5; del:=500; joue_niveau(cs,pt,bt,del); end;
  if (A='2') then begin cs:=true; pt:=11; bt:=9; del:=200; joue_niveau(cs,pt,bt,del); end;
  if (A='3') then begin cs:=false; pt:=11; bt:=9; del:=100; joue_niveau(cs,pt,bt,del); end;
  readln;
end;

(*Propose a l"usager de jouer, d"aller voir les instructions ou de quitter*)
Procedure menu;
var M:char;
begin
  repeat
  cleardevice;
  damier;
  setbkcolor(black);
  settextjustify(1,1);
  settextstyle(3,0,6);
  setcolor(magenta);
  outtextxy(((getmaxx)div 2),130,'MENU');
  settextstyle(3,0,4);
  settextjustify(0,0);
  outtextxy(220,220,'1 Instructions');
  outtextxy(220,270,'2 Jouer');
  outtextxy(220,320,'3 Quitter');
  M:=upcase(readkey);
  if (M='1') then instructions;
  if (M='2') then
    jeux;
until M='3';
end;


begin
  pilote:=detect;
  initgraph(pilote,mode,'m:/bgi');
  debut;
  menu;
  closegraph;
end.