# Need help with tetris game

This topic is 4299 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hello everyone, I'm making a tetris game and i'm having a really hard time to implement a row completion check. I have a Block class and a Shape class that inherits Block, and each different shape type inherits Shape. When a certain shape reaches the bottom I add it to an ArrayList called al_settledShapes. I'm making it based on the tutorial at c-unit.com, its not exactly that way, but the structure of the classes is pretty much the same, also my version is in SdlDotNet. Here's what i've been trying to do:
        public void CheckRowCompletion()
{
int completedCols = 0;
int rowPosition = 0;
ArrayList rowsToRemove = new ArrayList();

for (int row = 0; row < num_rows; row++)
{
rowPosition = i_bottomBorder - row * (Block.i_blockWidth + 1);

foreach (Shape s in al_settledShapes)
{
foreach (Block b in s.Blocks)
{
if (b.Active && (b.Y == rowPosition))
{
completedCols++;
if (completedCols == num_cols)
{
i_score++;
//remove row
completedCols = 0;
}
}
}
}
}
}

Really can't figure out why is not working Thanks in advance...

##### Share on other sites
How about a simple array, with as many elements as you have rows

Every time a block in a certain row is placed, add one and when it reaches the amount of blocks per row, it will be completed

##### Share on other sites
Well that would be "ANOTHER" way of doing it... but i already have my project pretty far, i want to do it the way i'm doing it...
Can someone help-me out with this? its a logic problem, so if you'd give me examples in other languages or explain to me what im doing wrong would be great.

Thanks

##### Share on other sites
You should tell us exactly what is going wrong. When the code runs what happens? does nothing happen or do you get some other unexpected result.

##### Share on other sites
Sorry about that, didn't notice, i actually didn't explain what the problem was. The problem is that NOTHING happens, i just increase the score counter to check if it worked but it didn't... hope somebody can come up with a solution

thanks

##### Share on other sites
Quote:
 Original post by BrasiLokauI have a Block class

What is the purpose of this class? How does its interface look like?

Quote:
 Original post by BrasiLokauand a Shape class that inherits Block

What is the purpose of this class? How does its interface look like?

Quote:
 Original post by BrasiLokauand each different shape type inherits Shape.

You mean you have seven different Shape classes? How do they differ in behavior?

