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

对上一篇日志里的代码进行调试和更改后,终于运行成功了。最终的代码对上篇的代码有些小的改动,但思想是没有改变的。这里改变了部分的实现方式,由于原来的有些方式不知怎的,总感觉那些实现方式很正常,却有得不到我想要的行为,并且我在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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值