Thread: how to make sure that my blocks stop when it reaches the border? tetris

  1. #1
    Registered User
    Join Date
    May 2013
    Posts
    59

    how to make sure that my blocks stop when it reaches the border? tetris

    I've got some ideas on how to stop the blocks but i do not know how to put them into codes. because moving to the left, i have to -cln so when the cln reach -1, i'll +1 to the cln again so that it remains at the same place. i've been racking my brains on this but still cant come up with the codes. I also need some help on the rotating.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    
    
    #define ROW 15
    #define COLUMN 15
    
    
    void gameboard(char b[ROW][COLUMN])
    {
        int r, c;
     
         
        for(r = -1; r <= ROW; r++)
        {
            for(c = -1; c  <= COLUMN; c++)
            {
              	  
    	
                if(r == -1 || r == ROW || c == -1 || c == COLUMN)
                {    
    				putchar('*');	 	 	 
    				putchar(' ');
    			}
                else
    			{
                    putchar(b[r][c]);
    				putchar(' ');
    			}
            }
     
            putchar('\n'); 
        }
    }
    	
    void assignblocks(char b[ROW][COLUMN])
    {
    	int rol,col;
    	srand( (unsigned) time(NULL));
    	
    	for (col = 6;col<9;col++)
    	
    	{
    		b[0][col] = rand()%2;
    		if (b[0][col] == 1)
    		{
    		b[0][col]= 'X';
    		}
    	
    	}
    	printf("\n");		
    	
    	for (col = 6;col<9;col++)
    	{
    		b[1][col] = rand()%2;
    		if (b[1][col] == 1)
    		{
    		b[1][col]= 'X';
    		
    		}	 	 
    	}
    	b[1][7]='X';	
    	printf("\n");		
    		
    	for (col = 6;col<9;col++)
    	{
    		b[2][col] = rand()%2;
    		if (b[2][col] == 1)
    		{
    		b[2][col] = 'X';
    		}
    	}
    }
    
    
    void movement (char b[ROW][COLUMN])
    {	
    	char input;
    	int rw,cln;
    	
    	do
    	{
    		fflush(stdin);
    		printf("\nEnter your next move: ");
    		scanf("%c",&input);
    	
    		if (input == '4') 
    		{
    			for (rw=0;rw<16;rw++)
    				for (cln=0;cln<16;cln++)
    				if (b[rw][cln] == 'X')
    				{
    					b[rw][cln-1]='X';
    					b[rw][cln]=' ';
    				}	    			
    		}
    			
    		if (input == '6') 
    			for (rw=15;rw>-1;rw--)
    				for (cln=15;cln>-1;cln--)
    				if (b[rw][cln] == 'X')
    				{
    					b[rw][cln+1]='X';
    					b[rw][cln]=' ';	   	   
    				}
    					
    		if (input == '8') 
    			for (rw=15;rw>-1;rw--)
    				for (cln=15;cln>-1;cln--)
    				
    				if (b[rw][cln] == 'X')
    				{
    					b[rw+1][cln]='X';
    					b[rw][cln]=' ';	   	   
    				}	
    		if (input == '2') 
    			{
    		 	 	 	 	 	 
    			}
    		 	   
    
    
    					
    	}while(input != '2' && input != '4' && input != '6' && input != '8');
    		
    }	   	   	   	   
    
    
    int main(void)
    {
    	char box[ROW][COLUMN];
    	char name[20] ="AAA" ;
    	int x,y;
    	bool end = false;
    
    
    	printf("*************Tetris Game*************\n");
    	printf("Please Enter Player Name: ");
    	scanf("%s", &name);
    	printf("Player Name:%s\n", name);
    		
    	for(x=0; x<16; x++)
    	{
    		for(y=0; y<16; y++)
    		{
    			box[x][y] = ' ';
    		}
    	}
    
    
    	assignblocks(box);
    
    
    	do
    	{
    	printf("\n\n*************Tetris Game*************\n");
    	printf("Player Name:%s\n", name);
    	
    	gameboard(box);
    		
    	movement(box);
    
    
    	}while (end == false);
    
    
    	return 0;
    }

  2. #2
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    Stop doing this

    Code:
    fflush(stdin);
    now!!! It's undefined behavior. Instead use this for your scanf

    Code:
    scanf(" %c",&input); /* Note the space before the %c */
    which will ignore the white space (i.e., the newline character) left in the input buffer.

  3. #3
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Let me start by saying that I admire your enthusiasm. I don't want to discourage you at all, but Tetris is not a trivial game to program. I will say that it is unlikely that you will create a Tetris game with your current code. Visually, you're not off to a bad start, but structurally, your code is not conducive to the developmental growth required to implement all the nuances of a Tetris game.

    For instance, the pieces should be a separate entity from the game board. As it stands, the game board array is just updated with X's, and piece movement consists of checking the current game board array and changing element values under certain conditions. What happens when the piece hits the bottom? How are you going to "store" the stopped piece and create a new one at the top, with this code implementation?

    Each piece that enters the game board should be represented by an object separate from the game board (structures would be good for this task). It should contain the X/Y coordinates of each piece segment in the piece. There should be a separate function to "blit" the piece, based on the coordinates of its segments, onto a copy of the game board. The actual game board array should not be updated, but merely a copy of it for printing. This way, when the piece moves, you don't need to update the game board array - you merely update the coordinates of the piece segements and "blit" it again before printing. Only when a piece stops should it be added to the actual game board array, because now it is "part of the background."

    With this setup, when a move is entered, you can just test the X/Y coordinate of each segment of the current piece to see if the move is allowed (i.e. to see if the piece reaches the left, right, or bottom border). There should be no need to reference the game board array for this kind of test.

    Also, rotating a piece with your current code would be a hideous nightmare to implement, way more difficult than it's worth. Again, with each piece as a "separate entity," you only have to adjust the X/Y coordinates of each segment of the piece for rotation, and not have to touch the game board array at all.

    Again, my goal is not to discourage you - in fact, it's to help prevent yourself from getting discouraged if this doesn't go the way you intended. Regardless of whether you "succeed" with this game as it stands, or not, you're gaining experience and getting valuable practice, so there is definitely some benefit either way.

  4. #4
    Registered User
    Join Date
    May 2013
    Posts
    59
    ok.. made them into structure... so far Im doing the checking for collision only for the block going down. but results is something weird.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    
    #define ROW 15
    #define COLUMN 15
    
    typedef struct
    {
        char sblock;
        char pblock;
    }block;
    
    void gameboard(block b[ROW][COLUMN])
    {
        int r, c;
    
        for(r = -1; r <= ROW; r++)
        {
            for(c = -1; c  <= COLUMN; c++)
            { 
                if(r == -1 || r == ROW || c == -1 || c == COLUMN)
                {    
                    putchar('*');               
                    putchar(' ');
                }
                else
                {
                    if (b[r][c].sblock=='X')
                    putchar(b[r][c].sblock);
                    else if (b[r][c].pblock=='X')
                    putchar(b[r][c].pblock);
                    else
                    putchar(b[r][c].sblock);                  
                    putchar(' ');
                }
            }
     
            putchar('\n'); 
        }
    }
        
    void assignblocks(block b[ROW][COLUMN])
    {
        int rol,col;
        srand( (unsigned) time(NULL));
        
        for (col = 6;col<9;col++)
        
        {
            b[0][col].sblock = rand()%2;
            if (b[0][col].sblock == 1)
            {
            b[0][col].sblock= 'X';
            }
        
        }
        printf("\n");        
        
        for (col = 6;col<9;col++)
        {
            b[1][col].sblock = rand()%2;
            if (b[1][col].sblock == 1)
            {
            b[1][col].sblock= 'X';
            
            }          
        }
        b[1][7].sblock='X';     
        printf("\n");        
            
        for (col = 6;col<9;col++)
        {
            b[2][col].sblock = rand()%2;
            if (b[2][col].sblock == 1)
            {
            b[2][col].sblock = 'X';
            }
        }
    }
    
    
    void movement (block b[ROW][COLUMN])
    {    
        char input;
        int rw,cln;
        
        do
        {
            printf("\nEnter your next move: ");
            scanf(" %c",&input);
        
            if (input == '4') 
            {
                for (rw=0;rw<16;rw++)
                    for (cln=0;cln<16;cln++)
                    if (b[rw][cln].sblock == 'X')
                    {
                        b[rw][cln-1].sblock='X';
                        b[rw][cln].sblock=' ';
                    }                    
            }
                
            if (input == '6') 
                for (rw=15;rw>-1;rw--)
                    for (cln=15;cln>-1;cln--)
                    if (b[rw][cln].sblock == 'X')
                    {
                        b[rw][cln+1].sblock='X';
                        b[rw][cln].sblock=' ';          
                    }
                        
            if (input == '8') 
                for (rw=15;rw>-1;rw--)
                    for (cln=15;cln>-1;cln--)
                    
                    if (b[rw][cln].sblock == 'X')
                    {
                        b[rw+1][cln].sblock='X';
                        b[rw][cln].sblock=' ';
                    }                
                if (b[15][cln].sblock=='X') /*here i will put the 'X' into the p.block so that it does not interfere with the moving when i have another block.*/
    
                {    
                    b[rw][cln].sblock=' ';
                    b[rw][cln].pblock='X';
                    printf("ok");
                }
                        
                                    
                        
            if (input == '2') 
                {
                                      
                }
               
        }while(input != '2' && input != '4' && input != '6' && input != '8');
            
    }                            
    
    int main(void)
    {
        block box[ROW][COLUMN];
        char name[20] ="AAA" ;
        int x,y;
        bool end = false;
    
    
        printf("*************Tetris Game*************\n");
        printf("Please Enter Player Name: ");
        scanf("%s", &name);
        printf("Player Name:%s\n", name);
        printf("ok\n");    
        for(x=0; x<15; x++)
        {
            for(y=0; y<15; y++)
            {
                box[x][y].sblock = ' ';
                box[x][y].pblock = ' ';
            }
        }
        
        assignblocks(box);
        
        do
        {
        printf("\n\n*************Tetris Game*************\n");
        printf("Player Name:%s\n", name);
        
        gameboard(box);
            
        movement(box);
        
        }while (end == false);
    
    
        return 0;
    }

  5. #5
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    I think you haven't understood Matticus' main point:

    Quote Originally Posted by Matticus View Post
    Each piece that enters the game board should be represented by an object separate from the game board (structures would be good for this task).
    As far as I understand your code, you have still just one big gameboard and no separate pieces.

    Quote Originally Posted by Alexius Lim View Post
    so far Im doing the checking for collision only for the block going down. but results is something weird.
    You need to be more specific than "results is something weird" if you want some help.

    Bye, Andreas

  6. #6
    Registered User
    Join Date
    May 2013
    Posts
    59
    Can i ask how long have u been into programming C?

  7. #7
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    i've started learning C about a year ago.

    But I've written my first small programs in BASIC on a C64, so I know a little bit about programming in general.

    Bye, Andreas

  8. #8
    Casual Visitor
    Join Date
    Oct 2001
    Posts
    350
    In the movement function, at least, you're off by at least 1 in your loops. You've got block box[ROW][COLUMN], but then you hard code boundaries for some reason.

    Code:
    for (rw=0;rw<16;rw++)
        for (cln=0;cln<16;cln++)
            if (b[rw][cln].sblock == 'X')
            {
                b[rw][cln-1].sblock='X';
                b[rw][cln].sblock=' ';
            }
    if ROW and COLUMN are 15, then where ever you've hard coded or set a variable so that it winds up being 15 or more, it will be out of bounds. Use the ROW and COLUMN constants in these loops - that's why you defined them. For example,

    Code:
    for(rw = ROW - 1; rw >= 0; --rw)
        for(cln = COLUMN - 1; cln >= 0; --cln)
    or
    
    for(rw = 0; rw < ROW; ++rw)
        for(cln = 0; cln < COLUMN; ++cln)

  9. #9
    Registered User rogster001's Avatar
    Join Date
    Aug 2006
    Location
    Liverpool UK
    Posts
    1,472
    You have not implemented the advice regarding coordinates - it was suggested that your struct should contain xPos and yPos valriables. Also in your main() function move the loops into a seperate InitBoard() function
    Thought for the day:
    "Are you sure your sanity chip is fully screwed in sir?" (Kryten)
    FLTK: "The most fun you can have with your clothes on."

    Stroustrup:
    "If I had thought of it and had some marketing sense every computer and just about any gadget would have had a little 'C++ Inside' sticker on it'"

  10. #10
    Registered User
    Join Date
    May 2013
    Posts
    2
    May i know how you write the code for tetris?
    I have no idea how to start.

  11. #11
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    This is your second post on someone else's thread. If you have a specific question, perhaps you'd be best off starting your own new thread.

    If you have no idea how to even start the code for Tetris, then you are not ready for this challenge yet.

  12. #12
    Registered User
    Join Date
    May 2013
    Posts
    59
    can you show me how and where should i make changes? cause i dont really know how to change the codes if i were to add the xPos yPos variables.

  13. #13
    Casual Visitor
    Join Date
    Oct 2001
    Posts
    350
    Quote Originally Posted by Alexius Lim View Post
    can you show me how and where should i make changes? cause i dont really know how to change the codes if i were to add the xPos yPos variables.
    I'd create a struct for the falling block, and rather than some random block pattern, maybe a few specific patterns - cube, line, angle, etc

    Code:
    typedef struct
    {
        int shape; // current block dropping
        int state; // what the block is doing - init, drop, collide, etc
        int row;   // starting row
        int col;   // starting col
        int max_w; // max width of dropping block
        int max_h; // max height of dropping block
    
    } object;
    
    void updateBox(char b[MAX_ROW][MAX_COL], object *);
    // prototype for manipulating object in box
    if you declare your box and a separate object, you should be able to track its movement within the box and determine whether or not it has hit something.
    I haven't used a compiler in ages, so please be gentle as I try to reacclimate myself. :P

  14. #14
    Registered User
    Join Date
    May 2013
    Posts
    59
    Quote Originally Posted by ronin View Post
    I'd create a struct for the falling block, and rather than some random block pattern, maybe a few specific patterns - cube, line, angle, etc
    Code:
    char blockI[4][4] = { { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, };
    	char blockJ[4][4] = { { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 }, };
    	char blockL[4][4] = { { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 }, };
    	char blockO[4][4] = { { 1, 1, 0, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, };
    	char blockS[4][4] = { { 0, 1, 1, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, };
    	char blockT[4][4] = { { 1, 1, 1, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, };
    	char blockZ[4][4] = { { 1, 1, 0, 0 }, { 0, 1, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, }
    ok, i have this. but where should i put them? declare as a global variable? and how do i use the structure u declared?

  15. #15
    Casual Visitor
    Join Date
    Oct 2001
    Posts
    350
    I find this topic fascinating. I didn't have time to test it very much, but I was thinking along the lines of below for dropping blocks. I'm in a bit of a rush, so please excuse the formatting from pasting.

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <time.h>
    #include <stdlib.h>
    
    #define MAX_COL 15
    #define MAX_ROW 15
    #define MAX_W    4
    #define MAX_H    4
    
    enum SHAPES { CUBE, LINE, ANGLE, MIRROR };
    
    typedef struct
    {
    	int row;
    	int col;
    	int shape;
    	int max_w;
    	int max_h;
    	char block[MAX_H][MAX_W];
    
    } object;
    
    void initObject(object *);
    void updateObject(object *);
    void drawBox(char b[MAX_ROW][MAX_COL], object *);
    
    int main(void)
    {
    	object obj = { 0 };
    	char box[MAX_ROW][MAX_COL] = { { 0 } };
    	time_t t1, t2;
    
    	srand((unsigned)time(0));
    
    	initObject(&obj);
    
    	for(;;)
    	{
    		updateObject(&obj);	    
    	    drawBox(box, &obj);
    
    		t1 = time(0);
    
    		do { t2 = time(0); } while(t1 + 1 > t2);
    	}
    
    	getchar();
    	return 0;
    }
    
    void initObject(object *tmp)
    {
        /* cube   line  angle  mirror
    	   XXXX   XXXX   XXXX  X   
    	   XXXX             X  XXXX
    	   XXXX             X  XXXX
    	   XXXX             X     X
        */
    
    	tmp->shape = rand() % 4;
    	tmp->row   = 0;    
    
    	if(tmp->shape == LINE)
    		tmp->max_h = 1;
    	else
    	    tmp->max_h = MAX_H;
    	
    	tmp->max_w = MAX_W;
    	tmp->col = (MAX_COL - tmp->max_w) / 2;   // center in box
    	memset(tmp->block, ' ', MAX_W * MAX_H); // clear the block
    
    	// set shape
    
    	if(tmp->shape == CUBE)
    		memset(tmp->block, 'X', 16);
    	else if(tmp->shape == LINE)
    		memset(tmp->block, 'X', 4);
    	else if(tmp->shape == ANGLE)
    	{
    		memset(tmp->block, 'X', 4);
    		memcpy(tmp->block + 1, "   X   X   X", 12);
    	}
    	else if(tmp->shape == MIRROR)
    	{
    		memset(tmp->block, 'X', 1);
    		memset(tmp->block + 1, 'X', 8);
    		memcpy(tmp->block + 3, "   X", 4);
    	}
    }
    
    void updateObject(object *tmp)
    {	
        if(tmp->row + tmp->max_h == MAX_ROW)
    		initObject(tmp);
    	else
    		++tmp->row;
    }
    
    void drawBox(char b[MAX_ROW][MAX_COL], object *tmp)
    {
    	int i, j, l=0, m;
    
    	memset(b, 0, MAX_ROW * MAX_COL);
    
    	for(i = tmp->row; i < tmp->row + tmp->max_h; ++i)
    	{
    		m = 0;
    		
    		for(j = tmp->col; j < tmp->col + tmp->max_w; ++j)
    		{
    			b[i][j] = tmp->block[l][m];
    			++m;
    		}
    
    		++l;
        }
    
    	for(i=0; i < MAX_ROW; ++i)
    	{
    		for(j=0; j < MAX_COL; ++j)
    			putchar(b[i][j]);
    
            putchar('\n');
    	}
    }
    I haven't used a compiler in ages, so please be gentle as I try to reacclimate myself. :P

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how to make a program stop after a while
    By xiaohuai in forum C++ Programming
    Replies: 4
    Last Post: 06-21-2011, 01:19 AM
  2. Make accept() stop
    By b00l34n in forum Networking/Device Communication
    Replies: 28
    Last Post: 12-20-2004, 06:50 PM
  3. Trying to make Tetris
    By kalpha in forum Game Programming
    Replies: 9
    Last Post: 06-18-2004, 08:50 AM
  4. how to make it stop
    By xlordt in forum C Programming
    Replies: 6
    Last Post: 01-21-2002, 07:43 AM
  5. Make it stop!
    By dougaerb in forum C++ Programming
    Replies: 2
    Last Post: 10-31-2001, 11:04 PM

Tags for this Thread