I’ve always wanted to code the Tetris, but as time goes on,this game looks a bit old fashion. Especially on those new computers with all bells and whistles, but this led me to idea of writing Tetris for .NET Micro Framework. It will be cool sample application and discovery of WPF possibilities in Micro Framework. Video shows more..

Two dimensional arrays in Micro Framework

Probably the biggest glitch with writing Tetris, was a fact that Micro Framework supports only one dimensional arrays. Since Tetris is about grid with falling ‘grid-blocks’, the two dimensional arrays are quite essential.

First step was to write ByteMatrix class which represents matrix of byte value (two dimensional byte array). Constructor of the class takes Rows and Columns argument to initiate the matrix size. Internally, values are stored in one dimensional array accessed by the GetCell(int row, int column) and SetCell(int row, int column, byte value) methods, that evaluates the appropriate index in array.

public class ByteMatrix
{
    private byte[] _baseArray;
    private int _rows, _columns;
    
    public ByteMatrix(int rows, int columns)    
    public ByteMatrix(ByteMatrix sourceMatrix)
    public byte GetCell(int row, int column)    
    public void SetCell(int row, int column, byte value)
    public void SetCells(int row, int column, byte[] inputArray)
    public void Clear()

    #region Properties
    public int Rows
    public int Columns
    public int Length
    public byte[] BaseArray
    #endregion
}

Tetris based on .NET Micro Framework 500x211 Tetris game running on the Tahoe board

Separating logic and presentation layer

It’s always better to separate business logic of the application and presentation layer. The code becomes better portable and maintainable as well as unit test of the logic are much easier to implement when UI is not considered. Tetris application has two namespaces GameLogic and Presentation. First one contains all classes for core game. These classes can be easily ported to .NET Compact Framework or full Framework because has no direct relation to Micro Framework. On the other hand the Presentation namespace consist of WPF controls and windows that are used to visualize the game and provides interaction with user. The base of the game is the GameUniverse class which keeps game grid, current falling block and game statistics (score, level, etc.). GameUniverse can be initialized by Init() method, that clears the game grid and game statistics. Starting game in GameUniverse is done by StartLevel(int level). Argument specifies level where game will start. StepUniverse() method runsn claa pmi< md palling blunsn"n"> iwatiunit tses bottombase of tme ges "n"baseore gameng>ng> metiasselhis fromband presentation lssed imh uial.

ssass="n">row oe bobnbsp; - juste thmakmes bet2 id demof th imviasHowgamrn, b an>of mais acis, pr nes dimfes beti separate bua o visuause newith f the at evaluas whs bettjusteanthe omnd Cored. thmto issese class="language-csharp highlighter-rouge">
public class ByteMatrix is dclass="p">}
private// Gd game st array acs

    classof tan class="kt">int LengthLengthLength10n class="p">;
    privateof tan class="kt">int LengthLengthLength20n class="p">;
    private int _rows, _columns;
    private int sourceMatriling blBwatin class="p">, _columns, private int sourceMatriwheldan class="n">LengthLengthsourceMatix(ByteMatrix, _columns)
     private intintintLengthsourceMatix()

    public void Clearn class="p">()

    public void SetCells(int row< by evel)n class="p">(public void SetCellsn class="p">()

    public void SetCellsn class="p">()

    public void SetCells()

    public void SetCells[] <    public void SetCells()

    # int SetCells, public int SetCells()

    private byteSetCells, ByteMatrix sourceMatribwatin class="p">, _columnsan> row(_columnsan> row)
    public int SetCells()

    #region Properties
    public int sourceMatriCing blBwatin classclass="k">public int sourceMatriNexlBwatin classclass="k">public int sourceMatriFheldan clasclass="k">public int Lengthpublic int Lengthpublic intint#endregion
}