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

对上一篇日志里的代码进行调试和更改后,终于运行成功了。最终的代码对上篇的代码有 些小的改动,但思想是没有改变的。这里改变了部分的实现方式,由于原来的有些方式不知怎的,总感觉那些实现方式很正常,却有得不到我想要的行为,并且我在 VC++6.0里面单独试验了这个小行为,明明是可以实现的,。呵呵。怪异,只好换方式了,看来我以后有必要对此进行总结一下了,要不这次的动手练习就白 费了。。

效 果如下:

代 码如下:

Code:
  1. #include <windows.h>   
  2. #include <stdlib.h>   
  3. const   int  SquareSize = 20;   //方块大小      
  4. const   int  GameSizeX = 50;    //游戏区左上角横坐标      
  5. const   int  GameSizeY = 50;    //游戏区左上角纵坐标   
  6. const   int  GameRegionWidth = 10;      
  7. const   int  GameRegionHeight = 20;       
  8. int  GameMapStates[10][20] = {0};    //用于保存游戏区的状态   
  9. int  nx[4],ny[4];   
  10. int  count = 0;   
  11. int  score = 0;   
  12. struct  CurrentTerics   
  13. {        
  14. int  shape,dir,x,y;        
  15. }CurrentTericsInfo;   
  16. const   COLORREF  color[7] =   
  17. {   
  18.     RGB(255,0,0),   
  19.     RGB(237,138,5),   
  20.     RGB(248,236,6),   
  21.     RGB(27,227,51),   
  22.     RGB(10,128,147),   
  23.     RGB(20,12,184),   
  24.     RGB(106,38,196)   
  25.        
  26. };   
  27. const  POINT Terics[7][4][4] =          
  28. {        
  29.   {       
  30.       
  31.      0,0,1,0,0,1,-1,1,       
  32.       
  33.      0,0,0,1,1,1,1,2,       
  34.       
  35.      0,0,1,0,0,1,-1,1,       
  36.       
  37.      0,0,0,1,1,1,1,2       
  38.       
  39.   },       
  40.   {       
  41.       
  42.      0,0,1,0,1,1,2,1,       
  43.       
  44.      0,0,0,1,-1,1,-1,2,       
  45.       
  46.      0,0,1,0,1,1,2,1,       
  47.       
  48.      0,0,0,1,-1,1,-1,2       
  49.       
  50.   },       
  51.   {       
  52.       
  53.      0,0,0,1,0,2,1,2,       
  54.       
  55.      0,0,0,1,-1,1,-2,1,       
  56.       
  57.      0,0,1,0,1,1,1,2,       
  58.       
  59.      0,0,0,1,1,0,2,0       
  60.       
  61.   },        
  62.   {       
  63.       
  64.      0,0,0,1,0,2,-1,2,       
  65.       
  66.      0,0,1,0,2,0,2,1,       
  67.       
  68.      0,0,1,0,0,1,0,2,       
  69.       
  70.      0,0,0,1,1,1,2,1       
  71.       
  72.   },        
  73.   {       
  74.       
  75.      0,0,0,1,0,2,0,3,       
  76.       
  77.      0,0,1,0,2,0,3,0,       
  78.       
  79.      0,0,0,1,0,2,0,3,       
  80.       
  81.      0,0,1,0,2,0,3,0       
  82.       
  83.   },        
  84.   {       
  85.       
  86.      0,0,1,0,0,1,1,1,       
  87.       
  88.      0,0,1,0,0,1,1,1,       
  89.       
  90.       0,0,1,0,0,1,1,1,       
  91.       
  92.      0,0,1,0,0,1,1,1       
  93.       
  94.   },       
  95.   {       
  96.       
  97.      0,0,1,0,2,0,1,1,       
  98.       
  99.      0,0,0,1,0,2,1,1,       
  100.       
  101.      0,0,0,1,-1,1,1,1,       
  102.       
  103.      0,0,0,1,0,2,-1,1       
  104.       
  105.   }         
  106. };    
  107. void  DrawGameRegion( HDC  hdc);   
  108. void  DrawRectangle( HDC  hdc, int  shape, int  x, int  y);   
  109. void  DrawTetromino( HDC  hdc, int  shape, int  dir, int  x, int  y);   
  110. BOOL  IsOutOfRegion( int  shape,  int  dir,  int  x,  int  y);   
  111. void  SaveStateofTerics( int  shape,  int  dir,  int  *x,  int  *y, int  *count);   
  112. void  EraseGameRegion( HDC  hdc);   
  113. void  LoadCurrentTerics( HDC  hdc);   
  114. void  InitTericsInfo();   
  115. void  PrintInfo( HDC  hdc, int  count, int  score);   
  116. /*  Declare Windows procedure  */   
  117. LRESULT  CALLBACK WindowProcedure ( HWNDUINTWPARAMLPARAM );   
  118.   
  119. /*  Make the class name into a global variable  */   
  120. char  szClassName[ ] =  "WindowsApp" ;   
  121.   
  122.   
  123. int  WINAPI   
  124. WinMain ( HINSTANCE  hThisInstance,   
  125.           HINSTANCE  hPrevInstance,   
  126.           LPSTR  lpszArgument,   
  127.           int  nFunsterStil)   
  128.   
  129. {   
  130.      HWND  hwnd;                /* This is the handle for our window */   
  131.     MSG messages;             /* Here messages to the application are saved */   
  132.     WNDCLASSEX wincl;         /* Data structure for the windowclass */   
  133.   
  134.      /* The Window structure */   
  135.     wincl.hInstance = hThisInstance;   
  136.     wincl.lpszClassName = szClassName;   
  137.     wincl.lpfnWndProc = WindowProcedure;       /* This function is called by windows */   
  138.     wincl.style = CS_DBLCLKS;                  /* Catch double-clicks */   
  139.     wincl.cbSize =  sizeof  (WNDCLASSEX);   
  140.   
  141.      /* Use default icon and mouse-pointer */   
  142.     wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);   
  143.     wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);   
  144.     wincl.hCursor = LoadCursor (NULL, IDC_ARROW);   
  145.     wincl.lpszMenuName = NULL;                  /* No menu */   
  146.     wincl.cbClsExtra = 0;                       /* No extra bytes after the window class */   
  147.     wincl.cbWndExtra = 0;                       /* structure or the window instance */   
  148.      /* Use Windows's default color as the background of the window */   
  149.     wincl.hbrBackground = ( HBRUSH )(COLOR_WINDOW+1);   
  150.   
  151.      /* Register the window class, and if it fails quit the program */   
  152.      if  (!RegisterClassEx (&wincl))   
  153.          return  0;   
  154.   
  155.      /* The class is registered, let's create the program*/   
  156.     hwnd = CreateWindowEx (   
  157.            0,                    /* Extended possibilites for variation */   
  158.            szClassName,          /* Classname */   
  159.             "MyTerics" ,       /* Title Text */   
  160.            WS_OVERLAPPEDWINDOW,  /* default window */   
  161.            CW_USEDEFAULT,        /* Windows decides the position */   
  162.            CW_USEDEFAULT,        /* where the window ends up on the screen */   
  163.            500,                  /* The programs width */   
  164.            500,                  /* and height in pixels */   
  165.            HWND_DESKTOP,         /* The window is a child-window to desktop */   
  166.            NULL,                 /* No menu */   
  167.            hThisInstance,        /* Program Instance handler */   
  168.            NULL                  /* No Window Creation data */   
  169.            );   
  170.      /* Make the window visible on the screen */   
  171.     ShowWindow (hwnd, nFunsterStil);   
  172.   
  173.      /* Run the message loop. It will run until GetMessage() returns 0 */   
  174.      while  (GetMessage (&messages, NULL, 0, 0))   
  175.     {   
  176.          /* Translate virtual-key messages into character messages */   
  177.         TranslateMessage(&messages);   
  178.          /* Send message to WindowProcedure */   
  179.         DispatchMessage(&messages);   
  180.     }   
  181.   
  182.      /* The program return-value is 0 - The value that PostQuitMessage() gave */   
  183.      return  messages.wParam;   
  184. }   
  185.   
  186.   
  187. /*  This function is called by the Windows function DispatchMessage()  */   
  188.   
  189. LRESULT  CALLBACK   
  190. WindowProcedure ( HWND  hwnd,  UINT  message,  WPARAM  wParam,  LPARAM  lParam)   
  191. {   
  192.     PAINTSTRUCT ps;   
  193.      HDC  hdc;   
  194.     RECT rt;   
  195.      HBRUSH  brush;   
  196.      switch  (message)                   /* handle the messages */   
  197.     {   
  198.          case  WM_CREATE:   
  199.         SetTimer(hwnd,1,1000,NULL);   
  200.          break ;   
  201.          case  WM_PAINT:   
  202.             hdc = BeginPaint(hwnd, &ps);   
  203.             brush = CreateSolidBrush(RGB(171,189,193));   
  204.             GetClientRect(hwnd,&rt);   
  205.             FillRect(hdc,&rt,brush);   
  206.             PrintInfo(hdc,count,score);   
  207.             EraseGameRegion(hdc);   
  208.             DrawGameRegion(hdc);   
  209.             InitTericsInfo();   
  210.             LoadCurrentTerics(hdc);   
  211.             DrawTetromino(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x,CurrentTericsInfo.y);   
  212.             EndPaint(hwnd, &ps);   
  213.              break ;   
  214.          case  WM_KEYDOWN:   
  215.         hdc = GetDC(hwnd);   
  216.          switch (wParam)   
  217.         {   
  218.              case  VK_UP:   
  219.              if  (!IsOutOfRegion(CurrentTericsInfo.shape,(CurrentTericsInfo.dir + 1)%4,CurrentTericsInfo.x,CurrentTericsInfo.y))   
  220.             {   
  221.                 CurrentTericsInfo.dir = ++CurrentTericsInfo.dir % 4;   
  222.                 EraseGameRegion(hdc);   
  223.                 DrawGameRegion(hdc);   
  224.                 LoadCurrentTerics(hdc);   
  225.                 DrawTetromino(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x,CurrentTericsInfo.y);   
  226.             }   
  227.              break ;   
  228.              case  VK_LEFT:   
  229.              if  (!IsOutOfRegion(CurrentTericsInfo.shape,CurrentTericsInfo.dir,(CurrentTericsInfo.x - 1),CurrentTericsInfo.y))   
  230.             {   
  231.                 --CurrentTericsInfo.x;   
  232.                 EraseGameRegion(hdc);   
  233.                 DrawGameRegion(hdc);   
  234.                 LoadCurrentTerics(hdc);   
  235.                 DrawTetromino(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x,CurrentTericsInfo.y);      
  236.             }   
  237.              break ;   
  238.              case  VK_RIGHT:   
  239.              if  (!IsOutOfRegion(CurrentTericsInfo.shape,CurrentTericsInfo.dir,(CurrentTericsInfo.x + 1),CurrentTericsInfo.y))   
  240.             {   
  241.                 ++CurrentTericsInfo.x;   
  242.                 EraseGameRegion(hdc);   
  243.                 DrawGameRegion(hdc);   
  244.                 LoadCurrentTerics(hdc);   
  245.                 DrawTetromino(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x,CurrentTericsInfo.y);      
  246.             }   
  247.              break ;   
  248.              case  VK_DOWN:   
  249.              if  (!IsOutOfRegion(CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x ,(CurrentTericsInfo.y + 1)))   
  250.             {   
  251.                 ++CurrentTericsInfo.y;   
  252.                 EraseGameRegion(hdc);   
  253.                 DrawGameRegion(hdc);   
  254.                 LoadCurrentTerics(hdc);   
  255.                 DrawTetromino(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x,CurrentTericsInfo.y);      
  256.             }   
  257.              else   
  258.             {   
  259.                 SaveStateofTerics(CurrentTericsInfo.shape,CurrentTericsInfo.dir,nx,ny,&count);   
  260.                 PrintInfo(hdc,count,score);   
  261.                 InvalidateRect(hwnd,NULL,FALSE);   
  262.             }   
  263.              break ;    
  264.         }   
  265.         ReleaseDC(hwnd,hdc);   
  266.          break ;   
  267.          case  WM_TIMER:   
  268.         hdc = GetDC(hwnd);   
  269.          if  (!IsOutOfRegion(CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x ,(CurrentTericsInfo.y + 1)))   
  270.         {   
  271.             ++CurrentTericsInfo.y;   
  272.             EraseGameRegion(hdc);   
  273.             DrawGameRegion(hdc);   
  274.             LoadCurrentTerics(hdc);   
  275.             DrawTetromino(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x,CurrentTericsInfo.y);      
  276.         }   
  277.          else   
  278.         {   
  279.             SaveStateofTerics(CurrentTericsInfo.shape,CurrentTericsInfo.dir,nx,ny,&count);   
  280.             PrintInfo(hdc,count,score);   
  281.             InvalidateRect(hwnd,NULL,FALSE);   
  282.         }   
  283.         ReleaseDC(hwnd,hdc);   
  284.          break ;   
  285.          case  WM_DESTROY:   
  286.             PostQuitMessage (0);        /* send a WM_QUIT to the message queue */   
  287.              break ;   
  288.          default :                       /* for messages that we don't deal with */   
  289.              return  DefWindowProc (hwnd, message, wParam, lParam);   
  290.     }   
  291.   
  292.      return  0;   
  293. }   
  294. void  DrawGameRegion( HDC  hdc)          
  295. {       
  296.      HBRUSH  brush;   
  297.      int  LeftX = GameSizeX;  //游戏区左上角横坐标       
  298.      int  LeftY = GameSizeY;  //游戏区坐上角纵坐标       
  299.      //游戏区右下角横坐 标       
  300.      int  Width =  LeftX + GameRegionWidth * SquareSize;        
  301.      //游戏区右下角纵坐 标       
  302.      int  Height = LeftY + GameRegionHeight * SquareSize;    
  303.     brush = CreateSolidBrush(RGB(171,189,193));   
  304.     SelectObject(hdc,brush);   
  305.     Rectangle(hdc,LeftX,LeftY,Width,Height);    
  306.     DeleteObject(brush);    
  307. }   
  308. void  DrawRectangle( HDC  hdc, int  shape, int  x, int  y)         
  309. {       
  310.      HBRUSH  brush;   
  311.      int  LeftX = GameSizeX + x * SquareSize;       
  312.      int  LeftY = GameSizeY + y * SquareSize;       
  313.      int  Width = LeftX + SquareSize;       
  314.      int  Height = LeftY + SquareSize;   
  315.     brush = CreateSolidBrush(color[shape]);   
  316.     SelectObject(hdc,brush);       
  317.     Rectangle(hdc,LeftX,LeftY,Width,Height);   
  318.     DeleteObject(brush);        
  319. }      
  320. void  DrawTetromino( HDC  hdc, int  shape, int  dir, int  x, int  y)         
  321. {       
  322.        int  index;    
  323.       RECT rect;    
  324.        for  ( index = 0; index < 4; ++index)       
  325.       {       
  326.           nx[index] = Terics[shape][dir][index].x + x;       
  327.           ny[index] = Terics[shape][dir][index].y + y;       
  328.           rect.left = nx[index];   
  329.           rect.top = ny[index];   
  330.           rect.right = SquareSize + nx[index];   
  331.           rect.bottom = SquareSize + ny[index];   
  332.           DrawRectangle(hdc,shape,nx[index],ny[index]);      
  333.       }     
  334. }        
  335. BOOL  IsOutOfRegion( int  shape,  int  dir,  int  x,  int  y)         
  336. {       
  337.          int  index;       
  338.          int  nx,ny;       
  339.          for  (index = 0; index < 4; ++index)       
  340.         {       
  341.             nx = Terics[shape][dir][index].x + x;        
  342.             ny = Terics[shape][dir][index].y + y;       
  343.              if  (ny >= GameRegionHeight || ny < 0 || nx < 0 || nx >= GameRegionWidth  || GameMapStates[nx][ny] != 0)       
  344.             {       
  345.                  return  TRUE;        
  346.             }       
  347.         }       
  348.          return  FALSE;       
  349. }       
  350. void  SaveStateofTerics( int  shape,  int  dir,  int  *x,  int  *y, int  *count)         
  351. {       
  352.      int  index;          
  353.      for  ( index = 0; index < 4; ++index)       
  354.     {        
  355.         GameMapStates[x[index]][y[index]] = 1;      
  356.     }    
  357.      BOOL  flag;       
  358.      int  indexX,indexY;       
  359.      int  m,n;       
  360.      for  (indexX = 0; indexX < GameRegionHeight; ++indexX)   
  361.     {       
  362.          flag = TRUE;   
  363.           for  (indexY = 0; indexY < GameRegionWidth; ++indexY)       
  364.          {       
  365.              if  (GameMapStates[indexY][indexX] != 1)       
  366.             {       
  367.       
  368.                 flag = FALSE;       
  369.       
  370.             }       
  371.            
  372.          }   
  373.           if  (flag)       
  374.          {           
  375.              for  (m = indexX; m >= 1; --m)   
  376.                 for  (n = 0; n < GameRegionWidth;++n)       
  377.                 {       
  378.                     GameMapStates[n][m] = GameMapStates[n][m-1];      
  379.                 }     
  380.                 ++(*count);     
  381.          }       
  382.     }   
  383. }   
  384. void  EraseGameRegion( HDC  hdc)        
  385. {       
  386.       RECT rect;       
  387.       rect.left = GameSizeX;       
  388.       rect.top = GameSizeY;       
  389.       rect.right = GameSizeX + GameRegionWidth * SquareSize;       
  390.       rect.bottom = GameSizeY + GameRegionHeight * SquareSize;       
  391.        HBRUSH  brush = CreateSolidBrush(RGB(255,255,255));       
  392.       FillRect(hdc,&rect,brush);   
  393.       DeleteObject(brush);          
  394. }       
  395. void  LoadCurrentTerics( HDC  hdc)        
  396. {       
  397.        int  indexX,indexY,shape;   
  398.       srand((unsigned)time(NULL));     
  399.       shape = rand() % 7;   
  400.        for  (indexX = 0; indexX < GameRegionWidth; ++indexX)    
  401.           for  (indexY = 0; indexY < GameRegionHeight; ++indexY)       
  402.          {       
  403.             if  (GameMapStates[indexX][indexY] == 1)       
  404.            {       
  405.                  DrawRectangle(hdc,shape,indexX,indexY);      
  406.            }       
  407.          }    
  408. }    
  409. void  InitTericsInfo()        
  410. {       
  411.     srand((unsigned)time(NULL));       
  412.     CurrentTericsInfo.shape = rand()%7;       
  413.     CurrentTericsInfo.dir = 0;       
  414.     CurrentTericsInfo.x = 4;       
  415.     CurrentTericsInfo.y = 0;       
  416. }    
  417. void  PrintInfo( HDC  hdc, int  count, int  score)   
  418. {   
  419.      char  szScore[] =  "Score: " ;   
  420.      char  szRowCount[] =  "row: " ;    
  421.      char  strCount[10],strScore[10];   
  422.     itoa(10*count,strScore,10);   
  423.     itoa(count,strCount,10);    
  424.     strcat(szScore,strScore);   
  425.     strcat(szRowCount,strCount);   
  426.     SetBkColor(hdc,RGB(171,189,193));   
  427.     TextOut(hdc,300,150,szScore,strlen(szScore));   
  428.     TextOut(hdc,300,200,szRowCount,strlen(szRowCount));   
  429. }  

这个种方法写出来的效果,说实话,效率有点低,代码实现上有点麻烦,每次移动方块都需要从新加载整个游戏。并且这种实现效果在改变外观上也有点 难。。。以后我会用另一种方法去实现,那种方法效率会高点,外观也比较美观。

若那位同学对实现上有更好的建议,欢迎指教。

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值