Section courante

A propos

Section administrative du site

Tetris

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 disparaitre des lignes. Voici la version que j'ai traduite de la version que j'avais originalement développé en langage de programmation Turbo Pascal.

A l'aide du code source C suivant pour le Turbo C version 2.0 de 1989, vous trouvez la réponse que vous souhaitez:

  1. #include <conio.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5.  
  6. #define FALSE 0
  7. #define TRUE !FALSE
  8.  
  9.  /* Code de touche clavier renvoyée par ReadKey */
  10. #define kbNoKey 0 /* Pas de touche */
  11. #define kbEsc 0x011B /* Escape */
  12. #define kbUp 0x4800 /* Up */
  13. #define kbLeft 0x4B00 /* Flèche de gauche (Left) */
  14. #define kbKeypad5 0x4CF0 /* 5 du bloc numérique */
  15. #define kbRight 0x4D00 /* Flèche de droite (Right) */
  16. #define kbDn 0x5000 /* Flèche du bas (Down) */
  17.  
  18. typedef struct {
  19.   enum {tmNone,tmStart,tmPlay,tmGameOver} Mode;
  20.   int  Level;
  21.   long Score;
  22.   unsigned Bar,SLevel;
  23.   char Tbl[21][10];
  24.   char Form,Move;
  25.   int X,Y,Sleep;
  26.   int Touch,Ok;
  27.   int SleepDelay;
  28.   unsigned FBar;
  29.   char UpDate;
  30. } TetrisGame;
  31.  
  32. char BlkHeight[7][4]  = {
  33.   {4,1,4,1}, /* Barre */
  34.   {2,2,2,2}, /* Boîte */
  35.   {3,2,3,2}, /* V */
  36.   {3,2,3,2}, /* L gauche */
  37.   {3,2,3,2}, /*/ L droite */
  38.   {3,2,3,2}, /* Serpent romain */
  39.   {3,2,3,2}  /* Serpent arabe */
  40. };
  41. /* Largeur des objets: */
  42. char BlkLength[7][4] = {
  43.   {1,4,1,4}, /* Barre */
  44.   {2,2,2,2}, /* Boîte */
  45.   {2,3,2,3}, /* V */
  46.   {2,3,2,3}, /* L gauche */
  47.   {2,3,2,3}, /* L droite */
  48.   {2,3,2,3}, /* Serpent romain */
  49.   {2,3,2,3}  /* Serpent arabe */
  50. };
  51. char BlkFormatX[7][4][4]={
  52.   {{0,0,0,0},   /* OOOO */
  53.    {0,1,2,3},
  54.    {0,0,0,0},
  55.    {0,1,2,3}},
  56.   {{0,1,0,1},   /* OO */
  57.    {0,1,0,1},   /* OO */
  58.    {0,1,0,1},
  59.    {0,1,0,1}},
  60.   {{1,0,1,1},  /* OOO */
  61.    {1,0,1,2},   /* O */
  62.    {0,0,1,0},
  63.    {0,1,2,1}},
  64.   {{0,0,0,1},
  65.    {0,1,2,2},   /* O */
  66.    {0,1,1,1},   /* O */
  67.    {0,1,2,0}},  /* OO */
  68.   {{1,1,1,0},
  69.    {0,1,2,0},   /* O */
  70.    {1,0,0,0},   /* O */
  71.    {0,1,2,2}},  /* OO */
  72.   {{0,0,1,1},
  73.    {1,2,0,1},
  74.    {0,0,1,1},
  75.    {1,2,0,1}},
  76.   {{1,0,1,0},
  77.    {0,1,1,2},
  78.    {1,0,1,0},   /*OO */
  79.    {0,1,1,2}} /* OO */
  80.   };
  81. char BlkFormatY[7][4][4]={
  82.   {{0,1,2,3},   /* OOOO */
  83.    {0,0,0,0},
  84.    {0,1,2,3},
  85.    {0,0,0,0}},
  86.   {{0,0,1,1},   /* OO */
  87.    {0,0,1,1},   /* OO */
  88.    {0,0,1,1},
  89.    {0,0,1,1}},
  90.   {{0,1,1,2},   /* OOO */
  91.    {0,1,1,1},   /* O */
  92.    {0,1,1,2},
  93.    {0,0,0,1}},
  94.   {{0,1,2,2},
  95.    {1,1,1,0},   /* O */
  96.    {0,0,1,2},   /* O */
  97.    {0,0,0,1}},  /* OO */
  98.   {{0,1,2,2},
  99.    {1,1,1,0},   /* O */
  100.    {0,0,1,2},   /* O */
  101.    {0,0,0,1}},  /*OO */
  102.   {{0,1,1,2},
  103.    {0,0,1,1},
  104.    {0,1,1,2},
  105.    {0,0,1,1}},
  106.   {{0,1,1,2},
  107.    {0,0,1,1},
  108.    {0,1,1,2},   /*OO*/
  109.    {0,0,1,1}}  /* OO */
  110.   };
  111.  
  112.  
  113. char TetrisInit(TetrisGame *Q);
  114. void TetrisStart(TetrisGame *Q);
  115. void TetrisRefresh(TetrisGame *Q);
  116. unsigned TetrisPlay(TetrisGame *Q);
  117.  
  118. #define HomeX 15
  119. #define HomeY 2
  120.  
  121. void WaitRetrace() {
  122.  delay((int *)(1000/60));
  123. }
  124.  
  125. #define Chr(X) (X & 0xFF)
  126.  
  127. void TextAttr(char Attr) {
  128.  textcolor(Attr & 0xF);
  129.  textbackground(Attr >> 4);
  130. }
  131.  
  132. void BarSpcHor(char X1,char Y,char X2) {
  133.  window(X1,Y,X2,Y);
  134.  clrscr();
  135.  window(1,1,40,25);
  136. }
  137.  
  138. char TetrisInit(TetrisGame *Q) {
  139.  memset(&(*Q),0,sizeof((*Q)));
  140.  (*Q).Level=1;
  141.  (*Q).Mode=tmStart;
  142. }
  143.  
  144. void TetrisStart(TetrisGame *Q) {
  145.  char I;
  146.  memset(&(*Q).Tbl,FALSE,sizeof((*Q).Tbl));
  147.  memset(&(*Q).Tbl[20],TRUE,sizeof((*Q).Tbl[20]));
  148.  (*Q).Score=0;(*Q).Bar=0;(*Q).SleepDelay=25;(*Q).Level=(*Q).SLevel;
  149.  for(I=0;I<(*Q).SLevel;I++) if((*Q).SleepDelay>6) (*Q).SleepDelay-=2;
  150.  (*Q).FBar=(*Q).Level << 4;
  151.  (*Q).Mode=tmStart;
  152. }
  153.  
  154. void TetrisRefresh(TetrisGame *Q) {
  155.  char I,J;
  156.  textbackground(1+(*Q).Level);
  157.  clrscr();
  158.  gotoxy(3,2);printf("Niveau:");
  159.  gotoxy(4,3);printf("%i",(*Q).Level);
  160.  gotoxy(3,5);printf("Pointage:");
  161.  gotoxy(4,6);printf("0");
  162.  gotoxy(3,8);printf("Ligne:");
  163.  gotoxy(4,9);printf("%i",(*Q).Bar);
  164.  window(HomeX,HomeY,HomeX+9,HomeY+19);
  165.  textbackground(BLACK);
  166.  clrscr();
  167.  window(1,1,40,25);
  168.  if((*Q).Mode==tmPlay || (*Q).Mode==tmGameOver) {
  169.   for(J=0;J<=19;J++) for(I=0;I<=9;I++) if((*Q).Tbl[J][I]) {
  170.    gotoxy(HomeX+I,HomeY+J);printf("þ");
  171.   }
  172.  }
  173. }
  174.  
  175. void TetrisPutForm(TetrisGame *Q, char Clr) {
  176.   char Chr;
  177.   char I,Attr,X,Y;
  178.   X=HomeX+(*Q).X;
  179.   Y=HomeY+(*Q).Y;
  180.   if(Clr) {
  181.    Chr=' ';Attr=7;
  182.   } else {
  183.    Chr='þ';Attr=0x71+(*Q).Form;
  184.   }
  185.   for(I=0;I<=3;I++) {
  186.    gotoxy(X+BlkFormatX[(*Q).Form][(*Q).Move][I],Y+BlkFormatY[(*Q).Form][(*Q).Move][I]);
  187.    TextAttr(Attr);
  188.    putch(Chr);
  189.    TextAttr(7);
  190.   }
  191.  }
  192.  
  193.  void TetrisInitGame(TetrisGame *Q) {
  194.   (*Q).Form=(rand() % 6);
  195.   if((*Q).Form==5) (*Q).Form+=(rand() % 2);
  196.   (*Q).X=5;(*Q).Y=0;
  197.   (*Q).Move=0;(*Q).Sleep=0;
  198.   TetrisPutForm(Q,FALSE);
  199.  }
  200.  
  201.  char TetrisUpDateData(TetrisGame *Q) {
  202.   char H,I,J,JK;
  203.   char Bonus;
  204.   char LnChk;
  205.   char result;
  206.   result=TRUE;(*Q).Sleep=0;
  207.   TetrisPutForm(Q,FALSE);
  208.   (*Q).Touch=0;(*Q).Ok=FALSE;
  209.   TetrisPutForm(Q,TRUE);
  210.   (*Q).Y++;
  211.   for(I=0;I<=3;I++) {
  212.    (*Q).Touch=(*Q).Touch || (*Q).Tbl[(*Q).Y+BlkFormatY[(*Q).Form][(*Q).Move][I]][(*Q).X+BlkFormatX[(*Q).Form][(*Q).Move][I]];
  213.   }
  214.   if((*Q).Touch) (*Q).Y--;
  215.   TetrisPutForm(Q,FALSE);
  216.   if((*Q).Touch) {
  217.    while((*Q).Sleep>(*Q).SleepDelay) (*Q).Sleep--;
  218.    (*Q).Sleep=0;(*Q).Ok=TRUE;
  219.    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;
  220.    if(Q->Level>7) {
  221.     (*Q).Score+=((long) 5)*(*Q).Level;
  222.     gotoxy(4,6);printf("%l",(*Q).Score);
  223.    }
  224.    Bonus=0;
  225.    for(J=0;J<=19;J++) {
  226.     (*Q).Touch=TRUE;
  227.     for(I=0;I<=9;I++) (*Q).Touch=(*Q).Touch && (*Q).Tbl[J][I];
  228.     if((*Q).Touch) Bonus++;
  229.    }
  230.    if(Bonus>0) Bonus--;
  231.    (*Q).Touch=FALSE;
  232.    for(JK=0;JK<=7;JK++) {
  233.     for(J=0;J<=19;J++) {
  234.      LnChk=TRUE;
  235.      for(I=0;I<=9;I++) LnChk=LnChk && (*Q).Tbl[J][I];
  236.      if(LnChk) {
  237.       if(!(*Q).Touch) {
  238.        (*Q).Touch=TRUE;
  239.       }
  240.       if(JK & 1==0) TextAttr(0xFF);
  241.                else TextAttr(7);
  242.       BarSpcHor(HomeX,HomeY+J,HomeX+9);
  243.      }
  244.     }
  245.     WaitRetrace();WaitRetrace();WaitRetrace();
  246.    }
  247.    for(J=0;J<=19;J++) {
  248.     (*Q).Touch=TRUE;
  249.     for(I=0;I<=9;I++) (*Q).Touch=(*Q).Touch && (*Q).Tbl[J][I];
  250.     if((*Q).Touch) {
  251.      memcpy(&(*Q).Tbl[1][0],&(*Q).Tbl[0][0],10*J);
  252.      memset(&(*Q).Tbl[0][0],FALSE,10);
  253.      movetext(HomeX,HomeY,HomeX+9,HomeY+J-1,HomeX,HomeY+1);
  254.      (*Q).Score+=((long) 5)+(Bonus*4)*((*Q).Level+1)+10*(*Q).Level; (*Q).Bar++;
  255.      gotoxy(4,6);printf("%i",(*Q).Score);
  256.      gotoxy(4,9);printf("%i",(*Q).Bar);
  257.      I=((*Q).Bar+(*Q).FBar) >> 4;
  258.      if((*Q).Level!=I) {
  259.       (*Q).Level=I;
  260.       gotoxy(4,3);printf("%i",(*Q).Level+1);
  261.       if((*Q).SleepDelay>6) (*Q).SleepDelay-=2;
  262.      }
  263.     }
  264.    }
  265.    if((*Q).Y<=1) return FALSE;
  266.    TetrisInitGame(Q);
  267.   }
  268.   return result;
  269.  }
  270.  
  271.  unsigned TetrisGameOver(TetrisGame *Q) {
  272.   gotoxy(10,7);printf("Partie Terminer");
  273.   if((*Q).UpDate) {
  274.    (*Q).UpDate=0;
  275.   }
  276.   return kbEsc;
  277.  }
  278.  
  279. void TetrisFirstTime(TetrisGame *Q) {
  280.  TetrisStart(Q);
  281.  TetrisRefresh(Q);
  282.  TetrisInitGame(Q);
  283.  (*Q).Mode=tmPlay;(*Q).UpDate=TRUE;
  284. }
  285.  
  286. unsigned TetrisRun(TetrisGame *Q) {
  287.  char I,J,H,XT;
  288.  unsigned XJ,YJ,K;
  289.  char NoAction;
  290.  K=0;
  291.  do {
  292.   do {
  293.    if((*Q).Sleep>(*Q).SleepDelay) if(!TetrisUpDateData(Q)) {
  294.     (*Q).Mode=tmGameOver;
  295.     return;
  296.    }
  297.    WaitRetrace();
  298.    (*Q).Sleep++;
  299.   } while(!kbhit());
  300.   K=getch();
  301.   if(K==0) K=K | (getch() << 8);
  302.   if(Chr(K)=='2') K=kbDn;
  303.   if(Chr(K)=='4') K=kbLeft;
  304.   if(Chr(K)=='6') K=kbRight;
  305.   NoAction=FALSE;
  306.   switch(K) {
  307.    case kbLeft:
  308.     if((*Q).X>0) {
  309.      (*Q).Touch=FALSE;
  310.      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];
  311.       if(!(*Q).Touch) {
  312.        TetrisPutForm(Q,TRUE);
  313.        (*Q).X--;
  314.        TetrisPutForm(Q,FALSE);
  315.       }
  316.      }
  317.      break;
  318.    case kbRight:
  319.     if((*Q).X+BlkLength[(*Q).Form][(*Q).Move]-1<9) {
  320.      (*Q).Touch=FALSE;
  321.      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];
  322.      if(!(*Q).Touch) {
  323.       TetrisPutForm(Q,TRUE);
  324.       (*Q).X++;
  325.       TetrisPutForm(Q,FALSE);
  326.      }
  327.     }
  328.     break;
  329.    case kbDn:
  330.     while(TRUE) {
  331.      if(!TetrisUpDateData(Q)) {
  332.       (*Q).Mode=tmGameOver;
  333.       return;
  334.      }
  335.      if((*Q).Ok) break;
  336.     }
  337.     break;
  338.    default:
  339.     NoAction=TRUE;
  340.     break;
  341.   }
  342.   if(NoAction) {
  343.    if((K==kbKeypad5)||(Chr(K)==' ')||(Chr(K)=='5')) {
  344.     (*Q).Touch=FALSE;
  345.     for(I=0;I<=3;I++) {
  346.      XT=(*Q).X+BlkFormatX[(*Q).Form][((*Q).Move+1) & 3][I]; (*Q).Touch=(*Q).Touch || (XT>9);
  347.      (*Q).Touch=(*Q).Touch || (*Q).Tbl[(*Q).Y+BlkFormatY[(*Q).Form][((*Q).Move+1)& 3][I]][XT];
  348.     }
  349.     if(!(*Q).Touch) {
  350.      TetrisPutForm(Q,TRUE);
  351.      (*Q).Move=((*Q).Move+1) & 3;
  352.      TetrisPutForm(Q,FALSE);
  353.     } else {
  354.      (*Q).Touch=FALSE;
  355.      for(I=0;I<=3;I++) {
  356.       XT=(*Q).X;
  357.       if(XT>0) XT--;
  358.       XT+=BlkFormatX[(*Q).Form][((*Q).Move+1) & 3][I]; (*Q).Touch=(*Q).Touch || (XT>9);
  359.       (*Q).Touch=(*Q).Touch || (*Q).Tbl[(*Q).Y+BlkFormatY[(*Q).Form][((*Q).Move+1) & 3][I]][XT];
  360.      }
  361.      if(!(*Q).Touch) {
  362.       TetrisPutForm(Q,TRUE);
  363.       (*Q).X--; (*Q).Move=((*Q).Move+1) & 3;
  364.       TetrisPutForm(Q,FALSE);
  365.      }
  366.     }
  367.    }
  368.     else
  369.    break;
  370.   }
  371.   if((K==kbEsc)||(Chr(K)=='Q')) break;
  372.  } while(TRUE);
  373.  return K;
  374. }
  375.  
  376. unsigned TetrisPlay(TetrisGame *Q) {
  377.  char I,J,H,XT;
  378.  unsigned XJ,YJ,K;
  379.  char NoAction;
  380.  
  381.  textmode(1);
  382.  TetrisRefresh(Q);
  383.  K=0;
  384.  do {
  385.   switch((*Q).Mode) {
  386.    case tmStart:
  387.     TetrisFirstTime(Q);
  388.     break;
  389.    case tmPlay:
  390.     K=TetrisRun(Q);
  391.     break;
  392.    case tmGameOver:
  393.     K=TetrisGameOver(Q);
  394.     break;
  395.   }
  396. _Exit:;
  397.  } while(K==0);
  398.  return K;
  399. }
  400.  
  401. void main() {
  402.  TetrisGame Game;
  403.  TetrisInit(&Game);
  404.  TetrisPlay(&Game);
  405. }

Code source

https://github.com/gladir/turboc_tetris

Dernière mise à jour : Dimanche, le 28 juin 2015