Best Tetris Data structure to use?

BlitzMax Forums/BlitzMax Beginners Area/Best Tetris Data structure to use?

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

In my tetris game I had a TShape type and a TBlock type. The board (TBoard) was a regular 2d array, of TBlock.

A TBlock has an x and y, relative to position of the shape, not actual game coordinate. For example, 0, 0 is the central pivot of the shape, 0, 1 is to the right of the shape

Each tetris shape has only 4 blocks, so give a TShape an array of 4 TBlocks. I was first tempted to give each a 4x4 array as this would fit any shape, in order to store the shape, but an array of 4 is simplier, trust me.

A TShape so far has 4 TBlocks, and also needs an x and y for it on the board. This is where the central block is located. So if it's at 5, 6 on the board, then block of coordinate 0, 1 will be at 5, 7.

Your block will also need whether it's active, rotatable etc and other overhead.

What's the point of this 4 block array? It makes rotating VERY simple. Simply create a temperary 4 block array that is rotated, pick up the piece off the board, and try and place the temp array. If it works, set the actual array to the temp array. If it doesn't, replace the original array - it cannot rotate.

I found the rotating algorithm, and some other ideas, from this site:
http://www.codeproject.com/KB/game/tetriscontrol.aspx
which has since been deleted, so here is my code. (I was hoping to show you the idea but I have forgotten, you'll have to gleam it. But it is a very good algorithm)

Method rotate(factor:Int, grid:TGrid)
		'This method rotates the shape by 90 degrees factor times clockwise
		'about its pivot (point 0, 0)
		'For example factor=1 means 90 degree clockwise rotation
		'factor=-1 conterclockwise 90
		
		'Assert (Not game And Not inplay) Or game Else "Error rotate";
		
		'to avoid redundant rotations. yay the complicatedness
		factor = ((factor < 0) * 4 + factor) Mod 4;
		
		'if the piece cannot be rotated (square), or no rotation is requested(!) then return
		If Not rotatable Or factor = 0 Then Return;
		
		'create some new points to store the rotated piece
		Local newPoint:TPoint[] = New TPoint[pointnum];
		For Local i:Int = 0 Until pointnum
			newPoint[i] = New TPoint;
		Next
		
		'store the current points in a temp array
		Local tempPoint:TPoint[] = New TPoint[pointnum];
		For Local i:Int = 0 Until pointnum
			tempPoint[i] = point[i].clone();
		Next
		
		'rotate the piece by swapping X and Y and changing the appropriate sign
		For Local rotationCount:Int = 0 Until factor
			For Local i:Int = 0 Until pointnum
				newPoint[i].alive = tempPoint[i].alive;
				newPoint[i].x = -tempPoint[i].y;
				newPoint[i].y = tempPoint[i].x;
				tempPoint[i] = newPoint[i].clone();
			Next
		Next
		
		If Not inplay
			For Local i:Int = 0 Until pointnum
				point[i] = newPoint[i].clone();
			Next
		Else
			'remove the old piece from the game board
			pluckPiece(grid);
			
			'in case the piece cannot be rotated here, store the old points safely. then give the piece the new rotated points
			Local oldPoint:TPoint[] = New TPoint[pointnum];
			For Local i:Int = 0 Until pointnum
				oldPoint[i] = point[i].clone();
				point[i] = newPoint[i].clone();
			Next
			
			'attempts to place the rorated piece. returns false if cannot be rotated. in that case restore the old points and replace
			If Not placePiece(grid, originX, originY)
				For Local i:Int = 0 Until pointnum
					point[i] = oldPoint[i].clone();
				Next
				placePiece(grid, originX, originy);
			End If
		End If
	End Method


This is all well and good, but how does the piece inform the board where it is, for collision checking?

The TBlocks on the board aren't to hold their own blocks, but will references the TBlocks in the arrays inside TShape in order to know that they are there. When placing a piece, loop through the 4-block array and by using the absolute coordinate of the piece and the relative coordinate of each block, to set the TBlock cell in the board array to reference it. When removing the block, simply dereference the cell in the board. (This way is my own idea).

I think I've given you the general idea. If I've missed any points off or you need something explaining better, please ask.


About your question about using lists, the board is so small that it is acceptable to simply start at the top of the board and move everything downwards.