(原创)一种用C#编写俄罗斯方块游戏的方法

    上个周末,突然莫名其妙的想做个什么小游戏娱乐一下,就写了个简单的俄罗斯方块游戏,做到一半后由于较忙加上没心情去做,一直没时间完成,这个周末终于有点时间,总算是差不多了。贴到这里与大家一起分享一下。希望能起到抛砖引玉的作用,呵呵~。我最后会把源代码和把编译好之后的游戏程序贴到到这里,不感兴趣的也可以下载过去,偶尔玩一下小时候最幼稚的游戏来解解闷,呵呵。
    先来个游戏截图:(点击源代码打包下载)

 

     我是在visual studio 2005下用C#做的,主要是觉得C#是C风格的语法,比较喜欢,就选它了。用的是.net的GDI+类库,当然也可以用其它语言工具来实现,如java中的swing,VC中的GDI都可以。
    先介绍一下我对整个游戏的算法思想,估计是最容易想到的也是最笨的方法(没办法,我也是第一次写,呵呵)。大家都知道,这种游戏主要的规则就是,就是某个方块模型在一个规定的区域里面,固定的下落,在下落的过程中,游戏者会左右移动操作或是调整它的形状,其它的一些包括加分、升级都是一些后续的问题。
    每一个方块模型都有一个共同的特点,那就是,它们都是由四个小矩形组成,排列成直线或是竖线或是T字形等等,这可以用四个矩形排列时的相对坐标位置不同来表示。我的总体做法就是把那个游戏区的黑色区域划分成很多个小矩形,目前是:12 X 21,当某个模型在区域中显示的时候,就把相应的矩形着成白色,同时打上标记。当模型方块在下落的过程中,每下移一行,就把原来的那一行重新着成黑色,去掉标记,把方块所在的新的一行所占用的矩形区域着成白色,同时打上标记。这样就达到了下落一行的效果,左移和右移与这个思想一样。再一个重要的问题就是变换的问题,例如方块模型从一个直线型变成一个竖线型,应该怎么办呢?这个问题从本质上来说仍然是对相应的矩形区域着色的问题,很自然的想法就是把原来的直线所在的矩形区域着成黑色,去掉标记,然后把竖线应该要显示的区域着成白色,同时打上标记,这样就达到了一个变换的效果。具体是怎么实现的,感兴趣的可以去看一下源代码,也许你会发现我的办法很笨拙,呵呵。那也是没办法的事。
    最后一个问题就是如何判断下落的方块在什么情况下由于周围所在的区域已经被占用了,导致不能再下落、不能左右移动的问题。这个问题复杂一些,刚刚在着色的时候,我的做法就是把着成白色的做了标记,空白的地方没有做标记(其实就是一个布尔型变量),只要在移动时判断一下是否有标记就行了,具体也可以去看源代码。
   还有一些问题,如一行被填满后,自动消失的问题,这应该比较简单,做法就是把此行先着成黑色,去掉标记,然后依次把相邻的上一行的信息移到这一行来,相信用程序控制起来比较容易实现。
   最后,方块的变换,左右移动的操作都是一些键盘消息,下落的过程用一个时间tick来完成,当然也可以单独用一个线程来处理。相信知道windows应用程序的人应该对这些不陌生。
   最后会把生成好了的应用程序和整个VS2005工程文件夹压缩好后贴上来,下载后,直接开以打开,感兴趣的可以下载过来玩一下:)
下面看源代码:
一共有这么几个文件:Form1.cs,Form1.Designer.cs,Form2.cs,Form2.Designer.cs,Program.cs.
对VS2005的C#windows应用程序的文件组织熟悉的人应该知道它们分别代表什么。
Form1.cs:游戏逻辑的主程序
Form1.Designer.cs:游戏主界面的界面程序代码,由VS2005自动生成
Form2.cs:游戏键位设置的主程序
Form2.Designer.cs:游戏键位设置的界面,由VS2005自动生成
Program.cs:整个应用程序的启动入口程序,相当于main()函数,由VS2005自动生成。

