   Tetris Collision Detection Issue
  Please look down for more recent post, I have a differet issue that I can't figure out.Hello,  So far my Tetris clone has been coming a long nicely, however I am having some difficulty with the collision detection system. It works fine for blocks moving down and for the most part moving the shape left and right works. The problem is that when I have a shape such as:0000011000100010and I am controlling a block such as 0100010001000100This is what happens:00x00 >>  0000000x00 >>  000x000xxx >>  000xx00x0x >>  000xx0000x >>  000xxNow, everything aside from that issue works as far as moving the block goes, but I can't seem to figure out a solution to this issue. Can anyone provide some insight?Here is my code thus far:#include <allegro.h>// Used for Timervolatile long speed_counter = 0;// Initialize allegro functions first.void init ();// Timer functionvoid increment_speed_counter();// Setting up the background and start of game.void gameSetup();// Moving the Blocksvoid moveBlock();// Used to draw imagesvoid draw();// Player Controlvoid controlBlock();// Reloads the Block arrayvoid resetBlock();// Clears full row of blocksvoid removeBlock(); // Global variablesint x=0,y=0, r=0, c=0;bool kRight=false,kLeft=false, move=true;// Global constantsconst int WIDTH = 10;const int HEIGHT = 14;// Load in BITMAPs.BITMAP *buffer;BITMAP *background;BITMAP *gBlock;// Game board 0 = empty, 1 = block: this is what is printed to the screen r is height c is width in loopsint gameBoard[HEIGHT][WIDTH] = {{0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,1,1,0,0},    {1,0,1,1,0,0,0,1,0,0},    {1,0,1,0,0,0,0,1,0,0},    {1,1,1,1,1,1,1,1,1,0}};/*int blocBoard[HEIGHT+1][WIDTH+1] = {{1,1,0,0,0,0,0,0,0,0},    {0,1,0,0,0,0,0,0,0,0},    {0,1,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0}};*/// This is a temporary board where the position of the blocks are stored before they go into the Game board.int tempBoard[HEIGHT][WIDTH] = {{0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0}};// This is the current position of the blocks//{4, 14, 24, 34}{1, 11, 21, 31}{4, 5,  14, 15}{1, 2,  11, 12}int block[5][4];int main(){init();gameSetup();  //Game loopwhile(!key[KEY_ESC]){while(speed_counter > 0)   {  controlBlock();speed_counter--;}}destroy_bitmap(buffer);    destroy_bitmap(background);destroy_bitmap(gBlock);return 0;}END_OF_MAIN();void init (){allegro_init();    install_keyboard();install_timer(); // Initialize timerinstall_int_ex(increment_speed_counter, BPS_TO_TIMER(2)); //Set the BPS    set_color_depth(16);    set_gfx_mode(GFX_AUTODETECT_WINDOWED, 1024,768, 0, 0);}void increment_speed_counter(){speed_counter+=1;}END_OF_FUNCTION(increment_speed_counter);void gameSetup(){background = load_bitmap("background.bmp", NULL);buffer = create_bitmap(1024, 768);gBlock = load_bitmap("gBlock.bmp", NULL);    //blit(background, buffer, 0, 0, 0, 0, 1024, 768);resetBlock();for(int r = 0; r <= 13; r++){for(int c = 0; c <= 9; c++){if(gameBoard[r][c] == 1)blit(gBlock, buffer, 0, 0, (50*c)+175, (50*r), 50, 50);}}}/*void moveBlock(){    int x, y;    for(int r = 0; r <= HEIGHT; r++){for(int c = 0; c <= WIDTH; c++){tempBoard[r][c] += gameBoard[r][c];if(tempBoard[r][c] > 0) tempBoard[r][c] = 1;   }}  //if(x <= HEIGHT)j++;   draw();}*/void moveBlock(){    int r, c;move = true; // Clear the original block location    for(int i = 0; i <= 3; i++)    {   r = (block[x] / WIDTH);   c = block[x] % WIDTH;   if(r > 0) gameBoard[r-1][c] = 0;    }    // Collision Detection (can the block move any further)    for(int i = 0; i <= 3; i++)    {   r = (block[x] / WIDTH);   c = block[x] % WIDTH;if(gameBoard[r][c] == 1 || r >= HEIGHT)   {//kLeft = false;//kRight = false;  move = false;  break;   }    }    // If the block is unable to move    if(!move)    {   // Lock the location of the blocks   for(int i = 0; i <= 3; i++)   {  r = (block[x] / WIDTH);  c = block[x] % WIDTH;  gameBoard[r-1][c] = 1;   }   resetBlock();   return;    }    // Moving the Block down.    for(int i = 0; i <= 3; i++)    {   r = (block[x] / WIDTH);   c = block[x] % WIDTH;   gameBoard[r][c] = 1;r++;block[x] = (r * WIDTH) + (c);    }    }void controlBlock(){    int r, c;bool left = false, right=false;    if(key[KEY_RIGHT]) kRight = true;    if(kRight && move)    {   for(int i = 0; i <= 3; i++)   {r = (block[x] / WIDTH)-1;  c = (block[x] % WIDTH);  gameBoard[r][c] = 0;  if(gameBoard[r][c+1] == 0 && gameBoard[r-1][c+1]!=1) right = true;else right = false;   }kRight = false;if(right) { for(int i = 0; i <= 3; i++){  block[x]++;}right=false;}}if(key[KEY_LEFT]) kLeft = true;    if(kLeft && move)    {   for(int i = 0; i <= 3; i++)   {r = (block[x] / WIDTH)-1;  c = (block[x] % WIDTH);  gameBoard[r][c] = 0;  if(gameBoard[r][c-1] == 0 && gameBoard[r-1][c-1]!=1  ) left = true;  else left = false;   }if(left) { for(int i = 0; i <= 3; i++){  block[x]--;}}kLeft = false;    }    moveBlock();    removeBlock();    draw();}void resetBlock(){    x = 4; //(rand()%5); /*  {4, 5,  6,  15},// T-Block{4, 5,  13, 14},// S-Block{4, 14, 24, 25},// L-Block{4, 5,  14, 15},// Sq-Block{4, 14, 24, 34}};*/  // Li-Block    // T-Block    block[0][0] = 4;    block[0][1] = 5;    block[0][2] = 6;    block[0][3] = 15;    // S-Block    block[1][0] = 4;    block[1][1] = 5;    block[1][2] = 13;    block[1][3] = 14;    // L-Block    block[2][0] = 4;    block[2][1] = 14;    block[2][2] = 24;    block[2][3] = 25;    // Sq-Block    block[3][0] = 4;    block[3][1] = 5;    block[3][2] = 14;    block[3][3] = 15;    // Li-Block    block[4][0] = 4;    block[4][1] = 14;    block[4][2] = 24;    block[4][3] = 34;}void removeBlock(){ //unused function next to be implemented.}void draw(){    blit(background, buffer, 0, 0, 0, 0, 1024, 768);    for(int r = 0; r <= HEIGHT-1; r++){for(int c = 0; c <= WIDTH-1; c++){    if(gameBoard[r][c] == 1) blit(gBlock, buffer, 0, 0, (50*c)+175, r*50, 50, 50);   }}    blit(buffer, screen, 0, 0, 0, 0, 1024, 768);}[Edited by - DeFessler on June 9, 2009 9:39:57 AM]
  I didn't look at the code, but I'll tell you how I've handled this in the past (not claiming this is the best approach, but it seemed to work). Whenever a 'move' is requested (i.e. a timer-triggered drop, a player-triggered drop or lateral movement, or a player-triggered rotation):make a copy of the pieceapply the move request (rotation, drop, or lateral movement) to the copycheck the copied piece against the current board matrixif any rows have been completed    adjust the board accordingly and spawn a new pieceelse if the move was a drop    add the piece (not the copy) to the board and spawn a new pieceelse    ignore the move requestend ifNo guarantees that I got the logic exactly right, but I know it was something pretty close to that.   ;  Ok, I have an issue with the rotation that I can't figure out. I have solved all other collision issues however.First let me explain how my code works. I have a multidimensional array that represents that playing field. I have number 1 - 7 placed on that play field to represent the block type and color of the block. I have another array that stores the block shape as a grid:000 001 002 003 004 005 006 007 008 009010 011 012 013 014 015 016 017 018 019020 021 022 023 024 025 026 027 028 029030 031 032 033 034 035 036 037 038 039040 041 042 043 044 045 046 047 048 049050 051 052 053 054 055 056 057 058 059060 061 062 063 064 065 066 067 068 069070 071 072 073 074 075 076 077 078 079080 081 082 083 084 085 086 087 088 089090 091 092 093 094 095 096 097 098 099100 101 102 103 104 105 106 107 108 109110 111 112 113 114 115 116 117 118 119120 121 122 123 124 125 126 127 128 129I used r = block / WIDTH and c = block % WIDTH to get the row and column to place each number on the playfield. I move left and right and rotate by manipulating the original grid number before I use the formula to get the row and column.When I rotate while colliding with a block already placed on the board, it will overwrite that block and remove it kind of like the shape I had would absorb the block or cut through the blocks like a chain saw if I was spinning towards it. I will include and upload of the game so you can see for your self. It is working a little bit but not well enough.You have to be trying to mess up the collision to see it.Here is the code:#include <allegro.h>#include <time.h>unsigned char controlTicks = 0;   // Used for the player input timer.unsigned char downTicks = 0; // Used for the blocks scrolling down timer.void init();  // Initialize allegro functions first.void controlTimer();    // Timer function (could use more work)void downTimer();  // Timer function (could use more work)void gameSetup();  // Setting up the background and start of game.void moveBlock();  // Moving the Blocks and collision detection.void draw();  // Used to draw on to the screen.void controlBlock();    // Player manipulation of blocks as they descend.void resetBlock(); // Reloads the Block array with the default block positions.void removeBlock();// Clears full row of blocksvoid rotateBlock(int rotateNum);  // Rotates blockvoid whatsNext();  // Used to determine the next block.void youWin();  // Under construction/*---Global variables---------------------------------------------------| x is used to determine which block form in the block[][] array to use.|  | tempX is used to store the flip value plus plus x value.    || nextBlock is used in determining what block is next in whatsNext();   || hasRun is used to determine if the what's next function has run yet   |\----------------------------------------------------------------------*/int x = 0, tempX = 0, flip = 0, nextBlock = 0;bool hasRun = false;/* Global constants */const int WIDTH = 10;const int HEIGHT = 14;/* gameBoard[][] is used to store the location of the blocks.   \  The value '1' is a block and '0' is the absense of a block. */int gameBoard[HEIGHT][WIDTH] = {{0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,0,0,0,0,0,0,0},    {0,0,0,1,0,0,0,0,0,0},    {0,0,0,1,0,0,0,0,0,0},    {1,1,1,1,1,1,1,1,1,0}};/* Used to display what the next block will be. */int tempBlock[4][4] = {{0,0,0,0},   {0,0,0,0},   {0,0,0,0},   {0,0,0,0}};/* This holds the 7 original block configurations. */int block[7][4];/* Declare containers for images. */BITMAP *buffer;BITMAP *background;BITMAP *gBlock;BITMAP *bBlock;BITMAP *brBlock;BITMAP *pBlock;BITMAP *puBlock;BITMAP *rBlock;BITMAP *yBlock;int main(){init();gameSetup();  /* Main game loop */while(!key[KEY_ESC]){controlBlock();draw();//youWin();}destroy_bitmap(buffer);    destroy_bitmap(background);destroy_bitmap(gBlock);return 0;}END_OF_MAIN();void init (){allegro_init();    install_keyboard();install_timer();LOCK_VARIABLE(downTicks);    LOCK_FUNCTION(downTimer);    install_int_ex(&downTimer, SECS_TO_TIMER(1));    LOCK_VARIABLE(controlTicks);    LOCK_FUNCTION(controlTimer);    install_int_ex(&controlTimer, MSEC_TO_TIMER(100));    set_color_depth(32);    set_gfx_mode(GFX_AUTODETECT_WINDOWED, 1024,768, 0, 0);}void controlTimer(){controlTicks++;}END_OF_FUNCTION(controlTimer);void downTimer(){downTicks++;}END_OF_FUNCTION(downTimer);void gameSetup(){background = load_bitmap("background.bmp", NULL);buffer = create_bitmap(1024,768);gBlock = load_bitmap("gBlock.bmp", NULL);bBlock = load_bitmap("bBlock.bmp", NULL);brBlock = load_bitmap("brBlock.bmp", NULL);pBlock = load_bitmap("pBlock.bmp", NULL);puBlock = load_bitmap("puBlock.bmp", NULL);rBlock = load_bitmap("rBlock.bmp", NULL);yBlock = load_bitmap("yBlock.bmp", NULL);srand ( (unsigned)time ( 0) );//whatsNext();resetBlock();for(int r = 0; r <= 13; r++){for(int c = 0; c <= 9; c++){if(gameBoard[r][c] == 1)blit(gBlock, buffer, 0, 0, (50*c)+175, (50*r), 50, 50);}}}void moveBlock(){    while(downTicks > 0)    {    /* Initialize variables */   int r = 0, c = 0;   /* Allowing block to move again. */    bool move = true;    /* Clear the original block location */   for(int i = 0; i <= 3; i++)   {  r = (block[x] / WIDTH);  c = (block[x] % WIDTH);  if(r > 0) gameBoard[r-1][c] = 0;   }   /* Collision Detection (can the block move any further). */   for(int i = 0; i <= 3; i++)   {  r = (block[x] / WIDTH);  c = (block[x] % WIDTH);  /* If the block form encounters another block, stop moving. */    if(gameBoard[r][c] >= 1 || r >= HEIGHT)  { move = false; break;  }   }   /* If the block is unable to move. */   if(!move)   {  /* Set permanent location of block. */  for(int i = 0; i <= 3; i++)  { r = (block[x] / WIDTH); c = (block[x] % WIDTH); if(r >0)gameBoard[r-1][c] = x+1;  } removeBlock(); // check for any completed rows, remove them, move the grid down,  resetBlock();  // and then reset the block array to default.  flip = 0;    return;   }  /* Continually move the block form currently stored in block[][]. */   for(int i = 0; i <= 3; i++)   {  r = (block[x] / WIDTH);  c = (block[x] % WIDTH);  if(c >= 0)gameBoard[r][c] = x+1;r ++;    block[x] = (r * WIDTH + c);   } downTicks--;    }}/* Player control of the block. */void controlBlock(){    while(controlTicks > 0)    {    /* Initalize and reset variables */   int r = 0, c = 0;   bool  kUp = false, kRight = false, kLeft = false, kDown = false;   bool  cUp = true, cRight=true, cLeft = true, cDown=true;    /* Each direction also does a little bit of collision detecion  \  to insure that a block is not in the way before it can move. */    if(key[KEY_RIGHT]) kRight = true;   if(kRight)   {    /* Clear block first. */  for(int i = 0; i <= 3; i++)  {    r = (block[x] / WIDTH)-1; c = (block[x] % WIDTH);    if(r >=0)gameBoard[r][c] = 0;  }    /* Check for collision. */  for(int i = 0; i <= 3; i++)  {    r = (block[x] / WIDTH)-1; c = (block[x] % WIDTH);if(gameBoard[r][c+1] >= 1 || c >= WIDTH-1) cRight = false;  }    /* If nothing collides move peice. */    if(cRight){for(int i = 0; i <= 3; i++)    { block[x]++;r = (block[x] / WIDTH)-1;    c = (block[x] % WIDTH);if(r >= 0) gameBoard[r][c] = x+1;    }    }    }    if(key[KEY_LEFT]) kLeft = true;   if(kLeft)   {    /* Clear block first. */  for(int i = 0; i <= 3; i++)  {    r = (block[x] / WIDTH)-1; c = (block[x] % WIDTH);    if(r >= 0)gameBoard[r][c] = 0;  }    /* Check for collision. */  for(int i = 0; i <= 3; i++)  {    r = (block[x] / WIDTH)-1; c = (block[x] % WIDTH); if(gameBoard[r][c-1] >= 1 || c <= 0 ) cLeft = false;  }    /* If nothing collides move peice. */    if(cLeft){for(int i = 0; i <= 3; i++)    { block[x]--;r = (block[x] / WIDTH)-1;    c = (block[x] % WIDTH);if(r >= 0)gameBoard[r][c] = x+1;    }    }   }tempX = x + flip; //tempX is sent to rotate funtion for flip number./* If the UP key is pressed, activate rotate. */   if(key[KEY_UP]) kUp = true;   if(kUp)   {    /* Clear block first. */  for(int i = 0; i <= 3; i++)  {    r = (block[x] / WIDTH)-1; c = (block[x] % WIDTH);    if(r >= 0)gameBoard[r][c] = 0;  }    /* Check for collision. */  for(int i = 0; i <= 3; i++)  {    r = (block[x] / WIDTH)-1; c = (block[x] % WIDTH); if(gameBoard[r+1][c] == 1 || gameBoard[r+1][c+1] == 1 || gameBoard[r][c+1] == 1 || gameBoard[r+1][c-1] == 1|| gameBoard[r][c-1] == 1 || c <= 0 && i == 1 || c >= WIDTH-1 && i == 1) {cUp = false;}if( x == 6 && c >= WIDTH-2 && i == 2 && flip < 6) cUp = false;  }    /* If nothing collides move peice. */    if(cUp){rotateBlock(tempX);    for(int i = 0; i <= 3; i++)    {  r = (block[x] / WIDTH)-1;    c = (block[x] % WIDTH);if(r >= 0)gameBoard[r][c] = x+1;    }    }   }/* If the down key is pressed, move down faster. */    if(key[KEY_DOWN]) kDown = true;   if(kDown)   {    // Clear block first.  for(int i = 0; i <= 3; i++)  {    r = (block[x] / WIDTH)-1; c = (block[x] % WIDTH);    if(r >= 0) gameBoard[r][c] = 0;  }    // Check for collision.  for(int i = 0; i <= 3; i++)  {    r = (block[x] / WIDTH)-1; c = (block[x] % WIDTH); if(gameBoard[r+1][c] >= 1 || r >= HEIGHT-1) cDown = false;  }    // If nothing collides move peice.    if(cDown){for(int i = 0; i <= 3; i++)    { block[x] += 10;r = (block[x] / WIDTH)-1;    c = (block[x] % WIDTH);if(r >= 0)gameBoard[r][c] = x+1;    }    }   }/* If the block can not move in either direction, make sure it's drawn. */if(!cRight || !cLeft || !cDown || !cUp )    {  for(int i = 0; i <= 3; i++)  { r = (block[x] / WIDTH)-1; c = (block[x] % WIDTH); if(r >= 0)gameBoard[r][c] = x+1;   }}   controlTicks--;    }moveBlock(); // After player input check is finished move the block   }// Clears row or rows when full.void removeBlock(){    /* Initialize variables */    int nRow = 0, rRow[4], i=0;    bool shift=false;    for(i = 0; i <= 4; i++)    {   rRow = 0;    }    i=0;/* Find all gameBoard rows that have 10 blocks and | save the row number to an array. Then allow |\ shift condition if any row has 10 blocks.  */    for(int r = 0; r <= HEIGHT-1; r++) {for(int c = 0; c <= WIDTH-1; c++){  if(gameBoard[r][c] >= 1)nRow += 1;  if(nRow >= 10)   { rRow = r; nRow = 0; if(i < 3) i++; shift = true;  }}/* Reset the number in the row to 0 if it's \ not a complete line. */   if(nRow < 10) nRow = 0;    }/* If any row has ten blocks take the value you in \ that row and move all of the above block down.  */    if(shift)    {   for(int i = 0; i <= 3; i++)   {for(int r = rRow; r >0; r--){for(int c = 0; c <= WIDTH-1; c++){if(r > 0)gameBoard[r][c] = gameBoard[r-1][c];}}   }}}/* Resets block shape positions for use again and picks a new block. */void resetBlock(){if(!hasRun)x = rand()%7;else x = nextBlock;/*  {4, 5,  6,  15},// T-Block{4, 5,  13, 14},// S-Block{4, 14, 24, 25},// L-Block{4, 5,  14, 15},// Sq-Block{4, 14, 24, 34}};*/  // Li-Block    // T-Block    block[0][0] = 13;    block[0][1] = 14;    block[0][2] = 15;    block[0][3] = 4;    // S-Block    block[1][0] = 5;    block[1][1] = 4;    block[1][2] = 14;    block[1][3] = 13;// Z-Block    block[2][0] = 3;    block[2][1] = 4;    block[2][2] = 14;    block[2][3] = 15;    // L-Block    block[3][0] = 4;    block[3][1] = 14;    block[3][2] = 24;    block[3][3] = 25;    // 7-Block    block[4][0] = 4;    block[4][1] = 14;    block[4][2] = 24;    block[4][3] = 23;    // Sq-Block    block[5][0] = 4;    block[5][1] = 5;    block[5][2] = 14;    block[5][3] = 15;    // Li-Block    block[6][0] = 4;    block[6][1] = 14;    block[6][2] = 24;    block[6][3] = 34;    whatsNext();}void rotateBlock( int rotateNum){int r = 0, c = 0;    // Clear block first.   for(int i = 0; i <= 3; i++)   {r = (block[x] / WIDTH)-1;  c = (block[x] % WIDTH);if(r >=0)gameBoard[r][c] = 0;   }switch(rotateNum){case 0:// T-Block (First Right)   block[0][0] -= 9;   block[0][1] += 0;   block[0][2] += 9;   block[0][3] += 11;flip += 7;break;case 1:    // S-Block{5, 4,  14, 13}, block[1][0] -= 11;block[1][1] += 0;block[1][2] -= 9;block[1][3] += 2;flip += 9; break;case 2:    // Z-Block{3, 4,  14, 15}, block[2][0] -= 9;block[2][1] -= 0;block[2][2] -= 1;block[2][3] -= 12;flip += 9; break;case 3:// L-Block {4, 14, 24, 25},block[3][0] += 11;block[3][1] -= 0;block[3][2] -= 11;block[3][3] -= 2;flip += 9;break;case 4:// 7-Blockblock[4][0] += 11;block[4][1] += 0;block[4][2] -= 11;block[4][3] -= 20;   flip += 11;   break;case 5:    // Sq-Blockflip = 0; break;case 6:    // Li-Block (Horizonal)   block[6][0] += 9;   block[6][1] -= 0;   block[6][2] -= 9;   block[6][3] -= 18;flip += 12;break;    case 7:    // T-Block (Second Right)   block[0][0] += 11;   block[0][1] += 0;   block[0][2] -= 11;   block[0][3] += 9;flip += 1;break;case 8:    // T-Block   block[0][0] += 9;   block[0][1] += 0;   block[0][2] -= 9;   block[0][3] -= 11;flip += 1;break;case 9:    // T-Block   block[0][0] -= 11;   block[0][1] += 0;   block[0][2] += 11;   block[0][3] -= 9;flip -= 9;break;case 10:    // S-Blockblock[1][0] += 11;block[1][1] += 0;block[1][2] += 9;block[1][3] -= 2;flip -= 9; break;case 11:    // Z-Block{3, 4,  14, 15}, block[2][0] += 9;block[2][1] += 0;block[2][2] += 1;block[2][3] += 12;flip -= 9; break;case 12:// L-Block {4, 14, 24, 25},block[3][0] += 9;block[3][1] -= 0;block[3][2] -= 9;block[3][3] -= 20;flip += 1;break;case 13:// L-Block {4, 14, 24, 25},block[3][0] -= 11;block[3][1] -= 0;block[3][2] += 11;block[3][3] += 2;flip += 1;break;case 14:// L-Block {4, 14, 24, 25},block[3][0] -= 9;block[3][1] -= 0;block[3][2] += 9;block[3][3] += 20;flip -= 11;break;    case 15:// 7-Blockblock[4][0] += 9;block[4][1] += 0;block[4][2] -= 9;block[4][3] += 2;   flip += 1;   break;    case 16:// 7-Blockblock[4][0] -= 9;block[4][1] += 0;block[4][2] += 9;block[4][3] += 20;   flip += 1;   break;    case 17:// 7-Blockblock[4][0] -= 11;block[4][1] += 0;block[4][2] += 11;block[4][3] -= 2;   flip -= 13;   break;case 18:    // Li-Block (Vertical)   block[6][0] -= 9;   block[6][1] += 0;   block[6][2] += 9;   block[6][3] += 18;flip -= 12;break;}}void whatsNext(){    int r=0, c=0;    hasRun = true;for(r = 0; r <= 3; r++)    {   for(c = 0; c <= 3; c++)   { tempBlock[r][c] = 0;   }    }nextBlock = rand()%7;    for(int i = 0; i <= 3; i++)    {   r = (block[nextBlock] / WIDTH)+1;   c = (block[nextBlock] % WIDTH)-6;   tempBlock[r][c] = nextBlock+1;    }}void youWin(){int value = 0;bool val = false;   for(int c = 0; c <= WIDTH-1; c++){for(int r = 0; r <= HEIGHT-1; r++){if(gameBoard[r][c] == 1)value++;if(value >= HEIGHT) val = true;   }value = 0;}   if(val){for(int r = 0; r <= HEIGHT-1; r++){for(int c = 0; c <= WIDTH-1; c++){gameBoard[r][c] = 0;}textout_ex(buffer, font, "You Lose!", 10, 10, makecol(0, 0, 255), -1);}rest(5000);}}void draw(){    blit(background, buffer, 0, 0, 0, 0, 1024,768);    for(int r = 0; r <= HEIGHT-1; r++){for(int c = 0; c <= WIDTH-1; c++){    if(gameBoard[r][c] == 1) blit(gBlock, buffer, 0, 0, (50*c)+175, r*50, 50, 50);if(gameBoard[r][c] == 2) blit(bBlock, buffer, 0, 0, (50*c)+175, r*50, 50, 50);if(gameBoard[r][c] == 3) blit(brBlock, buffer, 0, 0, (50*c)+175, r*50, 50, 50);if(gameBoard[r][c] == 4) blit(pBlock, buffer, 0, 0, (50*c)+175, r*50, 50, 50);if(gameBoard[r][c] == 5) blit(puBlock, buffer, 0, 0, (50*c)+175, r*50, 50, 50);if(gameBoard[r][c] == 6) blit(rBlock, buffer, 0, 0, (50*c)+175, r*50, 50, 50);if(gameBoard[r][c] == 7) blit(yBlock, buffer, 0, 0, (50*c)+175, r*50, 50, 50);   }}    for(int r = 0; r <= 3; r++)    {   for(int c = 0; c <= 3; c++)   {  if(tempBlock[r][c] == 1) blit(gBlock, buffer, 0, 0, (50*c)+700, (r*50)+225, 50, 50);if(tempBlock[r][c] == 2) blit(bBlock, buffer, 0, 0, (50*c)+700, (r*50)+225, 50, 50);if(tempBlock[r][c] == 3) blit(brBlock, buffer, 0, 0, (50*c)+700, (r*50)+225, 50, 50);if(tempBlock[r][c] == 4) blit(pBlock, buffer, 0, 0, (50*c)+700, (r*50)+225, 50, 50);if(tempBlock[r][c] == 5) blit(puBlock, buffer, 0, 0, (50*c)+700, (r*50)+225, 50, 50);if(tempBlock[r][c] == 6) blit(rBlock, buffer, 0, 0, (50*c)+700, (r*50)+225, 50, 50);if(tempBlock[r][c] == 7) blit(yBlock, buffer, 0, 0, (50*c)+700, (r*50)+225, 50, 50);   }    }    blit(buffer, screen, 0, 0, 0, 0, 1024,768);}http://defessler.jeremycrapsey.com/ontheblocks/ontheblocks.zip   