自己动手写俄罗斯方块(二)

补:写的这些程序没运行,写之后就直接弄上来了,后来用这些程 序来合成时,发现有些小错误,如有汉字字符,或名字写错,Rectangle函数的参数用错等。这里就不再改了,太过于麻烦,那些错误大家一眼就看看出来 的。在合成版本中,所有错误均为被纠正过来J。

各部分的实现

1 设定方块的 大小及游戏区坐标

对此我们可以 这样写 :

Code:
  1. const   int  SquareSize = 20;   
  2.   
  3. const   int  GameSizeX = 50;   
  4.   
  5. const   int  GameSizeY = 50;   

这样我们定义了方 块各边的大小为 20 。游戏区开始坐标为 (50,50);

这里的数组并不唯 一,根据个人爱好而定。

我们这里我们还是 有必要定义一下游戏区的信息:

Code:
  1. const   int  GameRegionWidth = 10;   
  2.   
  3. const   int  GameRegionHeight = 20;    
  4.   
  5. int  GameMapStates[20][10];   

// 这里我曾试过分别使用 GameRegionWidth GameRegionHeight // 10 20 ,但我使用的编译 器不支持。

2 建立游戏区 :

建立游戏去, 即一个 20 行, 10 列的网格游戏去,当然这个网格是隐藏的,是不显示出来的。也不需 要我们区画的。只要我们心中有这个网格就 OK J

好,我们现在 开始画了。我们使用的函数为 .

Code:
  1. BOOL  Rectangle(   
  2.   
  3. HDC  hdc,    
  4.   
  5. int  nLeftRect,    
  6.   
  7. int  nTopRect,    
  8.   
  9. int  nRightRect,    
  10.   
  11. int  nBottomRect   
  12.   
  13. );   
  14.   

我们既然决定要使用这个函数我们就的得到该函数相应的参数。

Code:
  1. int  LeftX = GameSizeX;  //游戏区左上角横坐标   
  2.   
  3. int  LeftY = GameSzieY;  //游戏区坐上角纵坐标   
  4.   
  5. //游戏区右下角横坐标   
  6.   
  7. int  RightX = GameSizeX + GameRegionWidth * SquareSize;    
  8.   
  9. //游戏区右下角纵坐标   
  10.   
  11. int  RightY = GameSizeY + GameRegionHeight * SquareSize;   
  12.   

好的,我们已经得到 5 个参数中的四个参数了。至于 HDC ,我们可以根据当时的情况来获得。我们该函数不同的用处获得 HDC 的方式不同。好了,画游戏区的功能已经实现了,但我们总不能每 次调用的时候都写这么多吧?我想为了美观与程序的易读性我们还是用个函数封装下好 J

好的,我们来封装一下该函数:

Code:
  1. void  DrawGameRegion( HDC  hdc)   
  2.   
  3. {   
  4.   
  5.        int  LeftX = GameSizeX;  //游戏区左上角横坐标   
  6.   
  7. int  LeftY = GameSzieY;  //游戏区坐上角纵坐标   
  8.   
  9. //游戏区右下角横坐标   
  10.   
  11. int  RightX = GameSizeX + GameRegionWidth * SquareSize;    
  12.   
  13. //游戏区右下角纵坐标   
  14.   
  15. int  RightY = GameSizeY + GameRegionHeight * SquareSize;   
  16.   
  17. Rectangle(hdc,LeftX,LeftY,RightX,RightY);   
  18.   
  19. }   
  20.   

封装成功 !

3 初始化俄罗斯方块的 7 中图形