Form1.cs文件:

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace RassionBlock
{
    
public partial class mainform : Form
    
{
        
public Keys left = Keys.Left;////这几个为游戏的键位设置,因为是在Form2中设置,这里定义成public访问属性
        public Keys right = Keys.Right;
        
public Keys down = Keys.Down;
        
public Keys change = Keys.Space;
        
public Keys start_puase = Keys.F2;
        
public Keys setkeys = Keys.F3;
        
public int grade = 1;///游戏极别,这个级别是控制timer的tick周期的快慢
        public Keys newgame = Keys.F4;

        
private const int x1 = 20;//黑色游戏区域的起始x坐标,以下类推
        private const int x2 = 260;
        
private const int y1 = 20;
        
private const int y2 = 440;
        
private const int rows = 21;//行数
        private const int cols = 12;//列数
        private struct unitrect  //每一个方块单元由一个矩形和一个标记位组成,标记位用于记录此单元是否被填充
        {
            
public bool flag;////flag为true时,表明此区域已经被填充了
            public Rectangle rect;
        }
;
        
private unitrect[,] urect;//二维数组,用于表示所有的矩形方框
        private struct moder  //方块模型,每一个模型都是由四个小方块组成
        {
            
public int x1;
            
public int x2;
            
public int x3;
            
public int x4;
            
public int y1;
            
public int y2;
            
public int y3;
            
public int y4;
        }
;
        
private moder[] mymoder;//方块模型
        private int currentIndex;//记录当前下落的方块模型的索引
        private bool rebuild;
        
private enum zouyf_flag { DOWN, LEFT, RIGHT };//任何方块模型在移动时,只能要向左、向右、向下三种操作,定义枚举类型
        private int currentcols;  //当前方块下落所在的列
        private int currentrows;  //当前方块下落所在的行
        private Random rand;
        
private bool sync = false;//用于控制当方块左右移动时与时间tick同步的问题,设计思想是,当方块正在判断能否下落时,锁定左右移动操作。
        private int nextIndex;     //记录下一次将要出现的方块模型的索引
        SolidBrush wbrush;         // 白色画刷
        SolidBrush bbrush;          //黑色
        SolidBrush gbrush;          //背景色
        private int totalscore = 0;  //总得分
        private int totaltime = 0;   //总耗时
        private float highest = 0;   //历史最高分数时间比
        public mainform()
        
{
            InitializeComponent();
        }


        
private void Form1_Paint(object sender, PaintEventArgs e)
        
{
            Graphics formgs 
= e.Graphics;
            formgs.FillRegion(bbrush, 
new Region(new Rectangle(x1, y1, x2 - x1 + 1, y2 - y1 + 1)));
            
for (int i = 0; i < rows; i++)//窗口被拖动、隐藏等时,需要重绘
                for (int j = 0; j < cols; j++)
                
{
                    
if (urect[i, j].flag)
                        formgs.FillRectangle(wbrush, urect[i, j].rect);
                }

            
////重绘下一次将要出现的next方块
            formgs.FillRectangle(bbrush, new Rectangle(300 + 20 * mymoder[nextIndex].x1, 40 + 20 * mymoder[nextIndex].y1, 1919));
            formgs.FillRectangle(bbrush, 
new Rectangle(300 + 20 * mymoder[nextIndex].x2, 40 + 20 * mymoder[nextIndex].y2, 1919));
            formgs.FillRectangle(bbrush, 
new Rectangle(300 + 20 * mymoder[nextIndex].x3, 40 + 20 * mymoder[nextIndex].y3, 1919));
            formgs.FillRectangle(bbrush, 
new Rectangle(300 + 20 * mymoder[nextIndex].x4, 40 + 20 * mymoder[nextIndex].y4, 1919));
            formgs.Dispose();
        }


        
private void Form1_Load(object sender, EventArgs e)
        
{
            initRect();
            initMymoder();
            wbrush 
= new SolidBrush(Color.White);
            bbrush 
= new SolidBrush(Color.Black);
            gbrush 
= new SolidBrush(Color.Gainsboro);
            mytimer.Enabled 
= true;
            score_time_timer.Enabled 
= true;
            rand 
= new Random();
            nextIndex 
= rand.Next(019);
            rebuild 
= true;//用于判断是不是最新构建的模型,在tick中会用到
        }


        
private void initRect()
        
{
            urect 
= new unitrect[rows, cols];
            
int unit = (x2 - x1) / cols;
            
for (int i = 0; i < rows; i++)
                
for (int j = 0; j < cols; j++)
                
{
                    urect[i, j].flag 
= false;
                    urect[i, j].rect 
= new Rectangle(x1 + unit * j + 1, y1 + unit * i + 1, unit - 1, unit - 1);
                }

        }


        
private void initMymoder()////构建方块模型,一共有19种,每一个模型由四个小方块组成,x,y用于记录每个小方块的顶点坐标
        {
            mymoder 
= new moder[19];

            
////横直线的坐标分布
            mymoder[0].x1 = 0;
            mymoder[
0].x2 = 1;
            mymoder[
0].x3 = 2;
            mymoder[
0].x4 = 3;
            mymoder[
0].y1 = 0;
            mymoder[
0].y2 = 0;
            mymoder[
0].y3 = 0;
            mymoder[
0].y4 = 0;

            
////竖直线的坐标分布,下面的类似
            mymoder[1].x1 = 0;
            mymoder[
1].x2 = 0;
            mymoder[
1].x3 = 0;
            mymoder[
1].x4 = 0;
            mymoder[
1].y1 = 0;
            mymoder[
1].y2 = 1;
            mymoder[
1].y3 = 2;
            mymoder[
1].y4 = 3;


            
////L形的坐标分布,接下来的三个为它的旋转后的模型
            mymoder[2].x1 = 0;
            mymoder[
2].x2 = 0;
            mymoder[
2].x3 = 0;
            mymoder[
2].x4 = 1;
            mymoder[
2].y1 = 0;
            mymoder[
2].y2 = 1;
            mymoder[
2].y3 = 2;
            mymoder[
2].y4 = 2;

            mymoder[
3].x1 = 0;
            mymoder[
3].x2 = 1;
            mymoder[
3].x3 = 2;
            mymoder[
3].x4 = 0;
            mymoder[
3].y1 = 0;
            mymoder[
3].y2 = 0;
            mymoder[
3].y3 = 0;
            mymoder[
3].y4 = 1;

            mymoder[
4].x1 = 0;
            mymoder[
4].x2 = 1;
            mymoder[
4].x3 = 1;
            mymoder[
4].x4 = 1;
            mymoder[
4].y1 = 0;
            mymoder[
4].y2 = 0;
            mymoder[
4].y3 = 1;
            mymoder[
4].y4 = 2;

            mymoder[
5].x1 = 2;
            mymoder[
5].x2 = 0;
            mymoder[
5].x3 = 1;
            mymoder[
5].x4 = 2;
            mymoder[
5].y1 = 0;
            mymoder[
5].y2 = 1;
            mymoder[
5].y3 = 1;
            mymoder[
5].y4 = 1;

            mymoder[
6].x1 = 1;
            mymoder[
6].x2 = 1;
            mymoder[
6].x3 = 0;
            mymoder[
6].x4 = 1;
            mymoder[
6].y1 = 0;
            mymoder[
6].y2 = 1;
            mymoder[
6].y3 = 2;
            mymoder[
6].y4 = 2;

            mymoder[
7].x1 = 0;
            mymoder[
7].x2 = 0;
            mymoder[
7].x3 = 1;
            mymoder[
7].x4 = 2;
            mymoder[
7].y1 = 0;
            mymoder[
7].y2 = 1;
            mymoder[
7].y3 = 1;
            mymoder[
7].y4 = 1;

            mymoder[
8].x1 = 0;
            mymoder[
8].x2 = 1;
            mymoder[
8].x3 = 0;
            mymoder[
8].x4 = 0;
            mymoder[
8].y1 = 0;
            mymoder[
8].y2 = 0;
            mymoder[
8].y3 = 1;
            mymoder[
8].y4 = 2;

            mymoder[
9].x1 = 0;
            mymoder[
9].x2 = 1;
            mymoder[
9].x3 = 2;
            mymoder[
9].x4 = 2;
            mymoder[
9].y1 = 0;
            mymoder[
9].y2 = 0;
            mymoder[
9].y3 = 0;
            mymoder[
9].y4 = 1;

            
////Z字形的坐标分布
            mymoder[10].x1 = 0;
            mymoder[
10].x2 = 1;
            mymoder[
10].x3 = 1;
            mymoder[
10].x4 = 2;
            mymoder[
10].y1 = 0;
            mymoder[
10].y2 = 0;
            mymoder[
10].y3 = 1;
            mymoder[
10].y4 = 1;

            mymoder[
11].x1 = 1;
            mymoder[
11].x2 = 0;
            mymoder[
11].x3 = 1;
            mymoder[
11].x4 = 0;
            mymoder[
11].y1 = 0;
            mymoder[
11].y2 = 1;
            mymoder[
11].y3 = 1;
            mymoder[
11].y4 = 2;

            mymoder[
12].x1 = 1;
            mymoder[
12].x2 = 2;
            mymoder[
12].x3 = 0;
            mymoder[
12].x4 = 1;
            mymoder[
12].y1 = 0;
            mymoder[
12].y2 = 0;
            mymoder[
12].y3 = 1;
            mymoder[
12].y4 = 1;

            mymoder[
13].x1 = 0;
            mymoder[
13].x2 = 0;
            mymoder[
13].x3 = 1;
            mymoder[
13].x4 = 1;
            mymoder[
13].y1 = 0;
            mymoder[
13].y2 = 1;
            mymoder[
13].y3 = 1;
            mymoder[
13].y4 = 2;

            mymoder[
14].x1 = 0;
            mymoder[
14].x2 = 1;
            mymoder[
14].x3 = 0;
            mymoder[
14].x4 = 1;
            mymoder[
14].y1 = 0;
            mymoder[
14].y2 = 0;
            mymoder[
14].y3 = 1;
            mymoder[
14].y4 = 1;

            mymoder[
15].x1 = 1;
            mymoder[
15].x2 = 0;
            mymoder[
15].x3 = 1;
            mymoder[
15].x4 = 1;
            mymoder[
15].y1 = 0;
            mymoder[
15].y2 = 1;
            mymoder[
15].y3 = 1;
            mymoder[
15].y4 = 2;

            mymoder[
16].x1 = 1;
            mymoder[
16].x2 = 0;
            mymoder[
16].x3 = 1;
            mymoder[
16].x4 = 2;
            mymoder[
16].y1 = 0;
            mymoder[
16].y2 = 1;
            mymoder[
16].y3 = 1;
            mymoder[
16].y4 = 1;

            mymoder[
17].x1 = 0;
            mymoder[
17].x2 = 0;
            mymoder[
17].x3 = 1;
            mymoder[
17].x4 = 0;
            mymoder[
17].y1 = 0;
            mymoder[
17].y2 = 1;
            mymoder[
17].y3 = 1;
            mymoder[
17].y4 = 2;

            mymoder[
18].x1 = 0;
            mymoder[
18].x2 = 1;
            mymoder[
18].x3 = 2;
            mymoder[
18].x4 = 1;
            mymoder[
18].y1 = 0;
            mymoder[
18].y2 = 0;
            mymoder[
18].y3 = 0;
            mymoder[
18].y4 = 1;
        }


        
//这个函数的作用是对于每一个方块模型,得到它最左边、最右边和最下边的坐标,在方块的变换和移动时要用到
        private void getMinAndMaxXY(moder tempmoder, ref int minx, ref int maxx, ref int maxy)
        
{
            minx 
= maxx = tempmoder.x1;
            maxy 
= tempmoder.y1;

            
if (minx > tempmoder.x2)
                minx 
= tempmoder.x2;
            
if (minx > tempmoder.x3)
                minx 
= tempmoder.x3;
            
if (minx > tempmoder.x4)
                minx 
= tempmoder.x4;

            
if (maxx < tempmoder.x2)
                maxx 
= tempmoder.x2;
            
if (maxx < tempmoder.x3)
                maxx 
= tempmoder.x3;
            
if (maxx < tempmoder.x4)
                maxx 
= tempmoder.x4;

            
if (maxy < tempmoder.y2)
                maxy 
= tempmoder.y2;
            
if (maxy < tempmoder.y3)
                maxy 
= tempmoder.y3;
            
if (maxy < tempmoder.y4)
                maxy 
= tempmoder.y4;
        }


        
private void mytimer_Tick(object sender, EventArgs e)
        
{
            sync 
= false;//用于控制方块的移动操作与时间tick的同步问题,可以把tick看成是当独运行的一个线程
            Graphics gs = this.CreateGraphics();
            
if (rebuild)//rebuild用于判断是否要构建新的方块,当前一个方块不能再下落时,构建新的方块
            {
                currentIndex 
= nextIndex;
                nextIndex 
=  rand.Next(019);//得到下一次将要出现的方块模型的索引
                ////更新next方块提示
                gs.FillRectangle(gbrush, new Rectangle(300 + 20 * mymoder[currentIndex].x1, 40 + 20 * mymoder[currentIndex].y1, 2020));
                gs.FillRectangle(gbrush, 
new Rectangle(300 + 20 * mymoder[currentIndex].x2, 40 + 20 * mymoder[currentIndex].y2, 2020));
                gs.FillRectangle(gbrush, 
new Rectangle(300 + 20 * mymoder[currentIndex].x3, 40 + 20 * mymoder[currentIndex].y3, 2020));
                gs.FillRectangle(gbrush, 
new Rectangle(300 + 20 * mymoder[currentIndex].x4, 40 + 20 * mymoder[currentIndex].y4, 2020));
                gs.FillRectangle(bbrush, 
new Rectangle(300 + 20 * mymoder[nextIndex].x1, 40 + 20 * mymoder[nextIndex].y1, 1919));
                gs.FillRectangle(bbrush, 
new Rectangle(300 + 20 * mymoder[nextIndex].x2, 40 + 20 * mymoder[nextIndex].y2, 1919));
                gs.FillRectangle(bbrush, 
new Rectangle(300 + 20 * mymoder[nextIndex].x3, 40 + 20 * mymoder[nextIndex].y3, 1919));
                gs.FillRectangle(bbrush, 
new Rectangle(300 + 20 * mymoder[nextIndex].x4, 40 + 20 * mymoder[nextIndex].y4, 1919));
                currentrows 
= 0;
                
if (currentIndex == 0 || currentIndex == 3 || currentIndex == 5 || currentIndex == 7 || currentIndex == 9 || currentIndex == 10 || currentIndex == 12 || currentIndex == 16 || currentIndex == 18)
                    currentcols 
= cols / 2 - 2;////这么做的目的是为了新出现的方块总是出现在顶部的中间,看起来美观一些
                else
                    currentcols 
= cols / 2 - 1;
                
////新的方块不能再构建时,则game over
                if (urect[currentrows + mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].flag ||
                    urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].flag ||
                    urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].flag ||
                    urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].flag)
                
{
                    mytimer.Enabled 
= false;
                    score_time_timer.Enabled 
= false;
                    MessageBox.Show(
"game over");
                }

                gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].rect);
                gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].rect);
                gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].rect);
                gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].rect);
                urect[
0 + mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].flag = true;
                urect[
0 + mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].flag = true;
                urect[
0 + mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].flag = true;
                urect[
0 + mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].flag = true;
                rebuild 
