`
zmo_xu
  • 浏览: 62452 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
最近访客 更多访客>>
社区版块
存档分类
最新评论

逐步讲解用C#实现俄罗斯方块之核心代码[中]

阅读更多

我们知道俄罗斯方块有以下的图形
■■(1) ■■■■(2)■■■(3)■■■(4)■■■(5)■■□(6)□■■(7)
■■(1) □□□□(2)■□□(2)□□■(4)□■□(5)□■■(6)■■□(7)

□□□        ■ (8)     ■□(9)    ■■(A)   ■□(B)    □■(C)     ■□(D)
□□□        ■ (8)     ■□(9)    ■□(A)   ■■(B)    ■■(C)     ■■
□□□        ■ (8)     ■■(9)    ■□(A)   ■□(B)    ■□(C)     □■
□□□        ■ (8)

□□□□□□□□□□□■(E) ■□□(F) □■□(H)
□□□□□□□□□■■■(E) ■■■(F) ■■■(H)

□□□□□□□□□ ■■(I)  □■(J)   □■(K)
□□□□□□□□□ □■(I)  □■(J)   ■■(K)
□□□□□□□□□ □■(I)  ■■(J)   □■(K)
这里的编号用字母没有任何特殊意义主要是10~19是2位数不利于排版
□也是为了排版因为空格在显示的时候和我编辑的时候不一样宽
我们看到共有19种图形,我们有两种方法实现,一种就是图形并没有旋转只是改变图形的编码比如图形2旋转后就将图形编号改成7,另外一种是做到真正的旋转,好处是实现,这种真正的旋转的好处是可以应付特殊图形大家知道俄罗斯有变种俄罗斯里面有
■■■
□■□
□■□
这种图形 有后面的方法可以轻松实现你只要将前面分pb数组的元素个数改成9就可以对付
■■■
■■■
■■■
中能产生的任意变种,淡然5*5甚至10*10是你能想到的任意图形矩阵也可以移植到别到程序中^_^(比如玛丽医生,活活)-我们用
■■


来讲解怎样计算(要使用到一些几何知识)
首先我们要使用几何中的象限来考虑问题
假设上面的图形是第一象限的 1~4象限按照逆时旋转得到那么分别是
■■□■□□□□■□□□□□
■□□■■■□□■□■■■□
■□□□□□□■■□□□■□
放入象限后是这样,假设红点是参考点(也是原点)红色和4个颜色分别组合就是在这个象限到图形到样子我们来寻找规律吧Let's GO!
□□■■□
■□■□□
■■■■■
□□■□■
□■■□□
我们从第一象限入手以红色为参考点 绿色为考察点
■■□■□□
■□□■■■
■□□□□□
请配合上面点4色象限图听我讲解|
在第一象限中X(绿)=X(红) + x; Y(绿) = Y(红) + 2y;
在第二象限中X(绿)=X(红) -2y; Y(绿) = Y(红) + x;
我们再看看这个图形
□□□□■□□□□■□■■□
■■■□■□□■■■□□■□
■□□□■■□□□□□□■□

□■□□□
□■■■■
□■■■□
■■■■□
□□□■□
这个4个象限图看起来有点累呵呵,不过按颜色区分还是能分出来的
□□□□■□
■■■□■□
■□□□■■|
在第一象限中X(绿) = (红) + 2x; Y(绿) = Y(红) + y;
在第二象限中X(绿)=X(红) -y; Y(绿) = Y(红) + 2x;
呵呵发现顾虑每假设第一象限中参考点和考察点的X轴坐标差为aY坐标差为b
在第一象限中X(绿)=X(红) + a; Y(绿) = Y(红) + b;//为什么都是+...肯定的以为第一象限的任意一点的横纵坐标都>=0
在第二象限中X(绿)=X(红) -b; Y(绿) = Y(红) + a;//因为横坐标<=0 纵坐标>=0
在这样的前提下我们开始大胆的猜想第三象限的公式
在第三象限中X(绿)=X(红) -a; Y(绿) = Y(红) - b;//因为横坐标<=0 纵坐标<=0
在第二象限中X(绿)=X(红) +b; Y(绿) = Y(红) -a;//因为横坐标>=0 纵坐标<=0
呵呵到此我们已经的到了旋转到公式,当然要带入别到图形进行验证,测试结果完全正确,那么旋转规律就是他了 现在我们要作到是将他们用代码实现并封装到方法中去,,这里就是一个逻辑到实现方法我这里就直接给出代码了好现在来看看这个finish()方法-

 public void finish()
        
...{
            
//对4个移动图形组的成员进行遍历判断
            for (int i = 0; i < 4; i++)
            
...{
                
//求出当前组件所在的行(游戏里面的行)
                int y = (pb[i].Location.Y - 20/ 10;
                
if(y>1)
                
...{
                    
if (CheckLine(y))
                    
...{
                        
//消除y所在的行
                        ClareLine(y);
                    }

                }

            }

        }

  
private bool CheckLine(int y)
        
...{
           
// MessageBox.Show(y + "," + (y - 1));
            for (int i = 0; i < 20; i++)
            
...{
                
if(oldpb[20*y+i]==null)
                    
return false;
            }

            
return true;
        }

看了上面的两个方法应该知道怎么判断了吧 就是判断pb中没个元素所在的行(还可以进行优化的...就是当多个图形在同一行时只检查该行一次,对于现在的计算机而言 知识检查20个数组元素是否==null,我懒得优化了)这样我们这个俄罗斯方块的类所有的方法基本全部实现了,对了把那个黑箱子给你checkPes()
  private bool checkPes(Point p)
        
...{
            
int x=p.X;
            
int y=p.Y;
            
//检查坐标是否越界
            if (p.X < 10 || p.X > 200return false;
            
//检查是否重叠
            if (pb[0].Location.Y > 10 && pb[1].Location.Y > 10 && pb[2].Location.Y > 10 && pb[3].Location.Y > 10&&y>20)
            
...{
                
if (oldpb[(y - 20/ 10 * 20 + (x - 10/ 10!= nullreturn false;
            }

            
return true;
        }
好了 关键代码我也将的差不多了,在下里面将给出所有的源代码

 

        //四个象限的旋转方法
        private void Roll1()//在第一象限转第二象限
        ...{
            
for (int i = 1; i < 4; i++)
            
...{
                
int x = System.Math.Abs(pb[0].Location.X - pb[i].Location.X);
                
int y = System.Math.Abs(pb[0].Location.Y - pb[i].Location.Y);
                pb[i].Location 
= new Point(pb[0].Location.X - y, pb[0].Location.Y - x);
            }

            
//如果坐标越界就进行反旋转
            if (pb[0].Location.X > 200 || pb[1].Location.X > 200 || pb[2].Location.X > 200 || pb[3].Location.X > 200) Roll4();
            
if (pb[0].Location.X < 0 || pb[1].Location.X < 0 || pb[2].Location.X < 0 || pb[3].Location.X < 0) Roll4();
        }

        
private void Roll2()//在2转3
        ...{
            
for (int i = 1; i < 4; i++)
            
...{
                
int x = System.Math.Abs(pb[0].Location.X - pb[i].Location.X);
                
int y = System.Math.Abs(pb[0].Location.Y - pb[i].Location.Y);
                pb[i].Location 
= new Point(pb[0].Location.X - y, pb[0].Location.Y + x);
            }

            
//如果坐标越界就进行反旋转
            if (pb[0].Location.X < 0 || pb[1].Location.X < 0 || pb[2].Location.X < 0 || pb[3].Location.X < 0) Roll1();
            
if (pb[0].Location.X > 200 || pb[1].Location.X > 200 || pb[2].Location.X > 200 || pb[3].Location.X > 200) Roll1();
        }

        
private void Roll3()//在3转4
        ...{
            
for (int i = 1; i < 4; i++)
            
...{
                
int x = System.Math.Abs(pb[0].Location.X - pb[i].Location.X);
                
int y = System.Math.Abs(pb[0].Location.Y - pb[i].Location.Y);
                pb[i].Location 
= new Point(pb[0].Location.X + y, pb[0].Location.Y + x);
            }

            
//如果坐标越界就进行反旋转
            if (pb[0].Location.X < 0 || pb[1].Location.X < 0 || pb[2].Location.X < 0 || pb[3].Location.X < 0) Roll2();
            
if (pb[0].Location.X > 200 || pb[1].Location.X > 200 || pb[2].Location.X > 200 || pb[3].Location.X > 200) Roll2();
        }

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics