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

来源:互联网 发布:python idle3.5.2 编辑:程序博客网 时间:2024/04/28 00:15

补:写的这些程序没运行,写之后就直接弄上来了,后来用这些程序来合成时,发现有些小错误,如有汉字字符,或名字写错,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列的网格游戏去,当然这个网格是隐藏的,是不显示出来的。也不需要我们区画的。只要我们心中有这个网格就OKJ

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

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

原创粉丝点击