##### Share on other sites
Quote:
 Original post by BrasiLokau if (b.Active && (b.Y == rowPosition)) { completedCols++; if (completedCols == num_cols) { i_score++; //remove row completedCols = 0; } }...

This section here is supposed to remove your row? As far as I can see it is only resetting a variable to 0. How is this removing a row? Sorry, hard to guess without knowing what your other code is doing.

##### Share on other sites
IronGryphon:

I think the comment is supposed to be a placeholder and the fact that the score isn't increated shows that it doesn't work.

BrasiLokau:

My suggestion is: rename the variables and write comments so that anybody can understand what is supposed to happen ... and to prove that you understand the code.
Maybe by doing that you'll stumble over the error.

Also create a logfile class that shows which parts of the code get executed and what doesn't ... or use the debug mode to "step through the code".
I usually work with a logfile so I can't explain how working with the debugger is done properly.

##### Share on other sites
omg... i found the stupid mistake i made... it was that a block when reaches the bottom, its Y value is greater than the value i was checking to see when the block reaches the bottom. Pretty weird problem... working on a fix...

Sorry about that guys, thanks a lot

##### Share on other sites
Btw, there is another error that will lead to problems. You reset "CompletedCols=0" only when you happen to find a completed row. This is wrong, because if a row is only half-complete, you will start the check of the next row with CompletedCols>0. You must reset CompletedCols in every iteration.

##### Share on other sites
I'd like to know how you actually remove the rows. As soon as you have implemented it (or have questions), feel free to post. Because as I see it, it involves splitting pieces that contribute to the rows into two pieces, or maybe just cut one piece a little smaller, or completely remove the piece.

two pieces:
XXX <-- cut hereX

one piece:
X <-- cut hereXXX

remove:
XXXX <-- cut here

How is your list of pieces sorted?

##### Share on other sites
Unless you have just ommitted it, it doesn't seem that you are doing anything to remove the completed row. Oh wait. Is the comment - // remove row - just a placeholder for the ommitted code? That would make sense. Why don't you post that because it sounds like that is the part of the code that is failing.

EDIT: wow, I should learn to read. Apparently you already found the solution! Doh! sorry.

##### Share on other sites
Quote:
 Original post by Fred304I'd like to know how you actually remove the rows. As soon as you have implemented it (or have questions), feel free to post. Because as I see it, it involves splitting pieces that contribute to the rows into two pieces, or maybe just cut one piece a little smaller, or completely remove the piece.two pieces:XXX <-- cut hereXone piece:X <-- cut hereXXXremove:XXXX <-- cut hereHow is your list of pieces sorted?

Seeing how he has a Block::Active flag, I assume he just "unflags" all blocks that belong to the removed row, and then removes all the Shapes that have all their blocks inactive. Anyway, the whole approach is slightly insane. What's the purpose of holding a list with several items, each one comprised of several blocks, which could be "active" or not? It's useless extra information. At any moment, Tetris only cares about the "soup" of blocks, not about how and by what shapes it got constructed. The logical thing to do is just have a WxH grid that fills with the correct values when a piece lands, and be done with it. BrasiLokau, I assume that you're making Tetris not just to make Tetris, but to learn. I don't think you learn much by using crazy methods like this. The design you follow does not fit the problem very good. Try to make your life simple.

##### Share on other sites
Quote:
Original post by mikeman
Quote:
 Original post by Fred304I'd like to know how you actually remove the rows. As soon as you have implemented it (or have questions), feel free to post. Because as I see it, it involves splitting pieces that contribute to the rows into two pieces, or maybe just cut one piece a little smaller, or completely remove the piece.two pieces:XXX <-- cut hereXone piece:X <-- cut hereXXXremove:XXXX <-- cut hereHow is your list of pieces sorted?

Seeing how he has a Block::Active flag, I assume he just "unflags" all blocks that belong to the removed row, and then removes all the Shapes that have all their blocks inactive. Anyway, the whole approach is slightly insane. What's the purpose of holding a list with several items, each one comprised of several blocks, which could be "active" or not? It's useless extra information. At any moment, Tetris only cares about the "soup" of blocks, not about how and by what shapes it got constructed. The logical thing to do is just have a WxH grid that fills with the correct values when a piece lands, and be done with it. BrasiLokau, I assume that you're making Tetris not just to make Tetris, but to learn. I don't think you learn much by using crazy methods like this. The design you follow does not fit the problem very good. Try to make your life simple.

Well as i said, I created this tetris clone based on the tutorial at c-unit. I did write the code like that to learn, and because the code looks clean and it has a lot of oop elements in it. The first solution i came up with when i was plaining the game, was using a bidimensional array int area[row,col], make all the game logic based in that array(moving, detecting rows, removing) and then translating that to graphics in the screen. But since i'm getting pretty far with this the way it is, i'm going to finish it. I need to fix collision detection thats is acting weird, also when i complete more than a single row at the same time it only removes the second row after the next shape reaches the bottom(pretty weird bug), have to write score and level part, also i pretend to implement highscore, splash screen e menus, then its finished :)

and for the guy that asked how do i remove the blocks, as mike said, each block is set its Active property to true, so when i call the render method, it only renders the ones that Active are set to true.

##### Share on other sites
Quote:
 I did write the code like that to learn, and because the code looks clean and it has a lot of oop elements in it.

Just because you use lots of classes and inheritance does not mean you have a good OO design.

Quote:
 and for the guy that asked how do i remove the blocks, as mike said, each block is set its Active property to true, so when i call the render method, it only renders the ones that Active are set to true.

But that does not cut the pieces into two :)

Let me make it clearer. Consider a case where an L-piece gets cut in the middle:
AB   <--- cut hereCD

As I understand it you set the B block to inactive which would look something like this:
ACD

But how can you make A fall onto C? It's supposed to look like this, isn't it:
ACD

##### Share on other sites
well, i must say that you 'r right... the way i'm doing its way more complicated than should be. But i really did learn alot of oop concepts with it, so it was worth writing the code that way. Because i don't expect millions of people trying out my tetris game :P, i made it for learning purposes.

I did make it work. Let me try to explain how the classes work. There is a block class, with fiels like position, if its active or not. Also there is a Shape class, which is responsible for creating an array of 4 block, the state(for rotation purposes), with methods for checkcollision, move shape, render, deactivate(loop through each block and set .active = false, so it is not draw by render method, and etc... So when i have to remove rows, i loop throw all settled shapes, and just check which ones are in the same height, as the row that has to be erased...
Thats the way it works, as i said, i read a tutorial at c-unit.com about making a tetris, my code is pretty much based with the code in the website, except for changes i've made. You can go there and see if you understand.
The code is not completed yet, there is a bug that if two rows are scored at the same time, it only desapear of screen after the next block hits the bottom.

[Edited by - BrasiLokau on May 19, 2006 5:33:16 PM]