对上一篇日志里的代码进行调试和更改后,终于运行成功了。最终的代码对上篇的代码有 些小的改动,但思想是没有改变的。这里改变了部分的实现方式,由于原来的有些方式不知怎的,总感觉那些实现方式很正常,却有得不到我想要的行为,并且我在 VC++6.0里面单独试验了这个小行为,明明是可以实现的,。呵呵。怪异,只好换方式了,看来我以后有必要对此进行总结一下了,要不这次的动手练习就白 费了。。
效 果如下:
代 码如下:
- #include <windows.h>
- #include <stdlib.h>
- const int SquareSize = 20; //方块大小
- const int GameSizeX = 50; //游戏区左上角横坐标
- const int GameSizeY = 50; //游戏区左上角纵坐标
- const int GameRegionWidth = 10;
- const int GameRegionHeight = 20;
- int GameMapStates[10][20] = {0}; //用于保存游戏区的状态
- int nx[4],ny[4];
- int count = 0;
- int score = 0;
- struct CurrentTerics
- {
- int shape,dir,x,y;
- }CurrentTericsInfo;
- const COLORREF color[7] =
- {
- RGB(255,0,0),
- RGB(237,138,5),
- RGB(248,236,6),
- RGB(27,227,51),
- RGB(10,128,147),
- RGB(20,12,184),
- RGB(106,38,196)
- };
- const POINT Terics[7][4][4] =
- {
- {
- 0,0,1,0,0,1,-1,1,
- 0,0,0,1,1,1,1,2,
- 0,0,1,0,0,1,-1,1,
- 0,0,0,1,1,1,1,2
- },
- {
- 0,0,1,0,1,1,2,1,
- 0,0,0,1,-1,1,-1,2,
- 0,0,1,0,1,1,2,1,
- 0,0,0,1,-1,1,-1,2
- },
- {
- 0,0,0,1,0,2,1,2,
- 0,0,0,1,-1,1,-2,1,
- 0,0,1,0,1,1,1,2,
- 0,0,0,1,1,0,2,0
- },
- {
- 0,0,0,1,0,2,-1,2,
- 0,0,1,0,2,0,2,1,
- 0,0,1,0,0,1,0,2,
- 0,0,0,1,1,1,2,1
- },
- {
- 0,0,0,1,0,2,0,3,
- 0,0,1,0,2,0,3,0,
- 0,0,0,1,0,2,0,3,
- 0,0,1,0,2,0,3,0
- },
- {
- 0,0,1,0,0,1,1,1,
- 0,0,1,0,0,1,1,1,
- 0,0,1,0,0,1,1,1,
- 0,0,1,0,0,1,1,1
- },
- {
- 0,0,1,0,2,0,1,1,
- 0,0,0,1,0,2,1,1,
- 0,0,0,1,-1,1,1,1,
- 0,0,0,1,0,2,-1,1
- }
- };
- void DrawGameRegion( HDC hdc);
- void DrawRectangle( HDC hdc, int shape, int x, int y);
- void DrawTetromino( HDC hdc, int shape, int dir, int x, int y);
- BOOL IsOutOfRegion( int shape, int dir, int x, int y);
- void SaveStateofTerics( int shape, int dir, int *x, int *y, int *count);
- void EraseGameRegion( HDC hdc);
- void LoadCurrentTerics( HDC hdc);
- void InitTericsInfo();
- void PrintInfo( HDC hdc, int count, int score);
- /* Declare Windows procedure */
- LRESULT CALLBACK WindowProcedure ( HWND , UINT , WPARAM , LPARAM );
- /* Make the class name into a global variable */
- char szClassName[ ] = "WindowsApp" ;
- int WINAPI
- WinMain ( HINSTANCE hThisInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpszArgument,
- int nFunsterStil)
- {
- HWND hwnd; /* This is the handle for our window */
- MSG messages; /* Here messages to the application are saved */
- WNDCLASSEX wincl; /* Data structure for the windowclass */
- /* The Window structure */
- wincl.hInstance = hThisInstance;
- wincl.lpszClassName = szClassName;
- wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
- wincl.style = CS_DBLCLKS; /* Catch double-clicks */
- wincl.cbSize = sizeof (WNDCLASSEX);
- /* Use default icon and mouse-pointer */
- wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
- wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
- wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
- wincl.lpszMenuName = NULL; /* No menu */
- wincl.cbClsExtra = 0; /* No extra bytes after the window class */
- wincl.cbWndExtra = 0; /* structure or the window instance */
- /* Use Windows's default color as the background of the window */
- wincl.hbrBackground = ( HBRUSH )(COLOR_WINDOW+1);
- /* Register the window class, and if it fails quit the program */
- if (!RegisterClassEx (&wincl))
- return 0;
- /* The class is registered, let's create the program*/
- hwnd = CreateWindowEx (
- 0, /* Extended possibilites for variation */
- szClassName, /* Classname */
- "MyTerics" , /* Title Text */
- WS_OVERLAPPEDWINDOW, /* default window */
- CW_USEDEFAULT, /* Windows decides the position */
- CW_USEDEFAULT, /* where the window ends up on the screen */
- 500, /* The programs width */
- 500, /* and height in pixels */
- HWND_DESKTOP, /* The window is a child-window to desktop */
- NULL, /* No menu */
- hThisInstance, /* Program Instance handler */
- NULL /* No Window Creation data */
- );
- /* Make the window visible on the screen */
- ShowWindow (hwnd, nFunsterStil);
- /* Run the message loop. It will run until GetMessage() returns 0 */
- while (GetMessage (&messages, NULL, 0, 0))
- {
- /* Translate virtual-key messages into character messages */
- TranslateMessage(&messages);
- /* Send message to WindowProcedure */
- DispatchMessage(&messages);
- }
- /* The program return-value is 0 - The value that PostQuitMessage() gave */
- return messages.wParam;
- }
- /* This function is called by the Windows function DispatchMessage() */
- LRESULT CALLBACK
- WindowProcedure ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- PAINTSTRUCT ps;
- HDC hdc;
- RECT rt;
- HBRUSH brush;
- switch (message) /* handle the messages */
- {
- case WM_CREATE:
- SetTimer(hwnd,1,1000,NULL);
- break ;
- case WM_PAINT:
- hdc = BeginPaint(hwnd, &ps);
- brush = CreateSolidBrush(RGB(171,189,193));
- GetClientRect(hwnd,&rt);
- FillRect(hdc,&rt,brush);
- PrintInfo(hdc,count,score);
- EraseGameRegion(hdc);
- DrawGameRegion(hdc);
- InitTericsInfo();
- LoadCurrentTerics(hdc);
- DrawTetromino(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x,CurrentTericsInfo.y);
- EndPaint(hwnd, &ps);
- break ;
- case WM_KEYDOWN:
- hdc = GetDC(hwnd);
- switch (wParam)
- {
- case VK_UP:
- if (!IsOutOfRegion(CurrentTericsInfo.shape,(CurrentTericsInfo.dir + 1)%4,CurrentTericsInfo.x,CurrentTericsInfo.y))
- {
- CurrentTericsInfo.dir = ++CurrentTericsInfo.dir % 4;
- EraseGameRegion(hdc);
- DrawGameRegion(hdc);
- LoadCurrentTerics(hdc);
- DrawTetromino(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x,CurrentTericsInfo.y);
- }
- break ;
- case VK_LEFT:
- if (!IsOutOfRegion(CurrentTericsInfo.shape,CurrentTericsInfo.dir,(CurrentTericsInfo.x - 1),CurrentTericsInfo.y))
- {
- --CurrentTericsInfo.x;
- EraseGameRegion(hdc);
- DrawGameRegion(hdc);
- LoadCurrentTerics(hdc);
- DrawTetromino(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x,CurrentTericsInfo.y);
- }
- break ;
- case VK_RIGHT:
- if (!IsOutOfRegion(CurrentTericsInfo.shape,CurrentTericsInfo.dir,(CurrentTericsInfo.x + 1),CurrentTericsInfo.y))
- {
- ++CurrentTericsInfo.x;
- EraseGameRegion(hdc);
- DrawGameRegion(hdc);
- LoadCurrentTerics(hdc);
- DrawTetromino(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x,CurrentTericsInfo.y);
- }
- break ;
- case VK_DOWN:
- if (!IsOutOfRegion(CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x ,(CurrentTericsInfo.y + 1)))
- {
- ++CurrentTericsInfo.y;
- EraseGameRegion(hdc);
- DrawGameRegion(hdc);
- LoadCurrentTerics(hdc);
- DrawTetromino(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x,CurrentTericsInfo.y);
- }
- else
- {
- SaveStateofTerics(CurrentTericsInfo.shape,CurrentTericsInfo.dir,nx,ny,&count);
- PrintInfo(hdc,count,score);
- InvalidateRect(hwnd,NULL,FALSE);
- }
- break ;
- }
- ReleaseDC(hwnd,hdc);
- break ;
- case WM_TIMER:
- hdc = GetDC(hwnd);
- if (!IsOutOfRegion(CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x ,(CurrentTericsInfo.y + 1)))
- {
- ++CurrentTericsInfo.y;
- EraseGameRegion(hdc);
- DrawGameRegion(hdc);
- LoadCurrentTerics(hdc);
- DrawTetromino(hdc,CurrentTericsInfo.shape,CurrentTericsInfo.dir,CurrentTericsInfo.x,CurrentTericsInfo.y);
- }
- else
- {
- SaveStateofTerics(CurrentTericsInfo.shape,CurrentTericsInfo.dir,nx,ny,&count);
- PrintInfo(hdc,count,score);
- InvalidateRect(hwnd,NULL,FALSE);
- }
- ReleaseDC(hwnd,hdc);
- break ;
- case WM_DESTROY:
- PostQuitMessage (0); /* send a WM_QUIT to the message queue */
- break ;
- default : /* for messages that we don't deal with */
- return DefWindowProc (hwnd, message, wParam, lParam);
- }
- return 0;
- }
- void DrawGameRegion( HDC hdc)
- {
- HBRUSH brush;
- int LeftX = GameSizeX; //游戏区左上角横坐标
- int LeftY = GameSizeY; //游戏区坐上角纵坐标
- //游戏区右下角横坐 标
- int Width = LeftX + GameRegionWidth * SquareSize;
- //游戏区右下角纵坐 标
- int Height = LeftY + GameRegionHeight * SquareSize;
- brush = CreateSolidBrush(RGB(171,189,193));
- SelectObject(hdc,brush);
- Rectangle(hdc,LeftX,LeftY,Width,Height);
- DeleteObject(brush);
- }
- void DrawRectangle( HDC hdc, int shape, int x, int y)
- {
- HBRUSH brush;
- int LeftX = GameSizeX + x * SquareSize;
- int LeftY = GameSizeY + y * SquareSize;
- int Width = LeftX + SquareSize;
- int Height = LeftY + SquareSize;
- brush = CreateSolidBrush(color[shape]);
- SelectObject(hdc,brush);
- Rectangle(hdc,LeftX,LeftY,Width,Height);
- DeleteObject(brush);
- }
- void DrawTetromino( HDC hdc, int shape, int dir, int x, int y)
- {
- int index;
- RECT rect;
- for ( index = 0; index < 4; ++index)
- {
- nx[index] = Terics[shape][dir][index].x + x;
- ny[index] = Terics[shape][dir][index].y + y;
- rect.left = nx[index];
- rect.top = ny[index];
- rect.right = SquareSize + nx[index];
- rect.bottom = SquareSize + ny[index];
- DrawRectangle(hdc,shape,nx[index],ny[index]);
- }
- }
- BOOL IsOutOfRegion( int shape, int dir, int x, int y)
- {
- int index;
- int nx,ny;
- for (index = 0; index < 4; ++index)
- {
- nx = Terics[shape][dir][index].x + x;
- ny = Terics[shape][dir][index].y + y;
- if (ny >= GameRegionHeight || ny < 0 || nx < 0 || nx >= GameRegionWidth || GameMapStates[nx][ny] != 0)
- {
- return TRUE;
- }
- }
- return FALSE;
- }
- void SaveStateofTerics( int shape, int dir, int *x, int *y, int *count)
- {
- int index;
- for ( index = 0; index < 4; ++index)
- {
- GameMapStates[x[index]][y[index]] = 1;
- }
- BOOL flag;
- int indexX,indexY;
- int m,n;
- for (indexX = 0; indexX < GameRegionHeight; ++indexX)
- {
- flag = TRUE;
- for (indexY = 0; indexY < GameRegionWidth; ++indexY)
- {
- if (GameMapStates[indexY][indexX] != 1)
- {
- flag = FALSE;
- }
- }
- if (flag)
- {
- for (m = indexX; m >= 1; --m)
- for (n = 0; n < GameRegionWidth;++n)
- {
- GameMapStates[n][m] = GameMapStates[n][m-1];
- }
- ++(*count);
- }
- }
- }
- void EraseGameRegion( HDC hdc)
- {
- RECT rect;
- rect.left = GameSizeX;
- rect.top = GameSizeY;
- rect.right = GameSizeX + GameRegionWidth * SquareSize;
- rect.bottom = GameSizeY + GameRegionHeight * SquareSize;
- HBRUSH brush = CreateSolidBrush(RGB(255,255,255));
- FillRect(hdc,&rect,brush);
- DeleteObject(brush);
- }
- void LoadCurrentTerics( HDC hdc)
- {
- int indexX,indexY,shape;
- srand((unsigned)time(NULL));
- shape = rand() % 7;
- for (indexX = 0; indexX < GameRegionWidth; ++indexX)
- for (indexY = 0; indexY < GameRegionHeight; ++indexY)
- {
- if (GameMapStates[indexX][indexY] == 1)
- {
- DrawRectangle(hdc,shape,indexX,indexY);
- }
- }
- }
- void InitTericsInfo()
- {
- srand((unsigned)time(NULL));
- CurrentTericsInfo.shape = rand()%7;
- CurrentTericsInfo.dir = 0;
- CurrentTericsInfo.x = 4;
- CurrentTericsInfo.y = 0;
- }
- void PrintInfo( HDC hdc, int count, int score)
- {
- char szScore[] = "Score: " ;
- char szRowCount[] = "row: " ;
- char strCount[10],strScore[10];
- itoa(10*count,strScore,10);
- itoa(count,strCount,10);
- strcat(szScore,strScore);
- strcat(szRowCount,strCount);
- SetBkColor(hdc,RGB(171,189,193));
- TextOut(hdc,300,150,szScore,strlen(szScore));
- TextOut(hdc,300,200,szRowCount,strlen(szRowCount));
- }
这个种方法写出来的效果,说实话,效率有点低,代码实现上有点麻烦,每次移动方块都需要从新加载整个游戏。并且这种实现效果在改变外观上也有点 难。。。以后我会用另一种方法去实现,那种方法效率会高点,外观也比较美观。
若那位同学对实现上有更好的建议,欢迎指教。
参照帖子:http://www.rupeng.com/forum/thread-2533-1-1-uid2704.html