= false;
            }

            
else
            
{
                
if (judgePaintEnable(currentrows, currentcols, currentIndex, zouyf_flag.DOWN))//判断能否下落,不然则rebuild新模型
                {
                    gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].rect);
                    gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].rect);
                    gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].rect);
                    gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].rect);
                    urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].flag = false;
                    urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].flag = false;
                    urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].flag = false;
                    urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].flag = false;
                    currentrows 
+= 1;//下落一行之后,当前行自增1
                    gs.FillRectangle(wbrush, urect[currentrows + mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].rect);
                    gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].rect);
                    gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].rect);
                    gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].rect);
                    urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].flag = true;
                    urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].flag = true;
                    urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].flag = true;
                    urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].flag = true;
                }

                
else
                
{
                    sync 
= true;//这个同步控制的变量很重要,方块在此次tick中不能再下落时,则不能左右移动方块,在左右移动操作中会看到此变量的用法
                    clearRect(gs);//当方块落定后检查是否满足加分消去此行的条件
                    rebuild = true;////指示在下一次tick中构建新的方块
                }

            }

            gs.Dispose();
        }


        
private void clearRect(Graphics gs)////当方块落定后,判断它所占用的几行中,是否有可以消分的行
        {
            
int minx = 0, maxx = 0, maxy = 0, temprows = 0, scoreCount = 0;
            
bool clearFlag = true;
            
bool topFlag = true;
            getMinAndMaxXY(mymoder[currentIndex], 
ref minx, ref maxx, ref maxy);
            
for (int i = 0; i <= maxy; i++)
            
{
                clearFlag 
= true;
                
for (int j = 0; j < cols; j++)
                
{
                    
if (!urect[currentrows + i, j].flag)
                    
{
                        clearFlag 
= false;//此行有没填充的区域时,则不满足消去条件
                        break;
                    }

                }

                
if (clearFlag)//此行满足消去的条件,算法思想为,从下往上,让每行依次下落
                {
                    scoreCount 
+= 1;
                    temprows 
= currentrows + i - 1;
                    topFlag 
= true;
                    
while (temprows >= 0 && topFlag)
                    
{
                        topFlag 
= false;////用于判断此行是不是空行
                        for (int j = 0; j < cols; j++)//依次把相邻的上一行拷贝到下一行
                        {
                            
if (urect[temprows, j].flag)
                            
{
                                gs.FillRectangle(wbrush, urect[temprows 
+ 1, j].rect);
                                urect[temprows 
+ 1, j].flag = true;
                                topFlag 
= true;//此行还有已经被着色的方框,则此行肯定不是空行
                            }

                            
else
                            
{
                                gs.FillRectangle(bbrush, urect[temprows 
+ 1, j].rect);
                                urect[temprows 
+ 1, j].flag = false;
                            }

                        }

                        temprows 
= temprows - 1;
                    }

                    
for (int j = 0; j < cols; j++)//原来最上面的一行下降一行后,最上面的一行用完全空行代替
                    {
                        gs.FillRectangle(bbrush, urect[temprows 
+ 1, j].rect);
                        urect[temprows 
+ 1, j].flag = false;
                    }

                }

            }

            
if (scoreCount == 1)//加分
                totalscore += 100;
            
else if (scoreCount == 2)
                totalscore 
+= 300;
            
else if (scoreCount == 3)
                totalscore 
+= 800;
            
else if (scoreCount == 4)
                totalscore 
+= 1600;
            
this.scoreLable.Text = totalscore + "";
        }


        
