17, .Net Micro Framework研究—用MF编写俄罗斯方块

       作者: 刘洪峰

 

 上次编写俄罗斯方块,好像是N年前的大学时代,使用TC2.0在DOS平台上开发的,由于当时的代码是保存在3.5寸软盘上的,到现在那些程序早已经作了古,没有了踪影。俄罗斯方块其实编写并不太容易,要考虑的东西还是蛮多的,以前想在PPC上用.Net精简框架集实现,后来起了个头,没有太大的动力,也就作罢了。现在对MF充满了激情,所以从零做起(没有参考任何现成代码,只不过还是依照我早期的思路编写而成),花费我大半天的时间才编写完毕(在编写过程中,还发现MF对二维数组支持不大好,我后面会提到)。

好了,让我们在.Net Micro Framework模拟器(由于我这里没有带LCD屏的MF开发板,所以很遗憾,不知道在实际的设备上该程序的性能会怎样)上体验一下俄罗斯方块游戏吧。

进入MF Windows(姑且这么叫吧),单击“开始”菜单按钮(MF平台不支持鼠标,是单击模拟器上的Menu按钮,或在键盘敲“空格”或“Windows”键),我们用光标键选中“俄罗斯方块”游戏,按OK键(或按键盘上的“回车”键)进入游戏。

通过开始菜单进入“俄罗斯方块”游戏

编写的俄罗斯方块游戏可是具备经典版的所有功能哟!可以翻转,可以移动,可以得分,可以快速降落等等!要认真玩,否则很快就“Game Over”的。

 

 

在编写过程中发现MF对二维数组支持不是太好。

下面的代码编译时会报错:

bool[,] bFlag=new bool[10,20];

所以在MF中二维数组必须这样声明才行:

bool[][] bShowFlag = new bool[22][]; //主显示区含边框

    for (int i = 0; i < 22; i++)

     {

  bShowFlag[i] = new bool[12];

}

 

