one last problem with tetris

Started by
4 comments, last by DevFred 15 years, 9 months ago
So i am having 1 last problem with tetris and that is about detecting a full row and deleting it and moving the rest of the rows down. I know the functions that delete the row and move the rows down work and the function that checks if a row is full works but the problem is its not checking the correct rows. I have it set up to check 1 row and then if its full erase it move the rows down and check the next row down. I have it check 4 rows like this because that is the max number of rows that can fill up when 1 piece lands. The problem is it checks the rows the wrong way. Say i have this piece as the final piece down. 1 1 1 1 so each 1 is at a different row as illustrated by this: row 12: 1 row 13: 1 row 14: 1 row 15: 1 the bottom 1 is at the last row of the board and it gets filled then it should check line 15, 14, 13, 12 because that would go from the bottom of the piece to the top but instead it starts at 12 and counts up from that so it checks lines 12, 11, 10, 9. So if the filled lines are below 12 then they never get checked In my function i have it go y = y-1 if the row is not full and i tried changing that to count up but it messes up the collision detection. Anyway i am going to post the code here because i have no idea what i would do to go about fixing this problem. Thanks.
"cpp"]
#include <cstdlib>
#include <iostream>
#include <ctime>
using namespace std;


#define MIDDLE_X 6
#define MIDDLE_Y 6
#define TRUE 1
#define FALSE 0

/************************************************
 *           function prototypes
 ************************************************/

void moveRowsDown(void);

/************************************************
 *           main game board
 ************************************************/