private void Form1_KeyDown(object sender, KeyEventArgs e)
        
{
            Graphics gs 
= this.CreateGraphics();
            
if (e.KeyCode == change)
            
{
                
if (sync || !mytimer.Enabled)
                    
return;
                
int tempindex = currentIndex, temprows = currentrows, tempcols = currentcols, minx = 0, maxx = 0, maxy = 0;
                
if (currentIndex == 14)////图形为正方形方块时,直接退出
                    return;
                
////直线图形在变换时,由于变换前后的起始点发生变化,因此单独处理
                else if (currentIndex == 0)//图形为横直线时,变换为竖直线
                {
                   
if (currentrows < 2)
                        
return;
                    currentrows 
-= 2;
                    currentcols 
+= 2;
                    currentIndex 
= 1;
                    getMinAndMaxXY(mymoder[currentIndex], 
ref minx, ref maxx, ref maxy);
                    
if (currentrows < 0 || currentrows + maxy >= rows - 1 || currentcols + maxx > cols - 1)
                    
{
                        currentrows 
= temprows;
                        currentcols 
= tempcols;
                        currentIndex 
= tempindex;
                        
return;
                    }


                    urect[temprows 
+ mymoder[tempindex].y1, tempcols + mymoder[tempindex].x1].flag = false;
                    urect[temprows 
+ mymoder[tempindex].y2, tempcols + mymoder[tempindex].x2].flag = false;
                    urect[temprows 
+ mymoder[tempindex].y3, tempcols + mymoder[tempindex].x3].flag = false;
                    urect[temprows 
+ mymoder[tempindex].y4, tempcols + mymoder[tempindex].x4].flag = false;
                    
////判断是否满足变换条件,算法思想为判断是否有足够的空间让变换后的模型显示,
                    if (urect[currentrows + mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].flag ||
                        urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].flag ||
                        urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].flag ||
                        urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].flag)
                    
{
                        currentIndex 
= tempindex;
                        currentrows 
= temprows;
                        currentcols 
= tempcols;
                        urect[temprows 
+ mymoder[tempindex].y1, tempcols + mymoder[tempindex].x1].flag = true;
                        urect[temprows 
+ mymoder[tempindex].y2, tempcols + mymoder[tempindex].x2].flag = true;
                        urect[temprows 
+ mymoder[tempindex].y3, tempcols + mymoder[tempindex].x3].flag = true;
                        urect[temprows 
+ mymoder[tempindex].y4, tempcols + mymoder[tempindex].x4].flag = true;
                        
return;
                    }

                    
else
                    
{
                        gs.FillRectangle(bbrush, urect[temprows 
+ mymoder[tempindex].y1, tempcols + mymoder[tempindex].x1].rect);
                        gs.FillRectangle(bbrush, urect[temprows 
+ mymoder[tempindex].y2, tempcols + mymoder[tempindex].x2].rect);
                        gs.FillRectangle(bbrush, urect[temprows 
+ mymoder[tempindex].y3, tempcols + mymoder[tempindex].x3].rect);
                        gs.FillRectangle(bbrush, urect[temprows 
+ mymoder[tempindex].y4, tempcols + mymoder[tempindex].x4].rect);
                        urect[temprows 
+ mymoder[tempindex].y1, tempcols + mymoder[tempindex].x1].flag = false;
                        urect[temprows 
+ mymoder[tempindex].y2, tempcols + mymoder[tempindex].x2].flag = false;
                        urect[temprows 
+ mymoder[tempindex].y3, tempcols + mymoder[tempindex].x3].flag = false;
                        urect[temprows 
+ mymoder[tempindex].y4, tempcols + mymoder[tempindex].x4].flag = false;

                        gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].rect);
                        gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].rect);
                        gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].rect);
                        gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].rect);
                        urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].flag = true;
                        urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].flag = true;
                        urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].flag = true;
                        urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].flag = true;

                        tempindex 