附:MF俄罗斯方块核心代码

 

 //俄罗斯方块(叶帆工作室:https://blog.csdn.net/yefanqiu)

        public class ElsGame

        {

            int Current_Y = -2, Current_X =3;

            int intGrade = 0;

            bool[][] bShowFlag = new bool[22][]; //主显示区含边框

            bool[][] bMetaShowFlag = new bool[4][]; //下一个方块显示区

            bool[][] bCurrentMetaShowFlag = new bool[4][]; //当前方块显示区

 

            int intNextNo = 0; //下一个方块索引

            int intCurrentNo = 0; //当前方块索引

 

            enum MoveWay{Left,Down,Right};

            DispatcherTimer GameTimer; //游戏时钟

 

            bool bGameRunFlag = false; //游戏运行标志

 

            public ElsGame(DispatcherTimer GameTimer)

            {

                this.GameTimer = GameTimer;

                Init();

            }

 

            //元素

            private bool[][] GetElsMeta(int intNo)

            {

                bool[][] ElsMetaFlag = new bool[4][];

                for (int i = 0; i < 4; i++)

                {

                    ElsMetaFlag[i] = new bool[4];

                }

                switch (intNo)

                {

                    case 0: //田

                        ElsMetaFlag[1][1] = true;

                        ElsMetaFlag[1][2] = true;

                        ElsMetaFlag[2][1] = true;

                        ElsMetaFlag[2][2] = true;

                        return ElsMetaFlag;

                    case 1: //-

                        ElsMetaFlag[2][0] = true;

                        ElsMetaFlag[2][1] = true;

                        ElsMetaFlag[2][2] = true;

                        ElsMetaFlag[2][3] = true;

                        return ElsMetaFlag;

                    case 2: //|

                        ElsMetaFlag[0][2] = true;

                        ElsMetaFlag[1][2] = true;

                        ElsMetaFlag[2][2] = true;

                        ElsMetaFlag[3][2] = true;

                        return ElsMetaFlag;

                    case 3: //┻

                        ElsMetaFlag[1][2] = true;

                        ElsMetaFlag[2][1] = true;

                        ElsMetaFlag[2][2] = true;

                        ElsMetaFlag[2][3] = true;

                        return ElsMetaFlag;

                    case 4: //┣

                        ElsMetaFlag[2][2] = true;

                        ElsMetaFlag[1][1] = true;

                        ElsMetaFlag[2][1] = true;

                        ElsMetaFlag[3][1] = true;

                        return ElsMetaFlag;

                    case 5: //┳

                        ElsMetaFlag[2][2] = true;

                        ElsMetaFlag[1][1] = true;

                        ElsMetaFlag[1][2] = true;

                        ElsMetaFlag[1][3] = true;

                        return ElsMetaFlag;

                    case 6: //┫

                        ElsMetaFlag[2][1] = true;

                        ElsMetaFlag[1][2] = true;

                        ElsMetaFlag[2][2] = true;

                        ElsMetaFlag[3][2] = true;

                        return ElsMetaFlag;

                    case 7: //┖

                        ElsMetaFlag[3][2] = true;

                        ElsMetaFlag[1][1] = true;

                        ElsMetaFlag[2][1] = true;

                        ElsMetaFlag[3][1] = true;

                        return ElsMetaFlag;

                    case 8: //┍

                        ElsMetaFlag[2][1] = true;

                        ElsMetaFlag[1][1] = true;

                        ElsMetaFlag[1][2] = true;

                        ElsMetaFlag[1][3] = true;

                        return ElsMetaFlag;

                    case 9: //┒

                        ElsMetaFlag[1][1] = true;

                        ElsMetaFlag[1][2] = true;

                        ElsMetaFlag[2][2] = true;

                        ElsMetaFlag[3][2] = true;

                        return ElsMetaFlag;

                    case 10: //┙

                        ElsMetaFlag[1][3] = true;

                        ElsMetaFlag[2][1] = true;

                        ElsMetaFlag[2][2] = true;

                        ElsMetaFlag[2][3] = true;

                        return ElsMetaFlag;

                    case 11: //┕

                        ElsMetaFlag[1][1] = true;

                        ElsMetaFlag[2][1] = true;

                        ElsMetaFlag[2][2] = true;

                        ElsMetaFlag[2][3] = true;

                        return ElsMetaFlag;

                    case 12: //┎

                        ElsMetaFlag[1][2] = true;

                        ElsMetaFlag[1][1] = true;

                        ElsMetaFlag[2][1] = true;

                        ElsMetaFlag[3][1] = true;

                        return ElsMetaFlag;

                    case 13: //┑

                        ElsMetaFlag[2][3] = true;

                        ElsMetaFlag[1][1] = true;

                        ElsMetaFlag[1][2] = true;

                        ElsMetaFlag[1][3] = true;

                        return ElsMetaFlag;

                    case 14: //┚

                        ElsMetaFlag[3][1] = true;

                        ElsMetaFlag[1][2] = true;

                        ElsMetaFlag[2][2] = true;

                        ElsMetaFlag[3][2] = true;

                        return ElsMetaFlag;

                }

                return null;

            }

 

            //翻转

            private int GetTurnMeta(int intNo)

            {

                switch (intNo)

                {

                    case 0: //田

                        return 0;

                    case 1: //-

                        return 2;

                    case 2: //|

                        return 1;

                    case 3: //┻

                        return 4;

                    case 4: //┣

                        return 5;

                    case 5: //┳

                        return 6;

                    case 6: //┫

                        return 3;

                    case 7: //┖

                        return 8;

                    case 8: //┍

                        return 9;

                    case 9: //┒

                        return 10;

                    case 10: //┙

                        return 7;

                    case 11: //┕

                        return 12;

                    case 12: //┎

                        return 13;

                    case 13: //┑

                        return 14;

                    case 14: //┚

                        return 11;

                }

                return intNo;

            }

 

            //初始化

            public void Init()

            {

                if (!bGameRunFlag)

                {

                    //主显示区

                    for (int i = 0; i < 22; i++)

                    {

                        bShowFlag[i] = new bool[12];

                        for (int j = 0; j < 12; j++)

                        {

                            if (i == 21 || j == 0 || j == 11)

                            {

                                bShowFlag[i][j] = true;

                            }

                            else

                            {

                                bShowFlag[i][j] = false;

                            }

                        }

                    }

 

                    //辅助显示区

                    for (int i = 0; i < 4; i++)

                    {

                        bMetaShowFlag[i] = new bool[4];

                        for (int j = 0; j < 4; j++)

                        {

                            bMetaShowFlag[i][j] = false;

                        }

                    }

 

                    //方块初始化

                    Microsoft.SPOT.Math.Randomize();

 

                    intCurrentNo = Microsoft.SPOT.Math.Random(15);

                    bCurrentMetaShowFlag = GetElsMeta(intCurrentNo);

 

                    intNextNo = Microsoft.SPOT.Math.Random(15);

                    bMetaShowFlag = GetElsMeta(intNextNo);

 

                    //时钟开始

                    GameTimer.Start();

 

                    //积分清零

                    intGrade = 0;

 

                    //游戏运行标志

                    bGameRunFlag = true;

                }

            }

 

            //下降

            public bool DoDownMove()

            {

               if (IsMove(Current_X, Current_Y, bCurrentMetaShowFlag, MoveWay.Down) && bGameRunFlag)

                {

                    Current_Y++;

                    MoveBlock(Current_X, Current_Y, bCurrentMetaShowFlag, MoveWay.Down);                   

                }

                else

                {

                   //时钟恢复正常

                    GameTimer.Interval = new TimeSpan(0, 0, 1);

                    //判断是否得分及游戏是否结束

                    int intRet=GetGameState() ;

                    if (intRet == -1)

                    {

                        GameTimer.Stop();

                        bGameRunFlag = false;

                        //主显示区

                        for (int i = 0; i < 22; i++)

                        {

                            bShowFlag[i] = new bool[12];

                            for (int j = 0; j < 12; j++)

                            {

                                if (i==1 || i == 20 || j == 1 || j == 10)

                                {

                                    bShowFlag[i][j] = true;

                                }

                                else

                                {

                                    bShowFlag[i][j] = false;

                                }

                            }

                        }

                    }

                    else

                    {

                        intGrade += intRet;

                        Current_Y = -3;

                        Current_X = 3;

                        NextBlock();

                    }

                }

                return true;

            }

 

            //判断游戏状态

            private int GetGameState()

            {

                bool bFlag = false;

                int intNum = 0;

                //判断游戏是否结束

                for (int i = 1; i < 11; i++)

                {

                    if (bShowFlag[1][i])

                    {

                        return -1;

                    }

                }

 

                //判断得分

                for (int i = 1; i < 21; i++)

                {

                    bFlag = true;

                    for (int j = 1; j < 11; j++)

                    {

                        if (!bShowFlag[i][j]) bFlag = false;

                    }

                    if (bFlag)

                    {

                        //移动数组

                        for (int e = i; e>0; e--)

                        {

                            for (int k = 1; k < 11; k++)

                            {

                                bShowFlag[e][k] =bShowFlag[e-1][k];

                            }

                        }

                        intNum++;

                    }

                }

                switch (intNum)

                {

                    case 1:

                        intNum = 100;

                        break;

                    case 2:

                        intNum = 300;

                        break;

                    case 3:

                        intNum = 500;

                        break;

                    case 4:

                        intNum = 800;

                        break;

                }

                return intNum;

            }

 

            //左移

            public bool DoLeftMove()

            {

                if (!bGameRunFlag) return false;

                if (IsMove(Current_X, Current_Y, bCurrentMetaShowFlag, MoveWay.Left))

                {

                    Current_X--;

                    MoveBlock(Current_X, Current_Y, bCurrentMetaShowFlag, MoveWay.Left);

                    return true;

                }

                return false;

            }

 

            //右移

            public bool DoRightMove()

            {

                if (!bGameRunFlag) return false;

                if (IsMove(Current_X, Current_Y, bCurrentMetaShowFlag, MoveWay.Right))

                {

                    Current_X++;

                    MoveBlock(Current_X, Current_Y, bCurrentMetaShowFlag, MoveWay.Right);

                    return true;

                }

                return false;

            }

                           

            //方块翻转

            public bool DoTurn()

            {

                if (!bGameRunFlag) return false;

                #region //判断是否能翻转

                int mX=0, mY = 0;

                bool bFlag = true;

                //翻转后的标志

                bool[][] bFlags = GetElsMeta(GetTurnMeta(intCurrentNo));

                SetBlock(Current_X, Current_Y, bCurrentMetaShowFlag, false);              

                for (int i = 0; i < 4; i++)

                {

                    for (int j = 0; j < 4; j++)

                    {

                        mX = Current_X + j + 1;

                        mY = Current_Y + i + 1;

                        if (mX > -1 && mX < 12 && mY > -1 && mY < 22)

                        {

                            if (bShowFlag[mY][mX] && bFlags[i][j])

                            {

                                bFlag = false;

                            }

                        }

                    }

                }

                SetBlock(Current_X, Current_Y, bCurrentMetaShowFlag, true);

                #endregion

 

                if (bFlag)

                {

                    SetBlock(Current_X, Current_Y, bCurrentMetaShowFlag, false);

                    intCurrentNo = GetTurnMeta(intCurrentNo);

                    bCurrentMetaShowFlag = GetElsMeta(intCurrentNo);

                    SetBlock(Current_X, Current_Y, bCurrentMetaShowFlag, true);

                    return true;

                }

                return false;

            }

 

            //设置方块

            private void SetBlock(int X, int Y, bool[][] bFlags, bool bFlag)

            {

                略 ;-)

            }

 

            //下一个方块

            private void NextBlock()

            {

                intCurrentNo = intNextNo;

                bCurrentMetaShowFlag = bMetaShowFlag;

                intNextNo = Microsoft.SPOT.Math.Random(15);

                bMetaShowFlag = GetElsMeta(intNextNo);

            }

 

            //移动方块

            private void MoveBlock(int X, int Y, bool[][] bFlags,MoveWay mw)

            {

                switch (mw)

                {

                    case MoveWay.Left:

                        SetBlock(X+1, Y, bCurrentMetaShowFlag, false);

                        SetBlock(X, Y, bCurrentMetaShowFlag, true);

                        break;

                    case MoveWay.Down:

                        SetBlock(X, Y - 1, bCurrentMetaShowFlag, false);

                        SetBlock(X, Y, bCurrentMetaShowFlag, true);

                        break;

                    case MoveWay.Right:

                        SetBlock(X-1, Y, bCurrentMetaShowFlag, false);

                        SetBlock(X, Y, bCurrentMetaShowFlag, true);

                        break;

                    default:

                        break;

                }             

            }           

 

           //是否可以移动

            private bool IsMove(int X, int Y, bool[][] bFlags, MoveWay mw)

            {

                略 ;-)

            }

 

            //绘制

            public void Draw(DrawingContext dc)

            {

                int BarTop = 26;

                int BarHeight = SystemMetrics.ScreenHeight - BarTop * 2;

                dc.DrawRectangle(new SolidColorBrush(Colors.Gray), new Pen(Colors.Gray), 0, BarTop, SystemMetrics.ScreenWidth, BarHeight);

 

                //主显示区

                dc.DrawRectangle(new SolidColorBrush(Colors.Black), new Pen(Colors.White), 79, BarTop + 3, 92, 182);

 

                //辅助显示区

                dc.DrawRectangle(new SolidColorBrush(Colors.Black), new Pen(Colors.White), 222,120, 38, 38);

 

                //积分区

                dc.DrawRectangle(new SolidColorBrush(Colors.White), new Pen(Colors.Blue), 205, 180, 74, 20);

                dc.DrawText(intGrade.ToString(), YFWinApp.YFFont,ColorUtility.ColorFromRGB(0,120,0), 224 + 17 - intGrade.ToString().Length * 3, 184);

               

                //显示

                DrawEls(80, BarTop + 4, 9, 9, dc);

 

                //结束

                if (!bGameRunFlag)

                {

                    dc.DrawText("Game Over!", YFWinApp.YFFont, Colors.Red,96, 110);

                }

            }

 

            //显示方块

            private void DrawEls(int X,int Y,int Width,int Height,DrawingContext dc)

            {

                SolidColorBrush sb=new SolidColorBrush(Colors.Green);

                Pen pen=new Pen(Colors.Blue);   

               

                //主显示区

                for (int i = 0; i < 20; i++)

                {

                    for (int j = 0; j < 10; j++)

                    {

                        if(bShowFlag[i+1][j+1])

                           dc.DrawRectangle(sb, pen, X +j * Width, Y + i * Height, Width, Height);

                    }

                }

 

                //辅助显示区

                for (int i = 0; i < 4; i++)

                {

                    for (int j = 0; j < 4; j++)

                    {

                        if(bMetaShowFlag[i][j])

                             dc.DrawRectangle(sb, pen,223 + j * Width, 121 + i * Height, Width, Height);

                    }

                }

            }

}