c#俄罗斯方块.pdf
前几天和一个在读的本科生聊天,他一直在抱怨学校学习的理论知识太多,实践的机会太少。担心自己因此毕业后可能难以找到工作。我认为一个人要是想投入开发,他总是可以找到项目的。与其把自己的时间浪费在抱怨和指责上,为什么不现在就动手开始开发呢?他的回答是不知道开发啥,没有人指导自己,不知道从何入手。我想想了,那么我们就从俄罗斯方块开始下手吧。“从俄罗斯方块开始,那个游戏太简单了。我即使可以开发一个俄罗斯方块,又会有那个公司要我呢?如果将来我的建立上写上我做过俄罗斯方块游戏。那也不大会有人要我吧”“一个俄罗斯方块无论是从算法上来讲,还是从其他方面上来讲,确实太简单了。但是很多人只能看到俄罗斯方块的简单,却很少有人能把简单做到极致。而一个成功的程序员就是要做到把简单的东西深入下去,把简单的事情做到极致,就不在是简单了。让我来带你开发个俄罗斯方块吧。”那么也请各位看客跟着我们起去深入俄罗斯方块,把这个简单的小玩意做到一个极致。这个系列的探讨适合有一定的C#的语法基础。但是尚未做过任何大的项目的童鞋一起学习。如果哪位大侠看到鄙人的东西,热烈欢迎拍砖。首先说说咱们的学习的大概的规划:第一步、我们先简单的理解下俄罗斯游戏开发的大概算法和需要的知识,然后把这些知识组合 开 发 个小小的俄罗斯游戏Demo。基本上实现俄罗斯方块游戏的控制和操作。第二步、我们在我们的Demo的基础上,尽可能的提出对我们的算法进行优化。对我们的界面进行美化,功能进行扩展。从一个简单的Dem。变成一个可玩性很强的单机版俄罗斯方块小游戏。第三步、我们来尝试把单机版俄罗斯方块做成一个俩人联机版游戏,利 用 SOCKET通信,让咱们的俄罗斯方块实现可以双人玩。我们主要使用point-to-point方式来玩。一 个 当做服务器端一个当做客户端来玩。第四步、我们把我们的简单联机版俄罗斯方块做成一个带游戏大厅的服务端和客户端多人连接俄罗斯方块游戏。让更多的人加入我们来玩。第五步、从可盈利出发。我们研究深入研究俄罗斯游戏可能产生的盈利模式,我们将在俄罗斯游戏中把我们的盈利模式实现,我们将在我们的游戏中增加其他的一些道具,而这些道具有可能需要稍微改变下游戏的规则。至此为止,我们就可以依托一个点逐渐的拓展成一个面,完成一个俄罗斯方块游戏商业模式。至此我们的游戏已经可以成为一个可盈利的商、也 模式。当然能不能依托这个简单的游戏收获金钱需要看咱们做的游戏的好坏。也需要看咱们的机会和宣传了。从极坏的情况下来讲解。咱们赚钱的可能性基本上为零。当然这个也是这次开发最最可能呈现的情况。但是对一个学习计算机的程序员来说。这样的开发过程绝对可以称得是一次工作经历了,而且有了这样的思维和学习的模式,我相信抱怨和指责应该可以远离你的生活了。根据上节我们规划好的开发过程,这节我们来实现一个简单的俄罗斯方块程序。当然完成俄罗斯方块的Dem。是我们这节课的最终目标。在实现这个目标的同时,我还要跟大家一起去分析俄罗斯方块的需求、算法、具体开发的步骤。并且最终选择C#语言来实现这个demo。下面废话少说,翠花,上内容!第一步、思考俄罗斯方块的游戏规则:任何时候我们去开发或者设计一个项目,首先需要思考的就是需求。俄罗斯方块中,我们要做一个俄罗斯方块的游戏,那么俄罗斯方块游戏的游戏规则就是我们的需求。所以我们必须深入了解俄罗斯方块游戏的游戏规则。俄罗斯方块游戏可能产生下面五种形状的方块。这些方块有我们的方向键的控制可以产生旋转,左右移动和加速前进等,往下掉,只到遇到下面已经有方块挡住停下来。如果一行完全排列满,则会消掉,如果排列到了顶部,则会失败。第二步、把我们的“需求”从计算机的角度去分析:我们对任何一个项目的最初的需求是从使用者的角度去描述这个项目的,这种描述基本 上涵盖了使用者可能用到的功能和要求。我们在做个项目,特别是为一个非计算机专业做一个项目的时候,客户的描述,或者业务人员承接到项目的时候,他们和客户的沟通,基本上是基于这种初级的需求的,这种初级的需求的有点是:客户和 也务人员比较容易理解,沟通起来非常的方便。但是他的缺点是非计算机专业用语,不够规范和严谨。不能拿这个文档和需求来直接要求开发人员。需 要个对市场(客户)比较了解,同时又是资深的程序员把这个需求编程一个专业开发人员相对比较容易理解的需求。甚至直接编程开发的具体思路。然后有开发人员去实现。我们的小游戏实在是太小了,不可能分出来业务人员、项目规划人员、项目架构、程序开发。所以这一切也都有我们开发者一个人独揽了。不过麻雀虽小,五脏俱全哦。我们不是说了嘛,通过学习俄罗斯方块掌握项目开发的经验呢。所以希望各位看客认真的看这些个步骤,如果我哪里说错了,欢迎拍砖。a、关于俄罗斯方块游戏中方块的产生。我们假设产生四种方块。实际上俄罗斯方块产生的方块要多余四个。但是咱们这节课是做一个Demo,所以先做四个,具体的四个请见图片1。因 为 CSDN不能上传图月、我上传到下载中去了。大家可以下载使用,期待csdn可以正常的上传图片)。b、俄罗斯方块当需要变化方块的时候,每个方块需要顺时针旋转90,具体可能产生的形状也见图一。从数学,或者计算机的角度来看:我们根据图1来看,我们可以把所有的方块看成一个4*4的二维数组。把 有“砖”的地方表示为1,没 有“砖”的地方表示为0,所以所有的的方块都可以表示为图二的样式。c、我们也可以把背景看成是14*20的二维数组。那么俄罗斯方块的需求,站在程序员的角度上就可以变成:我们随机从方块的4 个4*4的矩阵中挑选出来一个,并且随机的挑选一个他的初始化状态(关于状态变化,我们同样可以把他们表示在一个4*4的矩阵中)。然后这个被挑选的矩阵,在一个14*20的矩阵中不断的按照 种速度进行往下运动。我们同时可以使用方向键,对这个举证进行控制,使得它可以左右运动,同时可以循环的变化他的状态。如果这个矩阵在运动的方向上遇到了数值为 1 的时候则停止运动,在左右运动上表现为不能移动,在往下运动的时候则表现为这个方块运动的结束。把这个矩阵的数值复制到背景矩阵中去。这个时候检查背景矩阵,如果背景矩阵中有一个行全部为1,那么在y轴上比该行小的所有行向下移动一行,用户得分增加100。同理,检查所有的行,并且做同样动作。检查完成后,进入下个方块的随机挑选,下落。当某个方块下落完成的时候。他的y 坐标在背景中为。的时候。游戏结束。作为游戏的界面,我们需要在游戏的状态发生改变的时候,把背景矩阵和运动矩阵都绘制出来。数值为0 的地方不绘图,数值为1 的地方绘制图片。到此为止。我们的游戏已经用人类语言。从计算机的角度来说分析完成了。剩卜的就是使用计算机语言表达出来了,不管你是学习的C#,C语言,C+,Delphi,Java,python,Js,VB,(汇编我不懂,暂时不包括吧)。只要你能理解了上述的“思路”。那么你可以用任何语言来写出来。我真希望用所有的语言都给大家写写,把 IT老祖宗的那句:“编程靠的是思想(想法,思路),语言不重要。”的真理来验证下,可怜CSDN的 blog写起来太麻烦了,而且我老婆催着我赶紧回家过年的,所以这次就暂时使用C#来给大家实现下。我们就从一个C#盲来开始看看需要如何学习,如何实现。首先、确定我们要用的语言是C#,矩阵的运算需要多是多维数组,数组的运算多需要循环。另外对多种情况的判断需要if,switch等分支判断语句,我们的方块定时运动,需要用到timer控件。所以在开始咱们的项目前,请确保,你已经对C#的语法有了基本的了解,尤其对数组的操作、if语句,for循环语句,switch语句要会用。同时对基本的button、timer控件进行基本的了解。如果你在使用其他语言编程,找你所使用的语言中的类似的东西。其他的东西至少这个项目中不会经常用到。即时用到,查查即可。这个可能就是所谓的“语言没有思想重要吧”。如果你还不懂,去看看 C#入门经典吧.其次、俄罗斯方块需要绘制图形,这个需要你对C#GDI+有所了解。在其他语言中可能是GDI或 者 API 了,这个你只需要google下即可。如果GDI+编程你还不懂,那么来下载个教程吧。我已经给大家上传到:http:/ plaincopy to clipboardprint?#region定义砖块inti,j,y,x Tricks:i为那块砖,j 为状态,y 为列,x 为行private int,Tricks=(1,0,0,0),100,0,1,0,0,0),(1,0,0,0)1 ,0,0,0,01,0,0,0,0,10,0,0,0)(1,0,0,0),(1,0,0,0),1,0,。,。,1,0,0,0)1,1,1,1,0,0,0,0,0,0,0,0),0,0,0,01,1 AO),1,1,0,0),000,0,0,0,0,0)(1,1,0,0,U,0,0),(0,0,0,0,(0,0,0,0)1,1,0,0),(1,1,0,0),0,0,0,0),0,0,0,0)1,1,0.0,1,1,0.0),(0,0,0,0),(0,0,0,0)(1,0,0,0,(1,1,0,0),(0,1,0,0,(0,0,0,0)(0,1,1,0),1,1,0,0,0,000,0,0,0,0)1,0,0,0),(1,1,0,0,(0,1,0,0),(0,0,0,0)(0,1,1,01,1,1,0,0,(0,0,0,0,(0,0,0,01,1,0.0,0,1,0,0),0,1,0,0,(0,0,0,0)0,0,1,0),(1,1,1,0),(0,0,0,0,(0,0,0,01(1,0,0,0),1,0,0,。,1,1,0,0,0,0,0,0)(1,1,1,0,(1,0,0,0),0,0,0,0,(0,0,0,0);#endregion#region定义背景private int,bgGraoud=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,(0,0,0,0,0,0,0,0,0,0,0,0,0,01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,(0,0,0,0,0,0,0,0,0,0,0,00。,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 AO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,(0,0,0,0,0,0,0,0,0,0,0,0,0,01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,(0,0,0,0,0,0,0,0,0,0,0,0,0,01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,(0,0,0,0,0,0,0,0,0,0,0,0 AO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,01I-#endregion3#region定义砖块inti,j,y,x Tricks:i为那块砖,j为状态,y为列,x为行private inti,Tricks=(1,0,0,01,(1,0,0,0),1,0,0.0),(1,0,0,0)1,1,1,1),0,0,0,0,0,0,0,0),(0,0,0,0)(1,0,0,0),1,0,0,0),(1,0,0,0,1,0,0,0)1,1,1,1),0,0,0.0),0,0,0,0),0,0,0,011,1,0,0,1,1,0,0),(0,0,0,0),0,0,0,0)11,0,0,1,1,0,0),(0,0,0,0),(0,0,0,0)(1,1,0,0),1,1,0,0),0,0,0,0),0,0,0,0,1,1,0,01,(1,1,0,0),0,0,0,01,(0,0,0,0)1,00,0,(1,1,0,0),(0,1,0,0),(0,0,0,0)(0,1,1.0),(1,1,0,0),(0,0,0,0),(0,0,0,0)1,0,0,0,(1,1,0,0),(0,1,0,0),0,0,0,0(0,1,1,0),1,1,0,0),(0,0,0,0),0,0,0,0)1,1,0,0,0,1,0,0,(0,1,0,0),0,0,0,0)0,0,1,0),(1,1,1,0),(0,0,0,0),(0,0,0,0)1,0 AO),10,0,0,0,0,0,0)L I,1,0),1,0。,。,0,00,0,(0,0,0,0#endregion#region定义背景private int bgGraoud=0,0,00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),0,(W W W),0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),0,0,00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0#endregion砖块定义好了,我们还需要定义几个系统在变化的时候需要的全局变量。我在注视中写清楚了,不絮叨了。view plaincopy to clipboardprint?private int,CurrentTrick=new int4,4;当前的砖块/CurrentTrickNum 当前砖块的数目,CurrentStatusNum 当前状态,CurrentX 当前 x,CurrentY 当前 y,Sorce 分数private int CurrentTrickNum,CurrentStatusNum,CurrentX,CurrentY,Sorce;private int TricksNum=4;private int StatusNum=4;private Image mylmage;private Random rand=new Random();private inti,J CurrentTrick=new int4,4;当前的砖块/CurrentTrickNum 当前砖块的数目,CurrentStatusNum 当前状态,CurrentX 当前 x,CurrentY 当前 y,Sorce 分数private int CurrentTrickNum,CurrentStatusNum,CurrentX,CurrentY,Sorce;private int TricksNum=4;private int StatusNum=4;private Image mylmage;private Random rand=new RandomQ;定义好了变量,我们来想想我们的几个函数吧。首先是变化砖块,变化砖块其实就是变化传块的状态,把砖块数组中的状态位进行循环变化即可:view plaincopy to clipboardprint?/III变化方块/summaryprivate void ChangeTricks()if(CurrentStatusNum 3)CurrentStatusNum+;elseCurrentStatusNum=0;for(int y=0;y 4;y+)for(int x=0;x 4;x+)CurrentTricky,x=TricksCurrentTrickNuiTi,CurrentStatusNum,y,x;/变化方块/private void ChangeTricks()(if(CurrentStatusNum 3)CurrentStatusNum+;elseCurrentStatusNum=0;)for(int y=0;y 4;y+)(for(int x=0;x 4;x+)CurrentTricky,xj=TricksCurrentTrickNum,CurrentStatusNum,y,x;再接着是检测砖块是否可以向下移动、向左移动、向右移动。思路很简单。看看他的要运动的方向的背景下个位置是不是为1.如果不是。那么就返回true.否则是false:view plaincopy to clipboardprint?/检测是否可以向下了/private bool CheckIsDown()(for(int y=0;y 4;y+)for(int x=0;x=20)return false;if(x+CurrentX=14)CurrentX=13-x;if(bgGraoudy+CurrentY+1,x+CurrentX=1)(return false;)return true;)/检测是否可以左移/summary/private bool CheckIsLeft()for(int y=0;y 4;y+)(for(int x=0;x 4;x+)(if(CurrentTricky,x=1)(if(x+CurrentX-1 0)(return false;if(bgGraoudy+CurrentY,x+CurrentX-1=1)(return false;return true;)/III检测是否可以右移III summary/private bool GieckIsRight()for(int y=0;y 4;y+)for(int x=0;x=14)(return false;)if(bgGraoudy+CurrentY,x+CurrentX+1=1)(return false;)return true;III/检测是否可以向下了/private bool CheckIsDown()(for(int y=0;y 4;y+)(for(int x=0;x=20)(return false;)if(x+CurrentX=14)(CurrentX=13-x;)if(bgGraoudy+CurrentY+1,x+CurrentXJ=1)return false;return true;/检测是否可以左移/private bool CheckIsLeft()(for(int y=0;y 4;y+)(for(int x=0;x 4;x+)(if(CurrentTricky,x=1)(if(x+CurrentX-1 0)(return false;)if(bgGraoudy+CurrentY,x+CurrentX-1=1)(return false;return true;)/检测是否可以右移/private bool CheckIsRight()(for(int y=0;y 4;y+)(for(int x=0;x=14)return false;if(bgGraoudy+CurrentY,x+CurrentX+1=1)return false;return true;下面是绘制函数:没啥思路,循环画出即可view plaincopy to clipboardprint?private void Daw()Graphics g=Graphics.Fromlmage(mylmage);g.Clear(this.BackColor);for(int bgy=0;bgy 20;bgy+)(for(int bgx=0;bgx 14;bgx+)(if(bgGraoudbgy,bgx=1)(g.FillRectangle(new SolidBrush(Color.Blue),bgx*20,bgy*20,20,20);)绘制当前的图片for(int y=0;y 4;y+)(for(int x=0;x 4;x+)(if(CurrentTricky,xj=1)(g.FillRectangle(new SolidBrush(Color.Blue),(x+CurrentX)*20,(y+CurrentY)*20,20,20);)Graphics gg=panel 1 .CreateGraphics();gg.DrawImage(myImage,0,0);private void Draw()(Graphics g=Graphics.Fromlmage(mylmage);g.Clear(this.BackColor);for(int bgy=0;bgy 20;bgy+)(for(int bgx=0;bgx 14;bgx+)(if(bgGraoudbgy,bgx=1)(g.FillRectangle(new SolidBrush(Color.Blue),bgx*20,bgy*20,20,20);)绘制当前的图片for(int y=0;y 4;y+)(for(int x=0;x 4;x+)(if(CurrentTrickly,x=1)(g.FillRectangle(new SolidBrush(Color.Blue),(x+CuiTentX)*20,(y+CurrentY)*20,20,20);)Graphics gg=panel 1 .CreateGraphics();gg.DrawImage(myImage,0,0);下面的一个函数是比较重要的。向下运动函数。因为基本上向下运动的函数决定了下落的位置:基本思路其实很简单的。先检测是否可以向下下落,如果可以下落就下落了,如果不可以下落,那说明到底了。首先检测当前的坐标是不是为0,如果是,那么说明游戏结束了。否则。检测下。是否有满行的。如果有的,行平移然后并且可以增加积分,这一切完成以后,然后开始下个方块。view plaincopy to clipboardprint?Ill Ill下落方块/summaryprivate void EbwnTricks()(if CheckIsDown()(CurrentY+;)elseif(CurrentY=0)(timerl.StopO;MessageBox.Show(哈哈,你玩玩了)return;)/下落完成,修改背景for(int y=0;y 4;y+)(for(int x=0;x 4;x+)(if(CurrentTricky,x=1)(bgGraoudfCurrentY+y,CurrentX+x=CurrentTricky,x;)CheckSore();BeginTricks();)Draw();/下落方块/private void DownTricks()(if(CheckIsDown()CurrentY+;elseif(CurrentY=0)(timerl.StopO;MessageBox.Show(哈哈,你玩玩了)return;)下落完成,修改背景for(int y=0;y 4;y+)(for(int x=0;x 4;x+)(if(CurrentTricky,x=1)(bgGraoudLCurrentY+y,CurrentX+x=CurrentTricky,xj;)CheckSore();BeginTricks();)Draw();)好像忘记了如何开始向下落的哦。看代码:太容易了,不解释了。view plaincopy to clipboardprint?private void BeginTricks()(随机生成砖码和状态码int i=rand.Next(0,TricksNum);int j=rand.Next(0,StatusNum);CurrentTrickNum=i;CurrentStatusN um=j;分配数组for(int y=0;y 4;y+)(for(int x=0;x 4;x+)CurrentTrickly,xJ=Tricksi,j,y,xJ;CurrentX=0;CurrentY=0;timer l.Start();private void BeginTricks()(随机生成砖码和状态码int i=rand.Next(0,TricksNum);int j=rand.Next(0,StatusNum);CurrentTrickNum=i;CurrentStatusNum=j;分配数组for(int y=0;y 4;y+)(for(int x=0;x -1;y)(bool isFull=true;for(int x=13;x -1;x)(if(bgGraoudly,x=0)(isFull=false;break;if(sFull)(增加积分Sorce=Sorce+100;for(int yy=y;yy 0;yy-)(for(int xx=0;xx -1;y-)|bool isFull=true;for(int x=13;x -1;x)(if(bgGraoudly,xj=0)(isFull=false;break;)if(isFull)增加积分Sorce=Sorce+100;for(int yy=y;yy 0;yy)(for(int xx=0;xx 14;xx+)int temp=bgGraoudlyy-1,xx;bgGraoudfyy,xx=temp;y+;label 1 .Text=Sorce.ToStringO;Draw();还有儿个函数大家都可以看懂的,我就不讲解了。我把所有的代码都贴一遍。另外把所有的图片和源文件打包后上传到csd n,请大家下载。代力马下载地址:http:/ plaincopy to clipboardprint?using ystem;using stem.Collections.Generic;using stem.ComponentModel;using System.Data;using stem.Drawing;using stem.Linq;using stem.Text;using$stem.Windows.Fonns;namespace Tetris(public partial class Forml:Formpublic form 1()InitializeComponent();)#region定义砖块inti,j,y,x Tricks:i为 那 块 石 专,j 为状态,y 为列,x 为行private int,J Tricks=(1,0,0,0),1,0,0.0,1,0,0,0),L0,0,01,1/1,0,0,0,0),(0,0,0.0),(0,0,0,0)1,0,0.0),(1,0,0,0),1,0,0,。,1,0,0,01,1,1,1),0,0,0,0,(0,0,0,01,(0,0,0,0)11,0,0,1,1,0,0,0,0,0,01,(0,0,0,0)(1,1,0,0),1,1,0,0),0,0,0,0),0,0,0,0U,0,0),(1,1,0,0),0,0,0。,(0,0,0,0)1,1,0,0,1,1,0,0,(0,0,0,0,0,0,0,0)(1,0,0,0),1,1,0,0),0,1,0,01,(0,0,0,0)(0,1,1,01,1,1,0,0,0,0,0,0),(0,0,0,0)(1,0,0,0),(1,1,0.0,(0,1,0,0),(0,0,0,0)(0,1,1,0),1,1,0,0,0,0,0,01,(0,0,0,0)1,1,0,0),0,1,0,0),(0,1,0,0),0,0,0,0)0,0,1,0),1,1,1,0,(0,0,0,0),(0,0,0,0)1,0,0,0,1,0,0,0,(1,1,0,0),0,0,0,0(1,1,1,0),(1,0,0,0),00,0,0,(0,0,0,0);#endregion#region定义背景private int,bgGraoud=0,0,0,0,0,0,0,0,00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,(W W W,0,0,00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,(W),0,(W),0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),0,0,0,0,0,0 AO,0,0,0,0 AO),0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 AO,0,0,0,0,0,0 AO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);#endregionprivate int,CurrentTrick=new int4,4;当前的砖块/CurrentTrickNum 当前石专块的数目,CurrentStatusNum 当前状态,CurrentX 当前 x,CurrentY 当前 y,Sorce 分数private int CurrentTrickNum,CurrentStatusNum,CurrentX,CurrentY,Sorce;private int TricksNum=4;private int StatusNum=4;private Image mylmage;private Random rand=new Random();private void Form 1 _Load(object sender,EventArgs e)初始化mylmage=new Bitmap(panel 1 .Width,panel 1.Height);Sorce=0;protected overnde void OnPaint(PaintEventArgs e)(Draw();base.OnPaint(e);)private void button l_Click(object sender,EventArgs e)(for(int y=0;y 20;y+)(for(int x=0;x 14;x+)(bgGraoudy,xj=0;)timer 1.Interval=1000;BeginTricks();this.Focus();/III随机生成方块和状态/private void BeginTricks()(随机生成砖码和状态码int i=rand.Next(0,TricksNum);int j=rand.Next(0,StatusNum);CurrentTrickNum=i;CurrentStatusNum=j;分配数组for(int y=0;y 4;y+)(for(int x=0;x 4;x+)CurrentTricky,xJ=Tricksli,j,y,xJ;)CurrentX=0;CurrentY=0;timer l.Start();)/变化方块/summaryprivate void ChangeTricks()(if(CurrentStatusNum 3)(CurrentStatusNum+;)else(CurrentStatusNum=0;)for(int y=0;y 4;y+)(for(int x=0;x 4;x+)(CurrentTricky,xj=TricksCurrentTrickNum,CurrentStatusNum,y,xj;)III/下落方块/summaryprivate void DownTricks()if(ZhecklsDownO)(Current Y+;else(if(CurrentY=0)(timer l.StopO;MessageBox.Show(哈哈,你玩玩了)return;)下落完成,修改背景for(int y=0;y 4;y+)(for(int x=0;x 4;x+)if(CurrentTricky,x=1)bgGraoudCurrentY+y,CurrentX+x=CurrentTricky,x;)CheckSore();BeginTricks();)Draw();/检测是否可以向下了/4summary/private bool CheckIsDown()for(int y=0;y 4;y+)(for(int x=0;x=20)(return false;)if(x+CurrentX=14)(CurrentX=13-x;)if(bgGraoudy+CurrentY+1,x+CurrentX=1)(return false;)return true;/检测是否可以左移III/private bool CheckIsLeft()(for(int y=0;y 4;y+)(for(int x=0;x 4;x+)(if(CurrentTricky,x=1)(if(x+CurrentX-1 0)return false;)if(bgGraoudfy+CurrentY,x+CurrentX-1=1)(return false;)return true;)III/检测是否可以右移III summary/private bool CheckIsRight()(for(int y=0;y 4;y+)(for(int x=0;x=14)(return false;)if(bgGraoudly+CurrentY,x+CurrentX+1 J=1)return false;return true;private void Draw()(Graphics g=Graphics.Fromlmage(mylmage);g.Clear(this.BackColor);for(int bgy=0;bgy 20;bgy+)(for(int bgx=0;bgx 14;bgx+)(if(bgGraoudlbgy,bgx=1)(g.FillRectangle(new SolidBrush(Color.Blue),bgx*20,bgy*20,20,20);)绘制当前的图片for(int y=0;y 4;y+)(for(int x=0;x -1;y-)bool isFull=true;for(int x=13;x -1;x-)(if(bgGraoudy,x=0)(isFull=false;break;)i fsFull)(增加积分Sorce=Sorce+100;for(int yy=y;yy 0;yy-)(for(int xx=0;xx 14;xx+)(int temp=bgGraoudyy-1,xxbgGraoudyy,xxj=temp;)y+;label 1 .Text=Sorce.ToStringO;Draw();private void button2_Click(object sender,EventArgs e)(if(button2.Text=暂停游戏”)(button2.Text=开始游戏”;timer