= currentIndex;
                        temprows 
= currentrows;
                        tempcols 
= currentcols;
                        gs.Dispose();
                        
return;
                    }

                }

                
else if (currentIndex == 1)//图形为竖直线时,整个算法思想与上面的一样
                {
                    currentrows 
+= 2;
                    currentcols 
-= 2;
                    currentIndex 
= 0;
                    getMinAndMaxXY(mymoder[currentIndex], 
ref minx, ref maxx, ref maxy);
                    
if (currentrows > 20 || currentcols < 0 || currentcols + maxx > cols - 1 || currentrows + maxy > rows - 1)
                    
{
                        currentrows 
= temprows;
                        currentcols 
= tempcols;
                        currentIndex 
= tempindex;
                        
return;
                    }


                    urect[temprows 
+ mymoder[tempindex].y1, tempcols + mymoder[tempindex].x1].flag = false;
                    urect[temprows 
+ mymoder[tempindex].y2, tempcols + mymoder[tempindex].x2].flag = false;
                    urect[temprows 
+ mymoder[tempindex].y3, tempcols + mymoder[tempindex].x3].flag = false;
                    urect[temprows 
+ mymoder[tempindex].y4, tempcols + mymoder[tempindex].x4].flag = false;
                    
if (urect[currentrows + mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].flag ||
                        urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].flag ||
                        urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].flag ||
                        urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].flag)
                    
{
                        currentIndex 
= tempindex;
                        currentrows 
= temprows;
                        currentcols 
= tempcols;
                        urect[temprows 
+ mymoder[tempindex].y1, tempcols + mymoder[tempindex].x1].flag = true;
                        urect[temprows 
+ mymoder[tempindex].y2, tempcols + mymoder[tempindex].x2].flag = true;
                        urect[temprows 
+ mymoder[tempindex].y3, tempcols + mymoder[tempindex].x3].flag = true;
                        urect[temprows 
+ mymoder[tempindex].y4, tempcols + mymoder[tempindex].x4].flag = true;
                        
return;
                    }

                    
else
                    
{
                        gs.FillRectangle(bbrush, urect[temprows 
+ mymoder[tempindex].y1, tempcols + mymoder[tempindex].x1].rect);
                        gs.FillRectangle(bbrush, urect[temprows 
+ mymoder[tempindex].y2, tempcols + mymoder[tempindex].x2].rect);
                        gs.FillRectangle(bbrush, urect[temprows 
+ mymoder[tempindex].y3, tempcols + mymoder[tempindex].x3].rect);
                        gs.FillRectangle(bbrush, urect[temprows 
+ mymoder[tempindex].y4, tempcols + mymoder[tempindex].x4].rect);
                        urect[temprows 
+ mymoder[tempindex].y1, tempcols + mymoder[tempindex].x1].flag = false;
                        urect[temprows 
+ mymoder[tempindex].y2, tempcols + mymoder[tempindex].x2].flag = false;
                        urect[temprows 
+ mymoder[tempindex].y3, tempcols + mymoder[tempindex].x3].flag = false;
                        urect[temprows 
+ mymoder[tempindex].y4, tempcols + mymoder[tempindex].x4].flag = false;

                        gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].rect);
                        gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].rect);
                        gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].rect);
                        gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].rect);
                        urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].flag = true;
                        urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].flag = true;
                        urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].flag = true;
                        urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].flag = true;

                        tempindex 
= currentIndex;
                        temprows 
= currentrows;
                        tempcols 
= currentcols;
                        gs.Dispose();
                        
return;
                    }

                }

                
else//其它图形的变换,总是以顺时针方向进行旋转,与上面的变换思想一样,能变换,则更改模型索引
                {
                    tempindex 
= currentIndex;
                    
////Z字形图形的变换
                    if (currentIndex == 11 || currentIndex == 13)
                        currentIndex 
= currentIndex - 1;
                    
else if (currentIndex == 5 || currentIndex == 9 || currentIndex == 13 || currentIndex == 18)
                        currentIndex 
= currentIndex - 3;
                    
else
                        currentIndex 
= currentIndex + 1;
                    getMinAndMaxXY(mymoder[currentIndex], 
ref minx, ref maxx, ref maxy);
                    
if (currentcols + maxx > cols - 1 || currentrows + maxy > rows - 1)
                    
{
                        currentIndex 
= tempindex;
                        
return;
                    }

                    urect[currentrows 
+ mymoder[tempindex].y1, currentcols + mymoder[tempindex].x1].flag = false;
                    urect[currentrows 
+ mymoder[tempindex].y2, currentcols + mymoder[tempindex].x2].flag = false;
                    urect[currentrows 
+ mymoder[tempindex].y3, currentcols + mymoder[tempindex].x3].flag = false;
                    urect[currentrows 
+ mymoder[tempindex].y4, currentcols + mymoder[tempindex].x4].flag = false;
                    
////判断是否满足变换的条件
                    if (urect[currentrows + mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].flag ||
                        urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].flag ||
                        urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].flag ||
                        urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].flag)
                    
{
                        currentIndex 
= tempindex;
                        urect[currentrows 
+ mymoder[tempindex].y1, currentcols + mymoder[tempindex].x1].flag = true;
                        urect[currentrows 
+ mymoder[tempindex].y2, currentcols + mymoder[tempindex].x2].flag = true;
                        urect[currentrows 
+ mymoder[tempindex].y3, currentcols + mymoder[tempindex].x3].flag = true;
                        urect[currentrows 
+ mymoder[tempindex].y4, currentcols + mymoder[tempindex].x4].flag = true;
                    }

                    
else
                    
{
                        gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[tempindex].y1, currentcols + mymoder[tempindex].x1].rect);
                        gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[tempindex].y2, currentcols + mymoder[tempindex].x2].rect);
                        gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[tempindex].y3, currentcols + mymoder[tempindex].x3].rect);
                        gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[tempindex].y4, currentcols + mymoder[tempindex].x4].rect);
                        urect[currentrows 
+ mymoder[tempindex].y1, currentcols + mymoder[tempindex].x1].flag = false;
                        urect[currentrows 
+ mymoder[tempindex].y2, currentcols + mymoder[tempindex].x2].flag = false;
                        urect[currentrows 
+ mymoder[tempindex].y3, currentcols + mymoder[tempindex].x3].flag = false;
                        urect[currentrows 
+ mymoder[tempindex].y4, currentcols + mymoder[tempindex].x4].flag = false;

                        gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].rect);
                        gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].rect);
                        gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].rect);
                        gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].rect);
                        urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].flag = true;
                        urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].flag = true;
                        urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].flag = true;
                        urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].flag = true;
                        tempindex 
= currentIndex;
                    }

                }

            }

            
else if (e.KeyCode == left)//向左移动
            {
                
if (sync || !mytimer.Enabled)
                    
return;
                
if (judgePaintEnable(currentrows, currentcols, currentIndex, zouyf_flag.LEFT))
                
{
                    gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].rect);
                    gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].rect);
                    gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].rect);
                    gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].rect);
                    urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].flag = false;
                    urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].flag = false;
                    urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].flag = false;
                    urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].flag = false;
                    currentcols 
-= 1;//左移一列后,当前列自减1
                    gs.FillRectangle(wbrush, urect[currentrows + mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].rect);
                    gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].rect);
                    gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].rect);
                    gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].rect);
                    urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].flag = true;
                    urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].flag = true;
                    urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].flag = true;
                    urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].flag = true;
                }

            }

            
else if (e.KeyCode == right)//向右移动
            {
                
if (sync || !mytimer.Enabled)
                    
return;
                
if (judgePaintEnable(currentrows, currentcols, currentIndex, zouyf_flag.RIGHT))
                
{
                    gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].rect);
                    gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].rect);
                    gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].rect);
                    gs.FillRectangle(bbrush, urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].rect);
                    urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].flag = false;
                    urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].flag = false;
                    urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].flag = false;
                    urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].flag = false;
                    currentcols 
+= 1;//右移一列后,当前列自增1
                    gs.FillRectangle(wbrush, urect[currentrows + mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].rect);
                    gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].rect);
                    gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].rect);
                    gs.FillRectangle(wbrush, urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].rect);
                    urect[currentrows 
+ mymoder[currentIndex].y1, currentcols + mymoder[currentIndex].x1].flag = true;
                    urect[currentrows 
+ mymoder[currentIndex].y2, currentcols + mymoder[currentIndex].x2].flag = true;
                    urect[currentrows 
+ mymoder[currentIndex].y3, currentcols + mymoder[currentIndex].x3].flag = true;
                    urect[currentrows 
+ mymoder[currentIndex].y4, currentcols + mymoder[currentIndex].x4].flag = true;
                }

            }

            
else if (e.KeyCode == down)//加速下落
                mytimer.Interval = 15;//让时间tick周期变短,当键弹起后,再还原,当然也可以用其它的算法让此时的模型一落到底:)
            else if (e.KeyCode == start_puase)//开始与暂停
            {
                
if (mytimer.Enabled)
                
{
                    mytimer.Enabled 
= false;
                    score_time_timer.Enabled 
= false;
                }

                
else
                
{
                    mytimer.Enabled 
= true;
                    score_time_timer.Enabled 
= true;
                }

            }

            
else if (e.KeyCode == setkeys)//设置游戏按键
            {
                mytimer.Enabled 
= false;//设置按键时,暂停游戏
                score_time_timer.Enabled = false;
                Form setform 
= new Form2(this);
                setform.Show();
            }

            
else if (e.KeyCode == newgame)//开始新的游戏,清空与原游戏相关的所有信息8
            {
                mytimer.Enabled 
= false;
                rebuild 
= true;
                
for (int i = 0; i < rows; i++)
                    
for (int j = 0; j < cols; j++)
                    
{
                        gs.FillRectangle(bbrush, urect[i, j].rect);
                        urect[i, j].flag 
= false;
                    }

                totalscore 
= 0;
                totaltime 
= 0;
                highest 
= 0;
                time_label.Text 
= "00:00:00";
                score_time_label.Text 
= "0.00";
                highest_label.Text 
= "0.00";
                scoreLable.Text 
= "0";
                mytimer.Enabled 
= true;
                score_time_timer.Enabled 
= true;
                mytimer.Interval 
= 600 - 50 * grade;
            }

            gs.Dispose();
        }


        
private bool judgePaintEnable(int currentrows, int currentcols, int currentIndex, zouyf_flag flag)//判断能否移动
        {
            moder tempmoder 
= mymoder[currentIndex];
            
int tempx = 0, tempy = 0, minx = 0, maxx = 0, maxy = 0;
            getMinAndMaxXY(tempmoder, 
ref minx, ref maxx, ref maxy);////首先得到当前正在下落的模型最左边、最右边和最下边的坐标
            switch (flag)
            
{
                
case zouyf_flag.DOWN:////算法思想为,依次判断每一列是否能够下落
                    if (currentrows + maxy >= rows - 1)
                        
return false;
                    tempx 
= tempmoder.x1;
                    tempy 
= tempmoder.y1;
                    
if (tempmoder.x2 == tempx && tempmoder.y2 > tempy)
                        tempy 
= tempmoder.y2;
                    
if (tempmoder.x3 == tempx && tempmoder.y3 > tempy)
                        tempy 
= tempmoder.y3;
                    
if (tempmoder.x4 == tempx && tempmoder.y4 > tempy)
                        tempy 
= tempmoder.y4;
                    
if (urect[currentrows + tempy + 1, currentcols + tempx].flag)//此列的下一排已经被占用,不能再下落了
                        return false;
                    tempx 
= tempmoder.x2;
                    tempy 
= tempmoder.y2;
                    
if (tempmoder.x3 == tempx && tempmoder.y3 > tempy)
                        tempy 
= tempmoder.y3;
                    
if (tempmoder.x4 == tempx && tempmoder.y4 > tempy)
                        tempy 
= tempmoder.y4;
                    
if (urect[currentrows + tempy + 1, currentcols + tempx].flag)//此列的下一排已经被占用,不能再下落了
                        return false;
                    tempx 
= tempmoder.x3;
                    tempy 
= tempmoder.y3;
                    
if (tempmoder.x4 == tempx && tempmoder.y4 > tempy)
                        tempy 
= tempmoder.y4;
                    
if (urect[currentrows + tempy + 1, currentcols + tempx].flag)//此列的下一排已经被占用,不能再下落了
                        return false;
                    tempx 
= tempmoder.x4;
                    tempy 
= tempmoder.y4;
                    
if (urect[currentrows + tempy + 1, currentcols + tempx].flag)//此列的下一排已经被占用,不能再下落了
                        return false;
                    
break;
                
case zouyf_flag.LEFT:////算法思想为,依次判断每一行是否能够左移
                    if (currentcols + minx <= 0)
                        
return false;
                    tempx 
= tempmoder.x4;
                    tempy 
= tempmoder.y4;
                    
if (tempmoder.y3 == tempy && tempmoder.x3 < tempx)
                        tempx 
= tempmoder.x3;
                    
if (tempmoder.y2 == tempy && tempmoder.x2 < tempx)
                        tempx 
= tempmoder.x2;
                    
if (tempmoder.y1 == tempy && tempmoder.x1 < tempx)
                        tempx 
= tempmoder.x1;
                    
if (urect[currentrows + tempy, currentcols + tempx - 1].flag)
                        
return false;
                    tempx 
= tempmoder.x3;
                    tempy 
= tempmoder.y3;
                    
if (tempmoder.y2 == tempy && tempmoder.x2 < tempx)
                        tempx 
= tempmoder.x2;
                    
if (tempmoder.y1 == tempy && tempmoder.x1 < tempx)
                        tempx 
= tempmoder.x1;
                    
if (urect[currentrows + tempy, currentcols + tempx - 1].flag)
                        
return false;
                    tempx 
= tempmoder.x2;
                    tempy 
= tempmoder.y2;
                    
if (tempmoder.y1 == tempy && tempmoder.x1 < tempx)
                        tempx 
= tempmoder.x1;
                    
if (urect[currentrows + tempy, currentcols + tempx - 1].flag)
                        
return false;
                    tempx 
= tempmoder.x1;
                    tempy 
= tempmoder.y1;
                    
if (urect[currentrows + tempy, currentcols + tempx - 1].flag)
                        
return false;
                    
break;
                
case zouyf_flag.RIGHT:////算法思想为,依次判断每一行是否能够右移
                    if (currentcols + maxx >= cols - 1)
                        
return false;
                    tempx 
= tempmoder.x1;
                    tempy 
= tempmoder.y1;
                    
if (tempmoder.y2 == tempy && tempmoder.x2 > tempx)
                        tempx 
= tempmoder.x2;
                    
if (tempmoder.y3 == tempy && tempmoder.x3 > tempx)
                        tempx 
= tempmoder.x3;
                    
if (tempmoder.y4 == tempy && tempmoder.x4 > tempx)
                        tempx 
= tempmoder.x4;
                    
if (urect[currentrows + tempy, currentcols + tempx + 1].flag)
                        
return false;
                    tempx 
= tempmoder.x2;
                    tempy 
= tempmoder.y2;
                    
if (tempmoder.y3 == tempy && tempmoder.x3 > tempx)
                        tempx 
= tempmoder.x3;
                    
if (tempmoder.y4 == tempy && tempmoder.x4 > tempx)
                        tempx 
= tempmoder.x4;
                    
if (urect[currentrows + tempy, currentcols + tempx + 1].flag)
                        
return false;
                    tempx 
= tempmoder.x3;
                    tempy 
= tempmoder.y3;
                    
if (tempmoder.y4 == tempy && tempmoder.x4 > tempx)
                        tempx 
= tempmoder.x4;
                    
if (urect[currentrows + tempy, currentcols + tempx + 1].flag)
                        
return false;
                    tempx 
= tempmoder.x4;
                    tempy 
= tempmoder.y4;
                    
if (urect[currentrows + tempy, currentcols + tempx + 1].flag)
                        
return false;
                    
break;
                
default:
                    
return false;
            }

            
return true;
        }


        