Code:
  1. const  POINT Terics[7][4][4] =   
  2.   
  3. {   
  4.   
  5.   {   
  6.   
  7.      0,0,1,0,0,1,-1,1,   
  8.   
  9.      0,0,0,1,1,1,1,2,   
  10.   
  11.      0,0,1,0,0,1,-1,1,   
  12.   
  13.      0,0,0,1,1,1,1,2   
  14.   
  15.   },   
  16.   
  17.   {   
  18.   
  19.      0,0,1,0,1,1,2,1,   
  20.   
  21.      0,0,0,1,-1,1,-1,2,   
  22.   
  23.      0,0,1,0,1,1,2,1,   
  24.   
  25.      0,0,0,1,-1,1,-1,2   
  26.   
  27.   },   
  28.   
  29.   {   
  30.   
  31.      0,0,0,1,0,2,1,2,   
  32.   
  33.      0,0,0,1,-1,1,-2,1,   
  34.   
  35.      0,0,1,0,1,1,1,2,   
  36.   
  37.      0,0,0,1,1,0,2,0   
  38.   
  39.   },   
  40.   
  41.   {   
  42.   
  43.      0,0,0,1,0,2,-1,2,   
  44.   
  45.      0,0,1,0,2,0,2,1,   
  46.   
  47.      0,0,1,0,0,1,0,2,   
  48.   
  49.      0,0,0,1,1,1,2,1   
  50.   
  51.   },   
  52.   
  53.   {   
  54.   
  55.      0,0,0,1,0,2,0,3,   
  56.   
  57.      0,0,1,0,2,0,3,0,   
  58.   
  59.      0,0,0,1,0,2,0,3,   
  60.   
  61.      0,0,1,0,2,0,3,0   
  62.   
  63.   },   
  64.   
  65.   {   
  66.   
  67.      0,0,1,0,0,1,1,1,   
  68.   
  69.      0,0,1,0,0,1,1,1,   
  70.   
  71.       0,0,1,0,0,1,1,1,   
  72.   
  73.      0,0,1,0,0,1,1,1   
  74.   
  75.   },   
  76.   
  77.   {   
  78.   
  79.      0,0,1,0,2,0,1,1,   
  80.   
  81.      0,0,0,1,0,2,1,1,   
  82.   
  83.      0,0,0,1,-1,1,1,1,   
  84.   
  85.      0,0,0,1,0,2,-1,1   
  86.   
  87.   }   
  88.   
  89. };     
  90.   

这个我也曾下到我的思路里了。为了完美只好在这里再写一遍了 J

哇,一大推的数字是什么意思啊 ?:-D ,看似很难,其实很简单的。你

只需当前图形的形状和方向判断组成它的每个方块的右上角坐标比

当前坐标便宜多少,然后添上去就 OK 了。注意这里的坐标是游戏区

的坐标。即,偏移 1 相当于原来的坐标偏移一个方块边长的大小。

4 画方块

说了半天如何画一个方块还没实现呢, J 这 里我们仍然是函数封装。

Code:
  1. void  DrawRectangle( HDC  hdc, int  x, int  y)   
  2.   
  3. {   
  4.   
  5.             int  LeftX = GameSizeX + x * SquareSize;   
  6.   
  7.             int  LeftY = GameSizeY + y * SquareSize;   
  8.   
  9.        int  RightX = GameSizeX + SquareSize;   
  10.   
  11.        int  RightY = GameSizeY + SquareSize;   
  12.   
  13.       Rectangle(hdc,LeftX,LeftY,RightX,RightY);   
  14.   
  15. }   
  16.   

5 画俄罗斯方块

方块画好了, 我们该画各种形状的俄罗斯方块了。。仍然是函数封装哦 J

Code:
  1. void  DrawTetromino( HDC  hdc, int  shape, int  dir, int  x, int  y)   
  2.   
  3. {   
  4.   
  5.         int  index,nx,ny;   
  6.   
  7.        for  ( index = 0; index < 4; ++index)   
  8.   
  9.            {   
  10.   
  11.                  nx = Terics[shape][dir][index].x + x;   
  12.   
  13.                 ny = Terics[shape][dir][index].y + y;   
  14.   
  15.                 DrawRectangle(hdc,nx,ny);   
  16.   
  17.            }   
  18.   
  19. }    
  20.   

6 判断范围

该画的我们都 画好了,在让他移动之前我们先将它的范围设定一下吧。别急哦 J

Code:
  1. BOOL  IsOutOfRegion( int  shape,  int  dir,  int  x,  int  y)   
  2.   
  3. {   
  4.   
  5.             int  index;   
  6.   
  7.             int  nx,ny;   
  8.   
  9.             for  (index = 0; index < 4; ++index)   
  10.   
  11.            {   
  12.   
  13.                  nx = Terics[shape][dir][index].x + x;   
  14.   
  15.                  ny = Terics[shape][dir][index].y + y;   
  16.   
  17.                   if  (ny < 0 || ny >= GameRegionHeight || nx < 0 || nx >= GameRegionWidth  || GameMapStates[nx][ny] != 0)   
  18.   
  19.                  {   
  20.   
  21.                              return  TRUE;    
  22.   
  23.                  }   
  24.   
  25.            }   
  26.   
  27.            return  FALSE;   
  28.   
  29. }   
  30.   

7 保存游戏区当前的状态

该是保存状态的时候了。。 J 这 应该是写俄罗斯方块里最难得东西了(个人认为哈)。并不是这里的代码有多难,而是它的思想难。

Code:
  1. void  SaveStateofTerics( int  shape,  int  dir,  int  x,  int  y)   
  2.   
  3. {   
  4.   
  5.             int  index;   
  6.   
  7.             int  nx,ny;   
  8.   
  9.             for  ( index = 0; index < 4; ++index)   
  10.   
  11.            {   
  12.   
  13.                  nx = Terics[shape][dir][i].x + x;   
  14.   
  15.                  nx = Terics[shape][dir][i].y + y;   
  16.   
  17.                  GameMapStates[nx][ny] = 1;   
  18.   
  19.            }   
  20.   
  21. }   
  22.   
  23.   

8 消去一行

Code:
  1. void  DeleteTericsFromOfGameRegion( int  shape,  int  dir,  int  x,  int  y)   
  2.   
  3. {   
  4.   
  5.        bool  flag = TRUE;   
  6.   
  7.        int  indexX,indexY;   
  8.   
  9.     int  m,n;   
  10.   
  11.    for  (indexX = 0; indexX < GameRegionHeight; ++index)   
  12.   
  13.        for  (indexY = 0; indexY < GameRegionWidth; ++indexY)   
  14.   
  15.       {   
  16.   
  17.                   if  (GameMapStates[indexX][indexY] != 1)   
  18.   
  19.                  {   
  20.   
  21.                       flag = FALSE;   
  22.   
  23.                  }   
  24.   
  25.                   if  (flag)   
  26.   
  27.                  {   
  28.   
  29.                        for  (m = indexX; m >= 0; --m)   
  30.   
  31.                        for  (n = 0; n < GameRegionWidth;++n)   
  32.   
  33.                       {   
  34.   
  35.                             GameMapStates[m][n] = GameMapStates[m-1][n]   
  36.   
  37.                       }   
  38.   
  39.                  }   
  40.   
  41.          
  42.   
  43. }    
  44.   

9 显示问题

对于显示问 题,我们使用我们的思路里的第二种方法来实现,故我们需要定义擦除函数,加载函数。好的,我们开始吧。 J

Code:
  1. void  EraseGameRegion( HDC  hdc)   
  2.   
  3. {   
  4.   
  5.       RECT rect;   
  6.   
  7.    rect.left = GameSizeX;   
  8.   
  9.       rect.top = GameSizeY;   
  10.   
  11.       rect.right = GameSizeX + GameRegionWidth * SquareSize;   
  12.   
  13.       rect.bottom = GameSizeY + GameRegionHeight * SquareSize;   
  14.   
  15.        HBRUSH  brush = CreateSolidBrush(RGB(255,255,255));   
  16.   
  17.       FillRect(hdc,&rect,brush);   
  18.   
  19.     DrawGameRegion(hdc); //游戏区被删除,重新画一边   
  20.   
  21. }   
  22.   

定义加载函数

Code:
  1. void  LoadCurrentTerics( HDC  hdc)   
  2.   
  3. {   
  4.   
  5.        int  indexX,indexY;   
  6.   
  7.        for  (indexX = 0; indexX < GameRegionWidth; ++indexX)   
  8.   
  9.        for  (indexY = 0; indexY < GameRegionHeight; ++indexY)   
  10.   
  11.       {   
  12.   
  13.             if  (GameMapStates[indexX][indexY] == 1)   
  14.   
  15.            {   
  16.   
  17.                  DrawRectangle(hdc,indexX,indexY);   
  18.   
  19.            }   
  20.   
  21.       }   
  22.   
  23. }   
  24.   

10 初始化问题

  在俄罗斯方块 游戏中因为每次新方块都是从固定的地方出来,所以我们应该对之有一个初始化。为此我们还应该定义一个变量来保存当前图形的形状,方向,坐标;

Code:
  1. struct  CurrentTerics{   
  2.   
  3. int  shape,dir,x,y;   
  4.   
  5. }CurrentTericInfo;   
  6.   

注意这个应该 为一个全局的。

封装一个初始 化函数:

Code:
  1. void  InitTericsInfo()   
  2.   
  3. {   
  4.   
  5.       srand((unsigned)time(NULL));   
  6.   
  7.     CurrentTericsInfo.shape = rand()%7;   
  8.   
  9.     CurrentTericsInfo.dir = 0;   
  10.   
  11.     CurrentTericsInfo.x = 4;   
  12.   
  13.     CurrentTericsInfo.y = 0;   
  14.   
  15. }   
  16.   

好的。至此一 个俄罗斯方块的各部分都已实现,只剩下组装工作了。至于如何组装,该把这些函数放到那里,我的理路里都已有了大部分的方法。

 参照帖子:http://www.rupeng.com/forum/thread-2533-1-1-uid2704.html

                    http://www.rupeng.com/forum/thread-3195-1-1-uid2704.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值