Section courante

A propos

Section administrative du site

Vous vous savez du fabuleux jeux soviétique «Tetris», succès incroyable des années 1980, où il faut placer des cubes afin de faire disparaître des lignes. Voici la version que j'avais inclus dans le MonsterBook et que j'ai adapté pour MinGW et le «Win32».



A l'aide du code source C et C++ suivant pour le MinGW, vous trouvez la réponse que vous souhaitez :

MinGW C MinGW C++
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <conio.h>
  5. #include <windows.h>
  6. #include <wincon.h>
  7.  
  8. #define FALSE 0
  9. #define TRUE !FALSE
  10.  
  11.  /* Code de touche clavier renvoyée par ReadKey */
  12. #define kbNoKey 0 /* Pas de touche */
  13. #define kbEsc 0x011B /* Escape */
  14. #define kbUp 0x4800 /* Up */
  15. #define kbLeft 0x4BE0 /* Flèche de gauche (Left) */
  16. #define kbKeypad5 0x4CF0 /* 5 du bloc numérique */
  17. #define kbRight 0x4DE0 /* Flèche de droite (Right) */
  18. #define kbDn 0x50E0 /* Flèche du bas (Down) */
  19.  
  20. #define BLACK 0
  21.  
  22. char CurrX1=0;
  23. char CurrY1=0;
  24. char CurrX2=79;
  25. char CurrY2=24;
  26.  
  27. void GotoXY(char X,char Y) {
  28.  COORD Pos;
  29.  Pos.X=X;
  30.  if(Pos.X>0) Pos.X--;
  31.  Pos.Y=Y;
  32.  if(Pos.Y>0) Pos.Y--;
  33.  SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),Pos);
  34. }
  35.  
  36. void TextAttr(char Attr) {
  37.  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),Attr);
  38. }
  39.  
  40. void TextBackground(char Color) {
  41.  CONSOLE_SCREEN_BUFFER_INFO Info;
  42.  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&Info);
  43.  TextAttr((Color << 4)+(Info.wAttributes & 0x0F));
  44. }
  45.  
  46. void TextForeground(char Color) {
  47.  CONSOLE_SCREEN_BUFFER_INFO Info;
  48.  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&Info);
  49.  TextAttr((Info.wAttributes << 4)+(Color & 0x0F));
  50. }
  51.  
  52. void Window(char X1,char Y1,char X2,char Y2) {
  53.  CurrX1=X1;
  54.  if(CurrX1>0) CurrX1--;
  55.  CurrY1=Y1;
  56.  if(CurrY1>0) CurrY1--;
  57.  CurrX2=X2;
  58.  if(CurrX2>0) CurrX2--;
  59.  CurrY2=Y2;
  60.  if(CurrY2>0) CurrY2--;
  61. }
  62.  
  63. void ClrScr() {
  64.  COORD Pos;
  65.  HANDLE Console;
  66.  CONSOLE_SCREEN_BUFFER_INFO Info;
  67.  DWORD Output;
  68.  SHORT J;
  69.  Console=GetStdHandle(STD_OUTPUT_HANDLE);
  70.  GetConsoleScreenBufferInfo(Console,&Info);
  71.  GotoXY(1,1);
  72.  for(J=CurrY1;J<CurrY2;J++) {
  73.   Pos.X=CurrX1;
  74.   Pos.Y=J;
  75.   FillConsoleOutputCharacter(Console,' ',CurrX2-CurrX1+1,Pos,Output);
  76.   FillConsoleOutputAttribute(Console,Info.wAttributes,CurrX2-CurrX1+1,Pos,Output);
  77.  }
  78.  GotoXY(1,1);
  79. }
  80.  
  81. void MoveText(char X1,char Y1,char X2,char Y2,char X3,char Y3) {
  82.  HANDLE Console;
  83.  CONSOLE_SCREEN_BUFFER_INFO Info;
  84.  SMALL_RECT lpScrollRectangle,lpClipRectangle;
  85.  COORD dwDestinationOrigin;
  86.  CHAR_INFO lpFill;
  87.  Console=GetStdHandle(STD_OUTPUT_HANDLE);
  88.  GetConsoleScreenBufferInfo(Console,&Info);
  89.  lpScrollRectangle.Left=X1-1;
  90.  lpScrollRectangle.Top=Y1-1;
  91.  lpScrollRectangle.Right=X2-1;
  92.  lpScrollRectangle.Bottom=Y2-1+(Y3-Y1);
  93.  lpClipRectangle=lpScrollRectangle;
  94.  lpScrollRectangle.Bottom--;
  95.  dwDestinationOrigin.X=lpScrollRectangle.Left;
  96.  dwDestinationOrigin.Y=lpScrollRectangle.Top + (Y3-Y1);
  97.  lpFill.Char.UnicodeChar=' ';
  98.  lpFill.Attributes=Info.wAttributes;
  99.  ScrollConsoleScreenBuffer(Console,&lpScrollRectangle,&lpClipRectangle,dwDestinationOrigin,&lpFill);
  100. }
  101.  
  102.  
  103. typedef struct {
  104.   enum {tmNone,tmStart,tmPlay,tmGameOver} Mode;
  105.   int  Level;
  106.   long Score;
  107.   unsigned Bar,SLevel;
  108.   char Tbl[21][10];
  109.   char Form,Move;
  110.   int X,Y,Sleep;
  111.   int Touch,Ok;
  112.   int SleepDelay;
  113.   unsigned FBar;
  114.   char UpDate;
  115. } TetrisGame;
  116.  
  117. char BlkHeight[7][4]  = {
  118.   {4,1,4,1}, /* Barre */
  119.   {2,2,2,2}, /* Boîte */
  120.   {3,2,3,2}, /* V */
  121.   {3,2,3,2}, /* L gauche */
  122.   {3,2,3,2}, /*/ L droite */
  123.   {3,2,3,2}, /* Serpent romain */
  124.   {3,2,3,2}  /* Serpent arabe */
  125. };
  126. /* Largeur des objets: */
  127. char BlkLength[7][4] = {
  128.   {1,4,1,4}, /* Barre */
  129.   {2,2,2,2}, /* Boîte */
  130.   {2,3,2,3}, /* V */
  131.   {2,3,2,3}, /* L gauche */
  132.   {2,3,2,3}, /* L droite */
  133.   {2,3,2,3}, /* Serpent romain */
  134.   {2,3,2,3}  /* Serpent arabe */
  135. };
  136. char BlkFormatX[7][4][4]={
  137.   {{0,0,0,0},   /* OOOO */
  138.    {0,1,2,3},
  139.    {0,0,0,0},
  140.    {0,1,2,3}},
  141.   {{0,1,0,1},   /* OO */
  142.    {0,1,0,1},   /* OO */
  143.    {0,1,0,1},
  144.    {0,1,0,1}},
  145.   {{1,0,1,1},  /* OOO */
  146.    {1,0,1,2},   /* O */
  147.    {0,0,1,0},
  148.    {0,1,2,1}},
  149.   {{0,0,0,1},
  150.    {0,1,2,2},   /* O */
  151.    {0,1,1,1},   /* O */
  152.    {0,1,2,0}},  /* OO */
  153.   {{1,1,1,0},
  154.    {0,1,2,0},   /* O */
  155.    {1,0,0,0},   /* O */
  156.    {0,1,2,2}},  /* OO */
  157.   {{0,0,1,1},
  158.    {1,2,0,1},
  159.    {0,0,1,1},
  160.    {1,2,0,1}},
  161.   {{1,0,1,0},
  162.    {0,1,1,2},
  163.    {1,0,1,0},   /*OO */
  164.    {0,1,1,2}} /* OO */
  165.   };
  166. char BlkFormatY[7][4][4]={
  167.   {{0,1,2,3},   /* OOOO */
  168.    {0,0,0,0},
  169.    {0,1,2,3},
  170.    {0,0,0,0}},
  171.   {{0,0,1,1},   /* OO */
  172.    {0,0,1,1},   /* OO */
  173.    {0,0,1,1},
  174.    {0,0,1,1}},
  175.   {{0,1,1,2},   /* OOO */
  176.    {0,1,1,1},   /* O */
  177.    {0,1,1,2},
  178.    {0,0,0,1}},
  179.   {{0,1,2,2},
  180.    {1,1,1,0},   /* O */
  181.    {0,0,1,2},   /* O */
  182.    {0,0,0,1}},  /* OO */
  183.   {{0,1,2,2},
  184.    {1,1,1,0},   /* O */
  185.    {0,0,1,2},   /* O */
  186.    {0,0,0,1}},  /*OO */
  187.   {{0,1,1,2},
  188.    {0,0,1,1},
  189.    {0,1,1,2},
  190.    {0,0,1,1}},
  191.   {{0,1,1,2},
  192.    {0,0,1,1},
  193.    {0,1,1,2},   /*OO*/
  194.    {0,0,1,1}}  /* OO */
  195.   };
  196.  
  197.  
  198. char TetrisInit(TetrisGame *Q);
  199. void TetrisStart(TetrisGame *Q);
  200. void TetrisRefresh(TetrisGame *Q);
  201. unsigned TetrisPlay(TetrisGame *Q);
  202.  
  203. #define HomeX 15
  204. #define HomeY 2
  205.  
  206. void WaitRetrace() {
  207.  Sleep((int *)(1000/60));
  208. }
  209.  
  210. #define Chr(X) (X & 0xFF)
  211.  
  212. void BarSpcHor(char X1,char Y,char X2) {
  213.  Window(X1,Y,X2,Y);
  214.  ClrScr();
  215.  Window(1,1,40,24);
  216. }
  217.  
  218. char TetrisInit(TetrisGame *Q) {
  219.  memset(&(*Q),0,sizeof((*Q)));
  220.  (*Q).Level=1;
  221.  (*Q).Mode=tmStart;
  222. }
  223.  
  224. void TetrisStart(TetrisGame *Q) {
  225.  char I;
  226.  memset(&(*Q).Tbl,FALSE,sizeof((*Q).Tbl));
  227.  memset(&(*Q).Tbl[20],TRUE,sizeof((*Q).Tbl[20]));
  228.  (*Q).Score=0;(*Q).Bar=0;(*Q).SleepDelay=25;(*Q).Level=(*Q).SLevel;
  229.  for(I=0;I<(*Q).SLevel;I++) if((*Q).SleepDelay>6) (*Q).SleepDelay-=2;
  230.  (*Q).FBar=(*Q).Level << 4;
  231.  (*Q).Mode=tmStart;
  232. }
  233.  
  234. void TetrisRefresh(TetrisGame *Q) {
  235.  char I,J;
  236.  TextBackground(1+(*Q).Level);
  237.  ClrScr();
  238.  GotoXY(3,2);printf("Niveau:");
  239.  GotoXY(4,3);printf("%i",(*Q).Level);
  240.  GotoXY(3,5);printf("Pointage:");
  241.  GotoXY(4,6);printf("0");
  242.  GotoXY(3,8);printf("Ligne:");
  243.  GotoXY(4,9);printf("%i",(*Q).Bar);
  244.  Window(HomeX,HomeY,HomeX+9,HomeY+20);
  245.  TextBackground(BLACK);
  246.  ClrScr();
  247.  Window(1,1,40,24);
  248.  if((*Q).Mode==tmPlay || (*Q).Mode==tmGameOver) {
  249.   for(J=0;J<=19;J++) for(I=0;I<=9;I++) if((*Q).Tbl[J][I]) {
  250.    GotoXY(HomeX+I,HomeY+J);printf("þ");
  251.   }
  252.  }
  253. }
  254.  
  255. void TetrisPutForm(TetrisGame *Q, char Clr) {
  256.   char Chr;
  257.   char I,Attr,X,Y;
  258.   X=HomeX+(*Q).X;
  259.   Y=HomeY+(*Q).Y;
  260.   if(Clr) {
  261.    Chr=' ';Attr=7;
  262.   } else {
  263.    Chr='þ';Attr=0x71+(*Q).Form;
  264.   }
  265.   for(I=0;I<=3;I++) {
  266.    GotoXY(X+BlkFormatX[(*Q).Form][(*Q).Move][I],Y+BlkFormatY[(*Q).Form][(*Q).Move][I]);
  267.    TextAttr(Attr);
  268.    putch(Chr);
  269.    TextAttr(7);
  270.   }
  271.  }
  272.  
  273.  void TetrisInitGame(TetrisGame *Q) {
  274.   (*Q).Form=(rand() % 6);
  275.   if((*Q).Form==5) (*Q).Form+=(rand() % 2);
  276.   (*Q).X=5;(*Q).Y=0;
  277.   (*Q).Move=0;(*Q).Sleep=0;
  278.   TetrisPutForm(Q,FALSE);
  279.  }
  280.  
  281.  char TetrisUpDateData(TetrisGame *Q) {
  282.   char H,I,J,JK;
  283.   char Bonus;
  284.   char LnChk;
  285.   char result;
  286.   result=TRUE;(*Q).Sleep=0;
  287.   TetrisPutForm(Q,FALSE);
  288.   (*Q).Touch=0;(*Q).Ok=FALSE;
  289.   TetrisPutForm(Q,TRUE);
  290.   (*Q).Y++;
  291.   for(I=0;I<=3;I++) {
  292.    (*Q).Touch=(*Q).Touch || (*Q).Tbl[(*Q).Y+BlkFormatY[(*Q).Form][(*Q).Move][I]][(*Q).X+BlkFormatX[(*Q).Form][(*Q).Move][I]];
  293.   }
  294.   if((*Q).Touch) (*Q).Y--;
  295.   TetrisPutForm(Q,FALSE);
  296.   if((*Q).Touch) {
  297.    while((*Q).Sleep>(*Q).SleepDelay) (*Q).Sleep--;
  298.    (*Q).Sleep=0;(*Q).Ok=TRUE;
  299.    for(I=0;I<=3;I++) (*Q).Tbl[(*Q).Y+BlkFormatY[(*Q).Form][(*Q).Move][I]][(*Q).X+BlkFormatX[(*Q).Form][(*Q).Move][I]]=TRUE;
  300.    if(Q->Level>7) {
  301.     (*Q).Score+=((long) 5)*(*Q).Level;
  302.     GotoXY(4,6);printf("%l",(*Q).Score);
  303.    }
  304.    Bonus=0;
  305.    for(J=0;J<=19;J++) {
  306.     (*Q).Touch=TRUE;
  307.     for(I=0;I<=9;I++) (*Q).Touch=(*Q).Touch && (*Q).Tbl[J][I];
  308.     if((*Q).Touch) Bonus++;
  309.    }
  310.    if(Bonus>0) Bonus--;
  311.    (*Q).Touch=FALSE;
  312.    for(JK=0;JK<=7;JK++) {
  313.     for(J=0;J<=19;J++) {
  314.      LnChk=TRUE;
  315.      for(I=0;I<=9;I++) LnChk=LnChk && (*Q).Tbl[J][I];
  316.      if(LnChk) {
  317.       if(!(*Q).Touch) {
  318.        (*Q).Touch=TRUE;
  319.       }
  320.       if((JK & 1)==0) TextAttr(0xFF);
  321.                else TextAttr(7);
  322.       BarSpcHor(HomeX,HomeY+J,HomeX+9);
  323.      }
  324.     }
  325.     WaitRetrace();WaitRetrace();WaitRetrace();
  326.    }
  327.    for(J=0;J<=19;J++) {
  328.     (*Q).Touch=TRUE;
  329.     for(I=0;I<=9;I++) (*Q).Touch=(*Q).Touch && (*Q).Tbl[J][I];
  330.     if((*Q).Touch) {
  331.      memcpy(&(*Q).Tbl[1][0],&(*Q).Tbl[0][0],10*J);
  332.      memset(&(*Q).Tbl[0][0],FALSE,10);
  333.      MoveText(HomeX,HomeY,HomeX+9,HomeY+J-1,HomeX,HomeY+1);
  334.      (*Q).Score+=((long) 5)+(Bonus*4)*((*Q).Level+1)+10*(*Q).Level; (*Q).Bar++;
  335.      GotoXY(4,6);printf("%i",(*Q).Score);
  336.      GotoXY(4,9);printf("%i",(*Q).Bar);
  337.      I=((*Q).Bar+(*Q).FBar) >> 4;
  338.      if((*Q).Level!=I) {
  339.       (*Q).Level=I;
  340.       GotoXY(4,3);printf("%i",(*Q).Level+1);
  341.       if((*Q).SleepDelay>6) (*Q).SleepDelay-=2;
  342.      }
  343.     }
  344.    }
  345.    if((*Q).Y<=1) return FALSE;
  346.    TetrisInitGame(Q);
  347.   }
  348.   return result;
  349.  }
  350.  
  351.  unsigned TetrisGameOver(TetrisGame *Q) {
  352.   GotoXY(10,7);printf("Partie Terminer");
  353.   if((*Q).UpDate) {
  354.    (*Q).UpDate=0;
  355.   }
  356.   return kbEsc;
  357.  }
  358.  
  359. void TetrisFirstTime(TetrisGame *Q) {
  360.  TetrisStart(Q);
  361.  TetrisRefresh(Q);
  362.  TetrisInitGame(Q);
  363.  (*Q).Mode=tmPlay;(*Q).UpDate=TRUE;
  364. }
  365.  
  366. unsigned TetrisRun(TetrisGame *Q) {
  367.  char I,J,H,XT;
  368.  unsigned XJ,YJ,K;
  369.  char NoAction;
  370.  K=0;
  371.  do {
  372.   do {
  373.    if((*Q).Sleep>(*Q).SleepDelay) if(!TetrisUpDateData(Q)) {
  374.     (*Q).Mode=tmGameOver;
  375.     return;
  376.    }
  377.    WaitRetrace();
  378.    (*Q).Sleep++;
  379.   } while(!kbhit());
  380.   K=getch();
  381.   if(K==0xE0) K=K | (getch() << 8);
  382.   if(Chr(K)=='2') K=kbDn;
  383.   if(Chr(K)=='4') K=kbLeft;
  384.   if(Chr(K)=='6') K=kbRight;
  385.   NoAction=FALSE;
  386.   switch(K) {
  387.    case kbLeft:
  388.     if((*Q).X>0) {
  389.      (*Q).Touch=FALSE;
  390.      for(I=0;I<=3;I++) (*Q).Touch=(*Q).Touch || (*Q).Tbl[(*Q).Y+BlkFormatY[(*Q).Form][(*Q).Move][I]][(*Q).X+BlkFormatX[(*Q).Form][(*Q).Move][I]-1];
  391.       if(!(*Q).Touch) {
  392.        TetrisPutForm(Q,TRUE);
  393.        (*Q).X--;
  394.        TetrisPutForm(Q,FALSE);
  395.       }
  396.      }
  397.      break;
  398.    case kbRight:
  399.     if((*Q).X+BlkLength[(*Q).Form][(*Q).Move]-1<9) {
  400.      (*Q).Touch=FALSE;
  401.      for(I=0;I<=3;I++) (*Q).Touch=(*Q).Touch || (*Q).Tbl[(*Q).Y+BlkFormatY[(*Q).Form][(*Q).Move][I]][(*Q).X+BlkFormatX[(*Q).Form][(*Q).Move][I]+1];
  402.      if(!(*Q).Touch) {
  403.       TetrisPutForm(Q,TRUE);
  404.       (*Q).X++;
  405.       TetrisPutForm(Q,FALSE);
  406.      }
  407.     }
  408.     break;
  409.    case kbDn:
  410.     while(TRUE) {
  411.      if(!TetrisUpDateData(Q)) {
  412.       (*Q).Mode=tmGameOver;
  413.       return;
  414.      }
  415.      if((*Q).Ok) break;
  416.     }
  417.     break;
  418.    default:
  419.     NoAction=TRUE;
  420.     break;
  421.   }
  422.   if(NoAction) {
  423.    if((K==kbKeypad5)||(Chr(K)==' ')||(Chr(K)=='5')) {
  424.     (*Q).Touch=FALSE;
  425.     for(I=0;I<=3;I++) {
  426.      XT=(*Q).X+BlkFormatX[(*Q).Form][((*Q).Move+1) & 3][I]; (*Q).Touch=(*Q).Touch || (XT>9);
  427.      (*Q).Touch=(*Q).Touch || (*Q).Tbl[(*Q).Y+BlkFormatY[(*Q).Form][((*Q).Move+1)& 3][I]][XT];
  428.     }
  429.     if(!(*Q).Touch) {
  430.      TetrisPutForm(Q,TRUE);
  431.      (*Q).Move=((*Q).Move+1) & 3;
  432.      TetrisPutForm(Q,FALSE);
  433.     } else {
  434.      (*Q).Touch=FALSE;
  435.      for(I=0;I<=3;I++) {
  436.       XT=(*Q).X;
  437.       if(XT>0) XT--;
  438.       XT+=BlkFormatX[(*Q).Form][((*Q).Move+1) & 3][I]; (*Q).Touch=(*Q).Touch || (XT>9);
  439.       (*Q).Touch=(*Q).Touch || (*Q).Tbl[(*Q).Y+BlkFormatY[(*Q).Form][((*Q).Move+1) & 3][I]][XT];
  440.      }
  441.      if(!(*Q).Touch) {
  442.       TetrisPutForm(Q,TRUE);
  443.       (*Q).X--; (*Q).Move=((*Q).Move+1) & 3;
  444.       TetrisPutForm(Q,FALSE);
  445.      }
  446.     }
  447.    }
  448.     else
  449.    break;
  450.   }
  451.   if((K==kbEsc)||(Chr(K)=='Q')) break;
  452.  } while(TRUE);
  453.  return K;
  454. }
  455.  
  456. unsigned TetrisPlay(TetrisGame *Q) {
  457.  char I,J,H,XT;
  458.  unsigned XJ,YJ,K;
  459.  char NoAction;
  460.  
  461.  /*textmode(1);*/
  462.  TetrisRefresh(Q);
  463.  K=0;
  464.  do {
  465.   switch((*Q).Mode) {
  466.    case tmStart:
  467.     TetrisFirstTime(Q);
  468.     break;
  469.    case tmPlay:
  470.     K=TetrisRun(Q);
  471.     break;
  472.    case tmGameOver:
  473.     K=TetrisGameOver(Q);
  474.     break;
  475.   }
  476. _Exit:;
  477.  } while(K==0);
  478.  return K;
  479. }
  480.  
  481. void main() {
  482.  TetrisGame Game;
  483.  TetrisInit(&Game);
  484.  TetrisPlay(&Game);
  485. }
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <conio.h>
  5. #include <windows.h>
  6. #include <wincon.h>
  7.  
  8.  /* Code de touche clavier renvoyée par ReadKey */
  9. #define kbNoKey 0 /* Pas de touche */
  10. #define kbEsc 0x011B /* Escape */
  11. #define kbUp 0x4800 /* Up */
  12. #define kbLeft 0x4BE0 /* Flèche de gauche (Left) */
  13. #define kbKeypad5 0x4CF0 /* 5 du bloc numérique */
  14. #define kbRight 0x4DE0 /* Flèche de droite (Right) */
  15. #define kbDn 0x50E0 /* Flèche du bas (Down) */
  16.  
  17. #define BLACK 0
  18.  
  19. char CurrX1=0;
  20. char CurrY1=0;
  21. char CurrX2=79;
  22. char CurrY2=24;
  23.  
  24. void GotoXY(char X,char Y) {
  25.  COORD Pos;
  26.  Pos.X=X;
  27.  if(Pos.X>0) Pos.X--;
  28.  Pos.Y=Y;
  29.  if(Pos.Y>0) Pos.Y--;
  30.  SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),Pos);
  31. }
  32.  
  33. void TextAttr(char Attr) {
  34.  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),Attr);
  35. }
  36.  
  37. void TextBackground(char Color) {
  38.  CONSOLE_SCREEN_BUFFER_INFO Info;
  39.  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&Info);
  40.  TextAttr((Color << 4)+(Info.wAttributes & 0x0F));
  41. }
  42.  
  43. void TextForeground(char Color) {
  44.  CONSOLE_SCREEN_BUFFER_INFO Info;
  45.  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&Info);
  46.  TextAttr((Info.wAttributes << 4)+(Color & 0x0F));
  47. }
  48.  
  49. void Window(char X1,char Y1,char X2,char Y2) {
  50.  CurrX1=X1;
  51.  if(CurrX1>0) CurrX1--;
  52.  CurrY1=Y1;
  53.  if(CurrY1>0) CurrY1--;
  54.  CurrX2=X2;
  55.  if(CurrX2>0) CurrX2--;
  56.  CurrY2=Y2;
  57.  if(CurrY2>0) CurrY2--;
  58. }
  59.  
  60. void ClrScr() {
  61.  COORD Pos;
  62.  HANDLE Console;
  63.  CONSOLE_SCREEN_BUFFER_INFO Info;
  64.  DWORD Output;
  65.  SHORT J;
  66.  Console=GetStdHandle(STD_OUTPUT_HANDLE);
  67.  GetConsoleScreenBufferInfo(Console,&Info);
  68.  GotoXY(1,1);
  69.  for(J=CurrY1;J<CurrY2;J++) {
  70.   Pos.X=CurrX1;
  71.   Pos.Y=J;
  72.   FillConsoleOutputCharacter(Console,' ',CurrX2-CurrX1+1,Pos,&Output);
  73.   FillConsoleOutputAttribute(Console,Info.wAttributes,CurrX2-CurrX1+1,Pos,&Output);
  74.  }
  75.  GotoXY(1,1);
  76. }
  77.  
  78. void MoveText(char X1,char Y1,char X2,char Y2,char X3,char Y3) {
  79.  HANDLE Console;
  80.  CONSOLE_SCREEN_BUFFER_INFO Info;
  81.  SMALL_RECT lpScrollRectangle,lpClipRectangle;
  82.  COORD dwDestinationOrigin;
  83.  CHAR_INFO lpFill;
  84.  Console=GetStdHandle(STD_OUTPUT_HANDLE);
  85.  GetConsoleScreenBufferInfo(Console,&Info);
  86.  lpScrollRectangle.Left=X1-1;
  87.  lpScrollRectangle.Top=Y1-1;
  88.  lpScrollRectangle.Right=X2-1;
  89.  lpScrollRectangle.Bottom=Y2-1+(Y3-Y1);
  90.  lpClipRectangle=lpScrollRectangle;
  91.  lpScrollRectangle.Bottom--;
  92.  dwDestinationOrigin.X=lpScrollRectangle.Left;
  93.  dwDestinationOrigin.Y=lpScrollRectangle.Top + (Y3-Y1);
  94.  lpFill.Char.UnicodeChar=' ';
  95.  lpFill.Attributes=Info.wAttributes;
  96.  ScrollConsoleScreenBuffer(Console,&lpScrollRectangle,&lpClipRectangle,dwDestinationOrigin,&lpFill);
  97. }
  98.  
  99. typedef struct {
  100.   enum {tmNone,tmStart,tmPlay,tmGameOver} Mode;
  101.   int  Level;
  102.   long Score;
  103.   unsigned Bar,SLevel;
  104.   char Tbl[21][10];
  105.   char Form,Move;
  106.   int X,Y,Sleep;
  107.   int Touch,Ok;
  108.   int SleepDelay;
  109.   unsigned FBar;
  110.   char UpDate;
  111. } TetrisGame;
  112.  
  113. char BlkHeight[7][4]  = {
  114.   {4,1,4,1}, /* Barre */
  115.   {2,2,2,2}, /* Boîte */
  116.   {3,2,3,2}, /* V */
  117.   {3,2,3,2}, /* L gauche */
  118.   {3,2,3,2}, /*/ L droite */
  119.   {3,2,3,2}, /* Serpent romain */
  120.   {3,2,3,2}  /* Serpent arabe */
  121. };
  122. /* Largeur des objets: */
  123. char BlkLength[7][4] = {
  124.   {1,4,1,4}, /* Barre */
  125.   {2,2,2,2}, /* Boîte */
  126.   {2,3,2,3}, /* V */
  127.   {2,3,2,3}, /* L gauche */
  128.   {2,3,2,3}, /* L droite */
  129.   {2,3,2,3}, /* Serpent romain */
  130.   {2,3,2,3}  /* Serpent arabe */
  131. };
  132. char BlkFormatX[7][4][4]={
  133.   {{0,0,0,0},   /* OOOO */
  134.    {0,1,2,3},
  135.    {0,0,0,0},
  136.    {0,1,2,3}},
  137.   {{0,1,0,1},   /* OO */
  138.    {0,1,0,1},   /* OO */
  139.    {0,1,0,1},
  140.    {0,1,0,1}},
  141.   {{1,0,1,1},  /* OOO */
  142.    {1,0,1,2},   /* O */
  143.    {0,0,1,0},
  144.    {0,1,2,1}},
  145.   {{0,0,0,1},
  146.    {0,1,2,2},   /* O */
  147.    {0,1,1,1},   /* O */
  148.    {0,1,2,0}},  /* OO */
  149.   {{1,1,1,0},
  150.    {0,1,2,0},   /* O */
  151.    {1,0,0,0},   /* O */
  152.    {0,1,2,2}},  /* OO */
  153.   {{0,0,1,1},
  154.    {1,2,0,1},
  155.    {0,0,1,1},
  156.    {1,2,0,1}},
  157.   {{1,0,1,0},
  158.    {0,1,1,2},
  159.    {1,0,1,0},   /*OO */
  160.    {0,1,1,2}} /* OO */
  161.   };
  162. char BlkFormatY[7][4][4]={
  163.   {{0,1,2,3},   /* OOOO */
  164.    {0,0,0,0},
  165.    {0,1,2,3},
  166.    {0,0,0,0}},
  167.   {{0,0,1,1},   /* OO */
  168.    {0,0,1,1},   /* OO */
  169.    {0,0,1,1},
  170.    {0,0,1,1}},
  171.   {{0,1,1,2},   /* OOO */
  172.    {0,1,1,1},   /* O */
  173.    {0,1,1,2},
  174.    {0,0,0,1}},
  175.   {{0,1,2,2},
  176.    {1,1,1,0},   /* O */
  177.    {0,0,1,2},   /* O */
  178.    {0,0,0,1}},  /* OO */
  179.   {{0,1,2,2},
  180.    {1,1,1,0},   /* O */
  181.    {0,0,1,2},   /* O */
  182.    {0,0,0,1}},  /*OO */
  183.   {{0,1,1,2},
  184.    {0,0,1,1},
  185.    {0,1,1,2},
  186.    {0,0,1,1}},
  187.   {{0,1,1,2},
  188.    {0,0,1,1},
  189.    {0,1,1,2},   /*OO*/
  190.    {0,0,1,1}}  /* OO */
  191.   };
  192.  
  193.  
  194. #define HomeX 15
  195. #define HomeY 2
  196.  
  197. void WaitRetrace() {
  198.  Sleep((DWORD)(1000/60));
  199. }
  200.  
  201. #define Chr(X) (X & 0xFF)
  202.  
  203. void BarSpcHor(char X1,char Y,char X2) {
  204.  Window(X1,Y,X2,Y);
  205.  ClrScr();
  206.  Window(1,1,40,24);
  207. }
  208.  
  209. char TetrisInit(TetrisGame &Q) {
  210.  memset(&Q,0,sizeof(TetrisGame));
  211.  Q.Level=1;
  212.  Q.Mode=TetrisGame::tmStart;
  213. }
  214.  
  215. void TetrisStart(TetrisGame &Q) {
  216.  char I;
  217.  memset(&Q.Tbl,false,sizeof(Q.Tbl));
  218.  memset(&Q.Tbl[20],true,sizeof(Q.Tbl[20]));
  219.  Q.Score=0;Q.Bar=0;Q.SleepDelay=25;Q.Level=Q.SLevel;
  220.  for(I=0;I<Q.SLevel;I++) if(Q.SleepDelay>6) Q.SleepDelay-=2;
  221.  Q.FBar=Q.Level << 4;
  222.  Q.Mode=TetrisGame::tmStart;
  223. }
  224.  
  225. void TetrisRefresh(TetrisGame &Q) {
  226.  char I,J;
  227.  TextBackground(1+Q.Level);
  228.  ClrScr();
  229.  GotoXY(3,2);printf("Niveau:");
  230.  GotoXY(4,3);printf("%i",Q.Level);
  231.  GotoXY(3,5);printf("Pointage:");
  232.  GotoXY(4,6);printf("0");
  233.  GotoXY(3,8);printf("Ligne:");
  234.  GotoXY(4,9);printf("%i",Q.Bar);
  235.  Window(HomeX,HomeY,HomeX+9,HomeY+20);
  236.  TextBackground(BLACK);
  237.  ClrScr();
  238.  Window(1,1,40,24);
  239.  if(Q.Mode==TetrisGame::tmPlay || Q.Mode==TetrisGame::tmGameOver) {
  240.   for(J=0;J<=19;J++) for(I=0;I<=9;I++) if(Q.Tbl[J][I]) {
  241.    GotoXY(HomeX+I,HomeY+J);printf("þ");
  242.   }
  243.  }
  244. }
  245.  
  246. void TetrisPutForm(TetrisGame &Q, char Clr) {
  247.   char Chr;
  248.   char I,Attr,X,Y;
  249.   X=HomeX+Q.X;
  250.   Y=HomeY+Q.Y;
  251.   if(Clr) {
  252.    Chr=' ';Attr=7;
  253.   } else {
  254.    Chr='þ';Attr=0x71+Q.Form;
  255.   }
  256.   for(I=0;I<=3;I++) {
  257.    GotoXY(X+BlkFormatX[Q.Form][Q.Move][I],Y+BlkFormatY[Q.Form][Q.Move][I]);
  258.    TextAttr(Attr);
  259.    printf("%c",Chr);
  260.    TextAttr(7);
  261.   }
  262.  }
  263.  
  264.  void TetrisInitGame(TetrisGame &Q) {
  265.   Q.Form=(rand() % 6);
  266.   if(Q.Form==5) Q.Form+=(rand() % 2);
  267.   Q.X=5;Q.Y=0;
  268.   Q.Move=0;Q.Sleep=0;
  269.   TetrisPutForm(Q,false);
  270.  }
  271.  
  272.  char TetrisUpDateData(TetrisGame &Q) {
  273.   char H,I,J,JK;
  274.   char Bonus;
  275.   char LnChk;
  276.   char result;
  277.   result=true;Q.Sleep=0;
  278.   TetrisPutForm(Q,false);
  279.   Q.Touch=0;Q.Ok=false;
  280.   TetrisPutForm(Q,true);
  281.   Q.Y++;
  282.   for(I=0;I<=3;I++) {
  283.    Q.Touch=Q.Touch || Q.Tbl[Q.Y+BlkFormatY[Q.Form][Q.Move][I]][Q.X+BlkFormatX[Q.Form][Q.Move][I]];
  284.   }
  285.   if(Q.Touch) Q.Y--;
  286.   TetrisPutForm(Q,false);
  287.   if(Q.Touch) {
  288.    while(Q.Sleep>Q.SleepDelay) Q.Sleep--;
  289.    Q.Sleep=0;Q.Ok=true;
  290.    for(I=0;I<=3;I++) Q.Tbl[Q.Y+BlkFormatY[Q.Form][Q.Move][I]][Q.X+BlkFormatX[Q.Form][Q.Move][I]]=true;
  291.    if(Q.Level>7) {
  292.     Q.Score+=((long) 5)*Q.Level;
  293.     GotoXY(4,6);printf("%l",Q.Score);
  294.    }
  295.    Bonus=0;
  296.    for(J=0;J<=19;J++) {
  297.     Q.Touch=true;
  298.     for(I=0;I<=9;I++) Q.Touch=Q.Touch && Q.Tbl[J][I];
  299.     if(Q.Touch) Bonus++;
  300.    }
  301.    if(Bonus>0) Bonus--;
  302.    Q.Touch=false;
  303.    for(JK=0;JK<=7;JK++) {
  304.     for(J=0;J<=19;J++) {
  305.      LnChk=true;
  306.      for(I=0;I<=9;I++) LnChk=LnChk && Q.Tbl[J][I];
  307.      if(LnChk) {
  308.       if(!Q.Touch) {
  309.        Q.Touch=true;
  310.       }
  311.       if((JK & 1)==0) TextAttr(0xFF);
  312.                else TextAttr(7);
  313.       BarSpcHor(HomeX,HomeY+J,HomeX+9);
  314.      }
  315.     }
  316.     WaitRetrace();WaitRetrace();WaitRetrace();
  317.    }
  318.    for(J=0;J<=19;J++) {
  319.     Q.Touch=true;
  320.     for(I=0;I<=9;I++) Q.Touch=Q.Touch && Q.Tbl[J][I];
  321.     if(Q.Touch) {
  322.      memcpy(&Q.Tbl[1][0],&Q.Tbl[0][0],10*J);
  323.      memset(&Q.Tbl[0][0],false,10);
  324.      MoveText(HomeX,HomeY,HomeX+9,HomeY+J-1,HomeX,HomeY+1);
  325.      Q.Score+=((long) 5)+(Bonus*4)*(Q.Level+1)+10*Q.Level; Q.Bar++;
  326.      GotoXY(4,6);printf("%i",Q.Score);
  327.      GotoXY(4,9);printf("%i",Q.Bar);
  328.      I=(Q.Bar+Q.FBar) >> 4;
  329.      if(Q.Level!=I) {
  330.       Q.Level=I;
  331.       GotoXY(4,3);printf("%i",Q.Level+1);
  332.       if(Q.SleepDelay>6) Q.SleepDelay-=2;
  333.      }
  334.     }
  335.    }
  336.    if(Q.Y<=1) return false;
  337.    TetrisInitGame(Q);
  338.   }
  339.   return result;
  340.  }
  341.  
  342.  unsigned TetrisGameOver(TetrisGame &Q) {
  343.   GotoXY(10,7);printf("Partie Terminer");
  344.   if(Q.UpDate) {
  345.    Q.UpDate=0;
  346.   }
  347.   return kbEsc;
  348.  }
  349.  
  350. void TetrisFirstTime(TetrisGame &Q) {
  351.  TetrisStart(Q);
  352.  TetrisRefresh(Q);
  353.  TetrisInitGame(Q);
  354.  Q.Mode=TetrisGame::tmPlay;Q.UpDate=true;
  355. }
  356.  
  357. unsigned TetrisRun(TetrisGame &Q) {
  358.  char I,J,H,XT;
  359.  unsigned XJ,YJ,K;
  360.  char NoAction;
  361.  K=0;
  362.  do {
  363.   do {
  364.    if(Q.Sleep>Q.SleepDelay) if(!TetrisUpDateData(Q)) {
  365.     Q.Mode=TetrisGame::tmGameOver;
  366.     return 0;
  367.    }
  368.    WaitRetrace();
  369.    Q.Sleep++;
  370.   } while(!kbhit());
  371.   K=getch();
  372.   if(K==0xE0) K=K | (getch() << 8);
  373.   if(Chr(K)=='2') K=kbDn;
  374.   if(Chr(K)=='4') K=kbLeft;
  375.   if(Chr(K)=='6') K=kbRight;
  376.   NoAction=false;
  377.   switch(K) {
  378.    case kbLeft:
  379.     if(Q.X>0) {
  380.      Q.Touch=false;
  381.      for(I=0;I<=3;I++) Q.Touch=Q.Touch || Q.Tbl[Q.Y+BlkFormatY[Q.Form][Q.Move][I]][Q.X+BlkFormatX[Q.Form][Q.Move][I]-1];
  382.       if(!Q.Touch) {
  383.        TetrisPutForm(Q,true);
  384.        Q.X--;
  385.        TetrisPutForm(Q,false);
  386.       }
  387.      }
  388.      break;
  389.    case kbRight:
  390.     if(Q.X+BlkLength[Q.Form][Q.Move]-1<9) {
  391.      Q.Touch=false;
  392.      for(I=0;I<=3;I++) Q.Touch=Q.Touch || Q.Tbl[Q.Y+BlkFormatY[Q.Form][Q.Move][I]][Q.X+BlkFormatX[Q.Form][Q.Move][I]+1];
  393.      if(!Q.Touch) {
  394.       TetrisPutForm(Q,true);
  395.       Q.X++;
  396.       TetrisPutForm(Q,false);
  397.      }
  398.     }
  399.     break;
  400.    case kbDn:
  401.     while(true) {
  402.      if(!TetrisUpDateData(Q)) {
  403.       Q.Mode=TetrisGame::tmGameOver;
  404.       return 0;
  405.      }
  406.      if(Q.Ok) break;
  407.     }
  408.     break;
  409.    default:
  410.     NoAction=true;
  411.     break;
  412.   }
  413.   if(NoAction) {
  414.    if((K==kbKeypad5)||(Chr(K)==' ')||(Chr(K)=='5')) {
  415.     Q.Touch=false;
  416.     for(I=0;I<=3;I++) {
  417.      XT=Q.X+BlkFormatX[Q.Form][(Q.Move+1) & 3][I]; Q.Touch=Q.Touch || (XT>9);
  418.      Q.Touch=Q.Touch || Q.Tbl[Q.Y+BlkFormatY[Q.Form][(Q.Move+1)& 3][I]][XT];
  419.     }
  420.     if(!Q.Touch) {
  421.      TetrisPutForm(Q,true);
  422.      Q.Move=(Q.Move+1) & 3;
  423.      TetrisPutForm(Q,false);
  424.     } else {
  425.      Q.Touch=false;
  426.      for(I=0;I<=3;I++) {
  427.       XT=Q.X;
  428.       if(XT>0) XT--;
  429.       XT+=BlkFormatX[Q.Form][(Q.Move+1) & 3][I]; Q.Touch=Q.Touch || (XT>9);
  430.       Q.Touch=Q.Touch || Q.Tbl[Q.Y+BlkFormatY[Q.Form][(Q.Move+1) & 3][I]][XT];
  431.      }
  432.      if(!Q.Touch) {
  433.       TetrisPutForm(Q,true);
  434.       Q.X--; Q.Move=(Q.Move+1) & 3;
  435.       TetrisPutForm(Q,false);
  436.      }
  437.     }
  438.    }
  439.     else
  440.    break;
  441.   }
  442.   if((K==kbEsc)||(Chr(K)=='Q')) break;
  443.  } while(true);
  444.  return K;
  445. }
  446.  
  447. unsigned TetrisPlay(TetrisGame &Q) {
  448.  char I,J,H,XT;
  449.  unsigned XJ,YJ,K;
  450.  char NoAction;
  451.  
  452.  /*textmode(1);*/
  453.  TetrisRefresh(Q);
  454.  K=0;
  455.  do {
  456.   switch(Q.Mode) {
  457.    case TetrisGame::tmStart:
  458.     TetrisFirstTime(Q);
  459.     break;
  460.    case TetrisGame::tmPlay:
  461.     K=TetrisRun(Q);
  462.     break;
  463.    case TetrisGame::tmGameOver:
  464.     K=TetrisGameOver(Q);
  465.     break;
  466.   }
  467. _Exit:;
  468.  } while(K==0);
  469.  return K;
  470. }
  471.  
  472. int main() {
  473.  TetrisGame Game;
  474.  TetrisInit(Game);
  475.  TetrisPlay(Game);
  476.  return 0;
  477. }


Dernière mise à jour : Samedi, le 7 avril 2018