private void Form1_KeyUp(object sender, KeyEventArgs e)
        
{
            
if (e.KeyCode == down)
                mytimer.Interval 
= 600 - grade * 50;
        }


        
////这个函数与游戏模块的藕合性不大,主要用于处理总耗时,分数时间比,历史分数时间比等
        private void score_time_timer_Tick(object sender, EventArgs e)
        
{
            
int h = 0, m = 0, s = 0;
            
float tempvalue = 0;
            
string sh = "", sm = "", ss = "";
            totaltime 
+= 1;
            h 
= totaltime / 3600;
            m 
= totaltime % 3600 / 60;
            s 
= totaltime % 3600 % 60;
            sh 
= h + "";
            
if (h < 10)
                sh 
= "0" + h + "";
            sm 
= "" + m;
            
if (m < 10)
                sm 
= "0" + m;
            ss 
= "" + s;
            
if (s < 10)
                ss 
= "0" + s;
            time_label.Text 
= sh + ":" + sm + ":" + ss;
            tempvalue 
= (float)Math.Round(totalscore / (float)totaltime, 3);
            
this.score_time_label.Text = tempvalue + "";
            
if (tempvalue > highest)
            
{
                highest 
= tempvalue;
                highest_label.Text 
= highest + "";
            }

        }

    }

}

Form2.cs文件:

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace RassionBlock
{
    
//这个类就是一些键的设置,设置完成后在主窗口中显示,应该很容易懂,我就不过多的解释了
    public partial class Form2 : Form
    
{
        
private Keys left = Keys.Left;
        
private Keys right = Keys.Right;
        
private Keys down = Keys.Down;
        
private Keys change = Keys.Space;
        
private Keys start_puase = Keys.F2;
        
private Keys setkeys = Keys.F3;
        
private Keys newgame = Keys.F4;
        
private int grade = 1;
        
private mainform form1;
        
public Form2(mainform form1)//用主窗口传递过来的实例初始化,便于与主窗口类进行通信 
        {
            InitializeComponent();
            
this.form1 = form1;
        }


        
private void left_keyDown(object sender, KeyEventArgs e)
        
{
            left_textBox.Text 
= e.KeyCode + "";
            left 
= e.KeyCode;
        }


        
private void right__keyDown(object sender, KeyEventArgs e)
        
{
            right_textBox.Text 
= e.KeyCode + "";
            right 
= e.KeyCode;
        }


        
private void down_keyDown(object sender, KeyEventArgs e)
        
{
            down_textBox.Text 
= e.KeyCode + "";
            down 
= e.KeyCode;
        }


        
private void change_keyDown(object sender, KeyEventArgs e)
        
{
            change_textBox.Text 
= e.KeyCode + "";
            change 
= e.KeyCode;
        }


        
private void sp_keyDown(object sender, KeyEventArgs e)
        
{
            sp_textBox.Text 
= e.KeyCode + "";
            start_puase 
= e.KeyCode;
        }


        
private void set_keyDown(object sender, KeyEventArgs e)
        
{
            set_textBox.Text 
= e.KeyCode + "";
            setkeys 
= e.KeyCode;
        }


        
private void newgame_keyDown(object sender, KeyEventArgs e)
        
{
            newgame_textBox.Text 
= e.KeyCode + "";
            newgame 
= e.KeyCode;
        }


        
private void ok_Click(object sender, EventArgs e)
        
{
            
try
            
{
                grade 
= int.Parse(grade_textBox.Text);
                
if (grade < 1 || grade > 10)
                
{
                    grade 
= 1;
                    MessageBox.Show(
"级别只能是在1-10之间!");
                    
return;
                }

            }

            
catch
            
{
                MessageBox.Show(
"设置级别时,请输入1-10之间的数字!");
                grade 
= 1;
                
return;
            }

            
if (left == right || left == down || left == change || left == start_puase || left == setkeys || left == newgame ||
                right 
== down || right == change || right == start_puase || right == setkeys || right == newgame ||
                down 
== change || down == start_puase || down == setkeys || down == newgame ||
                change 
== start_puase || change == setkeys || change == newgame ||
                start_puase 
== setkeys || start_puase == newgame ||
                setkeys 
== newgame)
            
{
                MessageBox.Show(
"检测到有相同的键位设置!");
                
return;
            }

            form1.left 
= left;
            form1.right 
= right;
            form1.down 
= down;
            form1.change 
= change;
            form1.start_puase 
= start_puase;
            form1.setkeys 
= setkeys;
            form1.grade 
= grade;
            form1.newgame 
= newgame;
            form1.left_label.Text 
= left_textBox.Text;
            form1.right_label.Text 
= right_textBox.Text;
            form1.down_label.Text 
= down_textBox.Text;
            form1.change_label.Text 
= change_textBox.Text;
            form1.sp_label.Text 
= sp_textBox.Text;
            form1.set_label.Text 
= set_textBox.Text;
            form1.grade_lagel.Text 
= grade_textBox.Text;
            form1.newgame_label.Text 
= newgame_textBox.Text;
            form1.mytimer.Interval 
= 600 - 50 * grade;
            
this.Close();
        }


        
private void reset_Click(object sender, EventArgs e)
        
{
            left 
= Keys.Left;
            right 
= Keys.Right;
            down 
= Keys.Down;
            change 
= Keys.Space;
            start_puase 
= Keys.F2;
            setkeys 
= Keys.F3;
            grade 
= 1;
            newgame 
= Keys.F4;
            left_textBox.Text 
= "Left";
            right_textBox.Text 
= "Right";
            down_textBox.Text 
= "Down";
            change_textBox.Text 
= "Space";
            sp_textBox.Text 
= "F2";
            set_textBox.Text 
= "F3";
            grade_textBox.Text 
= "1";
            newgame_textBox.Text 
= "F4";
        }


        
private void Form2_Load(object sender, EventArgs e)//设置键位的窗口在加载时,显示当前的键位设置 
        {
            left_textBox.Text 
= form1.left_label.Text;
            right_textBox.Text 
= form1.right_label.Text;
            down_textBox.Text 
= form1.down_label.Text;
            change_textBox.Text 
= form1.change_label.Text;
            sp_textBox.Text 
= form1.sp_label.Text;
            set_textBox.Text 
= form1.set_label.Text;
            grade_textBox.Text 
= form1.grade_lagel.Text;
            newgame_textBox.Text 
= form1.newgame_label.Text;
        }


        
private void cancel_button_Click(object sender, EventArgs e)
        
{
            
this.Close();
        }

    }

}