int gameBoard[17][17] = {{8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
				  		 {8, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
						 {8, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
						 {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
						 {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
						 {8, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
						 {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
						 {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
						 {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
						 {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
						 {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
						 {8, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
						 {8, 0, 0, 0, 4, 4, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 8},
						 {8, 0, 0, 0, 0, 4, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 8},
						 {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
                         {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
                         {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
						};

// 0 out gameBoard()
void resetGameBoard()
{
   for (int row = 1; row < 16; row++)
   {
      for (int col = 1; col < 16; col++)
          gameBoard[row][col] = 0;
   } // end for
} // end resetGameBoard

void displayGameBoard()
{
    for (int row = 0; row < 17; row++)
    {
       for (int col = 0; col < 17; col++)
          cout << gameBoard[row][col];
       cout << endl;
    } // end for
} // end displayGameBoard

/************************************************
 *           end main game board
 ************************************************/

/************************************************
 *         array that holds all the shapes
 ************************************************/

int shapeArray[7][4][4][4] =
{
    {
        {
            {0, 0, 1, 0},
            {0, 0, 1, 0},
            {0, 0, 1, 0},
            {0, 0, 1, 0}
        },
        {
            {0, 0, 0, 0},
            {0, 0, 0, 0},
            {1, 1, 1, 1},
            {0, 0, 0, 0}
        },
        {
            {0, 1, 0, 0},
            {0, 1, 0, 0},
            {0, 1, 0, 0},
            {0, 1, 0, 0}
        },
        {
            {0, 0, 0, 0},
            {1, 1, 1, 1},
            {0, 0, 0, 0},
            {0, 0, 0, 0}
        }
    }
    ,
    {
        {
            {0, 0, 0, 0},
            {0, 2, 2, 2},
            {0, 0, 2, 0},
            {0, 0, 0, 0}
        },
        {
            {0, 0, 0, 0},
            {0, 0, 2, 0},
            {0, 2, 2, 0},
            {0, 0, 2, 0}
        },
        {
            {0, 0, 0, 0},
            {0, 2, 0, 0},
            {2, 2, 2, 0},
            {0, 0, 0, 0}
        },
        {
            {0, 2, 0, 0},
            {0, 2, 2, 0},
            {0, 2, 0, 0},
            {0, 0, 0, 0}
        }
    }
    ,
    {
        {
            {0, 0, 0, 0},
            {0, 3, 3, 0},
            {0, 3, 3, 0},
            {0, 0, 0, 0}
        },
        {
            {0, 0, 0, 0},
            {0, 3, 3, 0},
            {0, 3, 3, 0},
            {0, 0, 0, 0}
        },
        {
            {0, 0, 0, 0},
            {0, 3, 3, 0},
            {0, 3, 3, 0},
            {0, 0, 0, 0}
        },
        {
            {0, 0, 0, 0},
            {0, 3, 3, 0},
            {0, 3, 3, 0},
            {0, 0, 0, 0}
        }
    }
    ,
    {
        {
            {0, 0, 0, 0},
            {0, 4, 4, 4},
            {0, 0, 0, 4},
            {0, 0, 0, 0}
        },
        {
            {0, 0, 0, 0},
            {0, 0, 4, 0},
            {0, 0, 4, 0},
            {0, 4, 4, 0}
        },
        {
            {0, 0, 0, 0},
            {4, 0, 0, 0},
            {4, 4, 4, 0},
            {0, 0, 0, 0}
        },
        {
            {0, 4, 4, 0},
            {0, 4, 0, 0},
            {0, 4, 0, 0},
            {0, 0, 0, 0}
        }
    }
    ,
    {
        {
            {0, 0, 0, 0},
            {0, 5, 5, 0},
            {0, 0, 5, 5},
            {0, 0, 0, 0}
        },
        {
            {0, 0, 0, 0},
            {0, 0, 5, 0},
            {0, 5, 5, 0},
            {0, 5, 0, 0}
        },
        {
            {0, 0, 0, 0},
            {5, 5, 0, 0},
            {0, 5, 5, 0},
            {0, 0, 0, 0}
        },
        {
            {0, 0, 5, 0},
            {0, 5, 5, 0},
            {0, 5, 0, 0},
            {0, 0, 0, 0}
        }
    }
    ,
    {
        {
            {0, 0, 0, 0},
            {0, 0, 6, 6},
            {0, 6, 6, 0},
            {0, 0, 0, 0}
        },
        {
            {0, 0, 0, 0},
            {0, 6, 0, 0},
            {0, 6, 6, 0},
            {0, 0, 6, 0}
        },
        {
            {0, 0, 0, 0},
            {0, 6, 6, 0},
            {6, 6, 0, 0},
            {0, 0, 0, 0}
        },
        {
            {0, 6, 0, 0},
            {0, 6, 6, 0},
            {0, 0, 6, 0},
            {0, 0, 0, 0}
        }
    }
    ,
    {
        {
            {0, 0, 0, 0},
            {0, 7, 7, 7},
            {0, 7, 0, 0},
            {0, 0, 0, 0}
        },
        {
            {0, 0, 0, 0},
            {0, 7, 7, 0},
            {0, 0, 7, 0},
            {0, 0, 7, 0}
        },
        {
            {0, 0, 0, 0},
            {0, 0, 7, 0},
            {7, 7, 7, 0},
            {0, 0, 0, 0}
        },
        {
            {0, 7, 0, 0},
            {0, 7, 0, 0},
            {0, 7, 7, 0},
            {0, 0, 0, 0}
        }
    }
// etc for the other 4 shapes
};

/************************************************
 *        end array that holds all the shapes
 ************************************************/

int shape;
int rotation;
int xPos;
int yPos;
int collideDown = FALSE;
int score;
int level;
int lines;
bool gameOver = false;

// put the piece on the gameBoard
void putPieceOnBoard()
{
    for (int r = 0; r < 4; ++r)
        for (int c = 0; c < 4; ++c)
            if (shapeArray[shape][rotation][r][c] != 0)
                gameBoard[yPos+r][xPos+c] = shape+1;
} // end putPieceOnBoard

void removePieceFromBoard()
{
    for (int r = 0; r < 4; ++r)
        for (int c = 0; c < 4; ++c)
            if (shapeArray[shape][rotation][r][c] != 0)
                gameBoard[yPos+r][xPos+c] = 0;
} // end removePieceFromBoard

// check if there is a collision
bool checkCollision()
{
    for (int r = 0; r < 4; ++r)
        for (int c = 0; c < 4; ++c)
        {
            if ( (gameBoard[r+yPos][c+xPos] != 0) && (shapeArray[shape][rotation][r][c] != 0) )
                // There's overlap
                return true;
        } // end for

    return false;
} // end checkCollision

/*
// this returns the next random shape
void nextShape()
{
    shape = rand() % 7;
    //return shape;
} // end nextShape
*/

// gets the next piece, sets rotation and x and y cordinates
void nextShape()
{
    shape = rand() % 7;
    rotation = 0;
    xPos = MIDDLE_X; //or wherever the middle of your board is
    yPos = 0;
    if (checkCollision())
    {
        gameOver = true;
        cout << "The game is over!\n";
    } // end if
} // end nextPiece


// this returns the next rotation
// it sets the rotation to either a 0, 1, 2, or 3
void rotate()
{
    rotation = (rotation + 1) & 3;
    if (checkCollision())
        rotation = (rotation - 1) & 3;
} // end rotate

// try to move left, move back if you can't
void tryToMoveLeft()
{
    --xPos;
    if (checkCollision())
        ++xPos;
} // end tryToMoveLeft

// try to move right, move back if you can't
void tryToMoveRight()
{
    ++xPos;
    if (checkCollision())
        --xPos;
} // end tryToMoveRight

// try to move down, move back if you can't
void tryToMoveDown()
{
    ++yPos;
    if (checkCollision())
    {
        --yPos;
        collideDown = TRUE;
    } // end if
} // end tryToMoveDown

// rotate if you can, if you can't go back to old rotation
void tryToRotate()
{
    int oldRotation = rotation;
    rotation = (rotation + 1) & 3;
    if (checkCollision())
    {
        rotation = oldRotation;
        cout << "inside this if statement\n";
     } // end if
     cout << "the rotation inside the function is " << rotation << endl;
} // tryToRotate

// return true if the row is full and needs to be deleted, false otherwise
bool isRowFull(int row)
{
   int rowFull = 0;
   for (int col = 0; col < 17; col++)
   {
      if (gameBoard[row][col] != 0)
      {
          rowFull++;
          cout << "Row full is " << rowFull << endl;
          cout << "row is : " << row << endl;
       } // end if
   } // end for
   if (rowFull == 17)
   {
       cout << "row is full\n";
       return true;
    } // end if
   else
   {
      cout << "row is not full\n";
      return false;
   } // end else
} // end isRowFull

// test the row full function fill up a row with 1's and see if it returns true;
void fillRow(int row)
{
   for (int col = 1; col < 16; col++)
   {
       gameBoard[row][col] = 1;
   } // end for
} // end fillRow

// unfill 1 row
void unFillOneRow(int row)
{
    for (int col = 1; col < 16; col++)
        gameBoard[row][col] = 0;
} // end unFillOneRow
      
void moveRowsDown(int n)
{
   int row;
   for (row = n; row > 1; row--)
   {
       for (int col = 1; col < 16; col++)
       {
           //cout << "the row is : " << row << endl;
            //cout << "the col is : " << col << endl;
           gameBoard[row][col] = gameBoard[row-1][col];
       } // end for
   } // end for
   cout << "the row is " << row << endl;
   // this sets the first row to 0's
   unFillOneRow(1);
} // end moveRowsDown

void arrangeRows(int y)
{
   for (int i = 0; i < 4; i++)
   {
       if (isRowFull(y))
       {
            moveRowsDown(y);
            lines++;
            cout << "line count is " << lines << endl;
            cout << "level is " << level << endl;
       } // end if
       else
         y = y - 1;
   } // end for
} // end arrangeRows

// increment level if it needs to be
void increaseLevel()
{
   if (lines = 10)
      level = level + 1;
} // end increaseLevel

int main(int argc, char *argv[])
{
    srand((unsigned)time(0));
    xPos = MIDDLE_X;
    yPos = 0;
    char input;
    //nextShape();
    //rotation = 0;
    removePieceFromBoard();
    nextShape();
    rotation = 0;
    xPos = MIDDLE_X;
    yPos = 0;
    cout << "the rotation is = " << rotation << endl;
    char move;

    resetGameBoard();

    while (true)
    {
        putPieceOnBoard();
        displayGameBoard();
        cout << "enter a move char\n";
        cin >> move;
        if (move == 'w')
        {
            removePieceFromBoard();
            tryToRotate();
            //rotate();
            cout << "the rotation = " << rotation;
            putPieceOnBoard();
            cout << endl << endl;
            displayGameBoard();
             cout << endl << endl;
         } // end if
         else if (move == 'a')
         {
             removePieceFromBoard();
             tryToMoveLeft();
             putPieceOnBoard();
             cout << endl << endl;
            displayGameBoard();
             cout << endl << endl;
         } // end if
         else if (move == 's' && collideDown == FALSE)
         {
             removePieceFromBoard();
             tryToMoveDown();
             putPieceOnBoard();
            cout << endl << endl;
            displayGameBoard();
             cout << endl << endl;
         } // end else if
         else if (move == 's' && collideDown == TRUE)
         {
            // do all the level and line checks in here
            cout << "yPos = " << yPos << endl;
            arrangeRows(yPos);
            nextShape();
            rotation = 0;
            xPos = MIDDLE_X;
            yPos = 0;
            collideDown = FALSE;
            continue;
          } // end else if
         else if (move == 'd')
          {
             removePieceFromBoard();
             tryToMoveRight();
             putPieceOnBoard();
            cout << endl << endl;
            displayGameBoard();
             cout << endl << endl;
          } // end else if
} // end while
    system("PAUSE");
    return EXIT_SUCCESS;
} // end main


I have tried to just fill up set rows and then pass the row that i know is full and then all of this works but its when i have to pass in the row that it does not work right.
Advertisement
The way I do is it I check each line to see if it is full. Once I find a full line I delete the line and move all the above lines down 1 unit. Then I call the clear lines function again returning 1 + the recursive call. If no lines are full I return 0. This will always clear all full lines and returns how many were cleared.
it has to be something with these functions. It is not counting the y right or something

function that re-arranges the row if it is full
[source="cpp"]void arrangeRows(int y){   for (int i = 0; i < 4; i++)   {        cout << "Y = " << y << endl;       if (isRowFull(y))       {            cout << "Y = " << y << endl;            moveRowsDown(y);            lines++;            cout << "line count is " << lines << endl;            cout << "level is " << level << endl;       } // end if       else         y = y - 1;   } // end for} // end arrangeRows


I think it is in the above function something with the i and 4 and y because i never change y there just if its an else and it counts down or i need y to be equal to the last row not the first or if it is equal to the first somehow check the rows down from it without saying y = y+1 because that messes up the collision test or maybe the collision test gets messed up because it erases the last row of 8's that signals the end of the board.

Function that moves the rows down 1
[source="cpp"]void moveRowsDown(int n){   int row;   for (row = n; row > 1; row--)   {       for (int col = 1; col < 16; col++)       {           //cout << "the row is : " << row << endl;            //cout << "the col is : " << col << endl;           gameBoard[row][col] = gameBoard[row-1][col];       } // end for   } // end for   cout << "the row is " << row << endl;   // this sets the first row to 0's   unFillOneRow(1);} // end moveRowsDown


Function that fills 1 row with 0's to empty it. This is used to clear the top row
[source="cpp"]// unfill 1 rowvoid unFillOneRow(int row){    for (int col = 1; col < 16; col++)        gameBoard[row][col] = 0;} // end unFillOneRow


Function that returns true if a row is full false if not
[source="cpp"]// return true if the row is full and needs to be deleted, false otherwisebool isRowFull(int row){   int rowFull = 0;   for (int col = 0; col < 17; col++)   {      if (gameBoard[row][col] != 0)      {          rowFull++;          cout << "Row full is " << rowFull << endl;          cout << "row is : " << row << endl;       } // end if   } // end for   if (rowFull == 17)   {       cout << "row is full\n";       return true;    } // end if   else   {      cout << "row is not full\n";      return false;   } // end else} // end isRowFull
I did it the same way. As I remember, my grid class (that's what I called the area that the pieces "landed" in) didn't care what the shapes were after the player lost control of a piece...it became some number of squares. It was a matrix (n x m array) of pointers that were NULL if no piece of a tetrad was in a space, or a pointer to the appropriately-colored graphic. Then I just checked each row to see that there was at least one null pointer in it. If not, I flagged it...then at the end of the check, I cleared those rows.
ok i figured it out i just go through all the rows from top to bottom instead of trying to figure out which is what with only 4 rows. Thanks.
Quote:Original post by cwl157
The problem is it checks the rows the wrong way.

In my function i have it go y = y-1 if the row is not full and i tried changing that to count up but it messes up the collision detection.

Well, checking from top to bottom is even easier, since you don't need the else. Tell me if this fixes your problem:
void arrangeRows(int y){   for (int i = 4; i; --i, ++y)   {       if (isRowFull(y))       {           moveRowsDown(y);           ++lines;       }   }}

This topic is closed to new replies.

Advertisement