Form1.Designer.cs文件:

 

namespace RassionBlock
{
    
partial class mainform
    
{
        
/// <summary>
        
/// 必需的设计器变量。
        
/// </summary>

        private System.ComponentModel.IContainer components = null;

        
/// <summary>
        
/// 清理所有正在使用的资源。
        
/// </summary>
        
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>

        protected override void Dispose(bool disposing)
        
{
            
if (disposing && (components != null))
            
{
                components.Dispose();
            }

            
base.Dispose(disposing);
        }


        
Windows 窗体设计器生成的代码

        
private System.Windows.Forms.Timer score_time_timer;
        
private System.Windows.Forms.Label label1;
        
private System.Windows.Forms.Label scoreLable;
        
private System.Windows.Forms.Label nextLabel;
        
private System.Windows.Forms.Label label2;
        
private System.Windows.Forms.Label label3;
        
private System.Windows.Forms.Label label4;
        
private System.Windows.Forms.Label label5;
        
private System.Windows.Forms.Label label6;
        
private System.Windows.Forms.Label label7;
        
private System.Windows.Forms.Label label8;
        
private System.Windows.Forms.Label label9;
        
private System.Windows.Forms.Label label10;
        
private System.Windows.Forms.Label label11;
        
private System.Windows.Forms.Label label12;
        
private System.Windows.Forms.Label label13;
        
private System.Windows.Forms.Label label14;
        
private System.Windows.Forms.Label time_label;
        
private System.Windows.Forms.Label score_time_label;
        
private System.Windows.Forms.Label highest_label;
        
public System.Windows.Forms.Timer mytimer;
        
public System.Windows.Forms.Label down_label;
        
public System.Windows.Forms.Label change_label;
        
public System.Windows.Forms.Label grade_lagel;
        
public System.Windows.Forms.Label set_label;
        
public System.Windows.Forms.Label right_label;
        
public System.Windows.Forms.Label left_label;
        
public System.Windows.Forms.Label sp_label;
        
public System.Windows.Forms.Label newgame_label;
    }

}

Form2.Designer.cs文件:

 

namespace RassionBlock
{
    
partial class Form2
    
{
        
/// <summary>
        
/// 必需的设计器变量。
        
/// </summary>

        private System.ComponentModel.IContainer components = null;

        
/// <summary>
        
/// 清理所有正在使用的资源。
        
/// </summary>
        
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>

        protected override void Dispose(bool disposing)
        
{
            
if (disposing && (components != null))
            
{
                components.Dispose();
            }

            
base.Dispose(disposing);
        }


        
Windows 窗体设计器生成的代码

        
private System.Windows.Forms.Label label1;
        
private System.Windows.Forms.Label label2;
        
private System.Windows.Forms.Label label3;
        
private System.Windows.Forms.Label label4;
        
private System.Windows.Forms.Label label5;
        
private System.Windows.Forms.Label label6;
        
private System.Windows.Forms.Label label7;
        
private System.Windows.Forms.Label label8;
        
private System.Windows.Forms.TextBox left_textBox;
        
private System.Windows.Forms.TextBox right_textBox;
        
private System.Windows.Forms.TextBox down_textBox;
        
private System.Windows.Forms.TextBox change_textBox;
        
private System.Windows.Forms.TextBox set_textBox;
        
private System.Windows.Forms.TextBox sp_textBox;
        
private System.Windows.Forms.Button ok_button;
        
private System.Windows.Forms.Button reset_button;
        
private System.Windows.Forms.TextBox grade_textBox;
        
private System.Windows.Forms.Label label9;
        
private System.Windows.Forms.TextBox newgame_textBox;
        
private System.Windows.Forms.Button cancel_button;
        
private System.Windows.Forms.Label label10;
        
private System.Windows.Forms.Label label11;
    }

}

Program.cs文件:

 

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace RassionBlock
{
    
static class Program
    
{
        
/// <summary>
        
/// 应用程序的主入口点。
        
/// </summary>

        [STAThread]
        
static void Main()
        
{
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(
false);
            Application.Run(
new mainform());
        }

    }

}


终于贴完了:)  (点击此下载源代码)

展开阅读全文

没有更多推荐了,返回首页