SDK下的俄罗斯方块程序分析

来源:互联网 发布:js如何获取cookie参数 编辑:程序博客网 时间:2024/05/21 00:21
  // ToyBricks.cpp : Defines the entry point for the application.       //     #include "stdafx.h"     /*******************************************************/       /* 文 件 名: ToyBricks.c       * 完成时间: 2001年9月       * 完成地点: 华东地质学院综合楼507机房       * 开发模式: SDK程序       * 开发环境: MS VC++ 6.0       * 作 者: 毛建忠       * 工作单位: 中国建设银行三水市(广东省)支行       * E - Mail: Mao_jzh@163.com       */       /* 备注:       * 这是一个简单的俄罗斯方块游戏程序,写程序时没有注释,       * 这是我写程序时的一个坏习惯。            正在装载数据……      毕业有半年了,也就半年没有写       * 过程序,周末闲着没事,捡起那些旧程序看看,顺便加上一些注       * 释。很怀念在学校写程序的那段日子,很怀念507。       */       /*******************************************************/       #include <windows.h>       #include <time.h>       #include <stdlib.h>       #define CELL 15 // 【方格】的边长(pix)       #define W 22 // 游戏区宽(22个【方格】边长)       #define H 30 // 游戏区高(30个【方格】边长)       #define MS_NEWBLOCK WM_USER+1 // 消息ID,产生新的【方块】       #define MS_DRAW WM_USER+2       LRESULT CALLBACK WndProc ( HWND, UINT, WPARAM, LPARAM);//窗口过程处理       int WINAPI WinMain ( HINSTANCE hInstance, //当前实例句柄       HINSTANCE hPrevInstance, //前一实例句柄       PSTR szCmdLine, //指向程序命令行参数的指针       int iCmdShow) //应用程序开始执行窗口时显示方式用int类型标志       {       static char AppName[]="ToyBrick";//定义一个静态字符数组保存字符串"ToyBrick"(机应用程序名)       HWND hwnd; //定义一个窗口句柄       MSG msg; //定义一消息结构体变量       WNDCLASSEX wndclass; //定义一窗口类结构变量,包含窗口类全部信息       int iScreenWide; //定义屏幕显示宽度       wndclass.cbSize = sizeof(wndclass);//窗口类对象大小       wndclass.style = CS_HREDRAW|CS_VREDRAW;//窗口类对象风格       wndclass.lpfnWndProc = WndProc;//窗口处理函数为WndProc       wndclass.cbClsExtra = 0; //窗口类无扩展       wndclass.cbWndExtra = 0;//窗口类实例没有扩展       wndclass.hInstance = hInstance;//当前实例句柄       wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);//窗口最小化图标为默认图标       wndclass.hCursor = LoadCursor (NULL,IDC_ARROW);//窗口当前光标为箭头光标       wndclass.hbrBackground = (HBRUSH)GetStockObject       (BLACK_BRUSH);//获得当前背景设置为黑色       wndclass.lpszMenuName = NULL;//窗体菜单名为空       wndclass.lpszClassName = AppName;//应用程序名       wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);//为应用程序加载图标       if(!RegisterClassEx (&wndclass)) return FALSE; //注册一个窗口类       // 获取显示器分辨率的X值iScreenWide,将程序窗口置于屏幕中央       iScreenWide=GetSystemMetrics (SM_CXFULLSCREEN);       //创建窗口       hwnd =CreateWindow (AppName,       "俄罗斯方块",       WS_MINIMIZEBOX|WS_SYSMENU ,       iScreenWide/2-W*CELL/2, CELL,       (W+1)*CELL-8, H*CELL,       NULL, NULL,       hInstance,       NULL );       if(!hwnd) return FALSE; //没有获得窗口句柄,返回假       ShowWindow (hwnd,iCmdShow); //显示窗口       UpdateWindow (hwnd); //更新窗口       MessageBox(hwnd,"开始游戏","开始",MB_OK);//显示Message       SendMessage(hwnd,MS_NEWBLOCK,0,0);//向当前窗口发送消息       SetTimer (hwnd, 1, 550,NULL);//设置下落时间       while (GetMessage (&msg, NULL, 0, 0))//进入消息循环       {       TranslateMessage (&msg);       DispatchMessage (&msg);       }       return msg.wParam;       }       // 函数DrawRact: 画【正方形】       // 参数: 设备环境句柄和【正方形】的四角坐标       void DrawRect (HDC hdc, int l, int t, int r, int b)       {       MoveToEx (hdc, l, t, NULL);       LineTo (hdc, r, t);       LineTo (hdc, r, b);       LineTo (hdc, l, b);       LineTo (hdc, l,t);       }       // 函数DrawCell: 画【方格】       // 参数: 设备环境句柄和【方格】的四角坐标       // 每个方格由内外两个【正方形】(DrawCell)画成,使其有立体感       void DrawCell (HDC hdc, int l, int t, int r, int b)       {       DrawRect (hdc,l+1, t+1, r-1, b-1);       DrawRect (hdc,l+3, t+3, r-3, b-3);       }       // 函数DrawBlock: 画【方块】       // 参数: 设备环境句柄和【方块】中四个【方格】在游戏区域中的位置       // 每个【方块】由四个【方格】组成7种不同的形状       void DrawBlock (HDC hdc, int block[4][2])       {       int i;       HPEN hpen;       hpen =CreatePen (PS_SOLID,1,RGB(255,255,255));       SelectObject (hdc,hpen);       for(i=0; i<4; i++)       DrawCell (hdc, (block[i][0]-1)*CELL, (block[i][1]-1)*CELL, //....       block[i][0]*CELL, block[i][1]*CELL);       DeleteObject (hpen);       }       // 函数Cover: 清除原来位置的【方块】       // 参数: 设备环境句柄和待清除的【方块】       // 清除【方块】即在该【方块】的每个【方块】处画一个正方形的黑块       void Cover (HDC hdc, int org[4][2])       {       int i;       SelectObject (hdc, (HBRUSH)GetStockObject (BLACK_BRUSH));       for(i=0; i<4; i++)       Rectangle ( hdc, (org[i][0]-1)*CELL, (org[i][1]-1)*CELL, //.....       org[i][0]*CELL, org[i][1]*CELL);       }       // 窗口过程函数WndProc       LRESULT CALLBACK WndProc ( HWND hwnd,       UINT iMsg,       WPARAM wParam,       LPARAM lParam )       {       int i,j,k,lines,r;       static int top, sel, flag;       static int cells[W+2][H]; // 控制游戏的【方格矩阵】       static int org[4][2], block[4][2]; // 【方块】       HDC hdc;       HPEN hpen;       PAINTSTRUCT ps;       switch (iMsg)       {       case WM_CREATE:       top=H-1;       // 将第一列和最后一列【方格】置1,控制【方块】不超出游戏区域       for(i=0; i<H; i++)       { cells[0][i]=1; cells[W+1][i]=1; }       // 将最底下一行【方格】置1,控制【方块】不超出游戏区域       for(i=0; i<W+2; i++) cells[i][H-1]=1;       // 其他【方格】置0,游戏方块只能在这里移动       for(i=1; i<=W; i++)       for(j=0; j<H-1; j++)       cells[i][j]=0;       return 0;       case MS_NEWBLOCK:       flag=0; // flag表示【方块】旋转了几次       for(i=top; i<H-1; i++)       {       lines =0;       // 循环语句检查是否有某一行全部被【方格】都填满       for(j=1; j<=W+1; j++)       if(! cells[j][i])       { lines=1; break; }       // 若该行被填满,则将上一行的填充状态复制到该行,依此类推       // 即从该行开始,所有的【方格】都下移一行       if(!lines)       { for(j=1;j<W+1; j++)       for(k=i; k>=top; k--)       cells[j][k]=cells[j][k-1];       top++;       InvalidateRect (hwnd, NULL, TRUE);       }       }       // 产生随机数0~7,分别代表【方块】的7种形状       srand( (unsigned)time( NULL ) );       sel =rand()%7;       //【方块】形状初始化       //【方块】的形状由其每个【方格】的位置决定       // 游戏区宽W=22,block[?][0]=9/10/11/12,block[?][1]=0/1/2       // 这样【方块】初始位置在游戏区的最顶部的中央       switch(sel)       {       case 0:       // ▓▓       // ▓▓       org[0][0]=block[0][0] =10; org[0][1]=block[0][1] =0;       org[1][0]=block[1][0] =11; org[1][1]=block[1][1] =0;       org[2][0]=block[2][0] =10; org[2][1]=block[2][1] =1;       org[3][0]=block[3][0] =11; org[3][1]=block[3][1] =1;       break;       case 1:       // ▓▓▓▓       org[0][0]=block[0][0] =9; org[0][1]=block[0][1] =0;       org[1][0]=block[1][0] =10; org[1][1]=block[1][1] =0;       org[2][0]=block[2][0] =11; org[2][1]=block[2][1] =0;       org[3][0]=block[3][0] =12; org[3][1]=block[3][1] =0;       break;       case 2:       //▓       //▓▓       // ▓       org[0][0]=block[0][0] =10; org[0][1]=block[0][1] =0;       org[1][0]=block[1][0] =10; org[1][1]=block[1][1] =1;       org[2][0]=block[2][0] =11; org[2][1]=block[2][1] =1;       org[3][0]=block[3][0] =11; org[3][1]=block[3][1] =2;       break;       case 3:       // ▓       //▓▓       //▓       org[0][0]=block[0][0] =11; org[0][1]=block[0][1] =0;       org[1][0]=block[1][0] =11; org[1][1]=block[1][1] =1;       org[2][0]=block[2][0] =10; org[2][1]=block[2][1] =1;       org[3][0]=block[3][0] =10; org[3][1]=block[3][1] =2;       break;       case 4:       //▓       //▓       //▓▓       org[0][0]=block[0][0] =10; org[0][1]=block[0][1] =0;       org[1][0]=block[1][0] =10; org[1][1]=block[1][1] =1;       org[2][0]=block[2][0] =10; org[2][1]=block[2][1] =2;       org[3][0]=block[3][0] =11; org[3][1]=block[3][1] =2;       break;       case 5:       // ▓       // ▓       //▓▓       org[0][0]=block[0][0] =10; org[0][1]=block[0][1] =0;       org[1][0]=block[1][0] =10; org[1][1]=block[1][1] =1;       org[2][0]=block[2][0] =10; org[2][1]=block[2][1] =2;       org[3][0]=block[3][0] =9; org[3][1]=block[3][1] =2;       break;       case 6:       // ▓       //▓▓▓       org[0][0]=block[0][0] =10; org[0][1]=block[0][1] =0;       org[1][0]=block[1][0] =9; org[1][1]=block[1][1] =1;       org[2][0]=block[2][0] =10; org[2][1]=block[2][1] =1;       org[3][0]=block[3][0] =11; org[3][1]=block[3][1] =1;       break;       default:       SendMessage (hwnd, MS_NEWBLOCK, 0, 0);       break;       }       return 0;       case WM_TIMER:       // 每个时间节拍【方块】自动下移一行       for(i=0; i<4; i++)       block[i][1]++;       // 检查【方块】下移是否被档住,即判断下移后新位置是否有【方格】       for(i=0; i<4; i++)       if(cells[ block[i][0] ][ block[i][1] ])       {       for(i=0; i<4; i++)       cells[ org[i][0] ][ org[i][1] ]=1;       if(top>org[0][1]-2) top=org[0][1]-2;       if (top<1)       {       KillTimer (hwnd, 1);       MessageBox (hwnd, "游戏结束,即将退出 !", "退出", MB_OK);       PostQuitMessage (0);       }       SendMessage (hwnd, MS_NEWBLOCK, 0, 0);       return 0;       }       SendMessage (hwnd, MS_DRAW, 0, 0);       return 0;       // 响应键盘控制       case WM_KEYDOWN:       r=0;       switch((int)wParam)       {       case VK_LEFT:       for(i=0; i<4; i++)       block[i][0]--;       break;       case VK_RIGHT:       for(i=0; i<4; i++)       block[i][0]++;       break;       case VK_DOWN:       for(i=0; i<4; i++)       block[i][1]++;       break;       // 按[向上键],【方块】顺时针旋转       //【方块】的旋转不是真正的旋转,而是根据不同的【方块】形状和       // 该【方块】旋转过的次数来移动其中的一个或几个【方格】,从而       // 达到旋转的效果 这样做很复杂,算法不够理想,但是能够保持【方       // 块】旋转时的重心比较稳定。       case VK_UP:       r=1;       flag++; //【方块】旋转加1       switch(sel) // sel代表当前【方块】的形状       {       case 0: break;       case 1:       flag =flag%2;       for(i=0; i<4; i++)       {       block[i][(flag+1)%2] =org[2][(flag+1)%2];       block[i][flag] =org[2][flag]-2+i;       }       break;       case 2:       flag =flag%2;       if(flag)       { block[0][1] +=2; block[3][0] -=2; }       else       { block[0][1] -=2; block[3][0] +=2; }       break;       case 3:       flag =flag%2;       if(flag)       { block[0][1] +=2; block[3][0] +=2; }       else       { block[0][1] -=2; block[3][0] -=2; }       break;       case 4:       flag=flag%4;       switch(flag)       {       case 0:       block[2][0] +=2; block[3][0] +=2;       block[2][1] +=1; block[3][1] +=1;       break;       case 1:       block[2][0] +=1; block[3][0] +=1;       block[2][1] -=2; block[3][1] -=2;       break;       case 2:       block[2][0] -=2; block[3][0] -=2;       block[2][1] -=1; block[3][1] -=1;       break;       case 3:       block[2][0] -=1; block[3][0] -=1;       block[2][1] +=2; block[3][1] +=2;       break;       }       break;       case 5:       flag=flag%4;       switch(flag)       {       case 0:       block[2][0] +=1; block[3][0] +=1;       block[2][1] +=2; block[3][1] +=2;       break;       case 1:       block[2][0] +=2; block[3][0] +=2;       block[2][1] -=1; block[3][1] -=1;       break;       case 2:       block[2][0] -=1; block[3][0] -=1;       block[2][1] -=2; block[3][1] -=2;       break;       case 3:       block[2][0] -=2; block[3][0] -=2;       block[2][1] +=1; block[3][1] +=1;       break;       }       break;       case 6:       flag =flag%4;       switch(flag)       {       case 0:       block[0][0]++; block[0][1]--;       block[1][0]--; block[1][1]--;       block[3][0]++; block[3][1]++;       break;       case 1:       block[1][0]++; block[1][1]++; break;       case 2:       block[0][0]--; block[0][1]++; break;       case 3:       block[3][0]--; block[3][1]--; break;       }       break;       }       break;       }       // 判断【方块】旋转后新位置是否有【方格】,若有,则旋转取消       for(i=0; i<4; i++)       if(cells[ block[i][0] ][ block[i][1] ])       {       if(r) flag +=3;       for(i=0; i<4; i++)       for(j=0; j<2; j++)       block[i][j]=org[i][j];       return 0;       }       SendMessage(hwnd, MS_DRAW, 0, 0);;       return 0;       // 清除当前【方块】,并在新的位置重新绘制【方块】       case MS_DRAW:       hdc =GetDC (hwnd);       Cover (hdc, org);       for(i=0; i<4; i++)       for(j=0; j<2; j++)       org[i][j]=block[i][j];       DrawBlock (hdc,block);       ReleaseDC (hwnd, hdc);       return 0;       // 按照【方格矩阵】重绘游戏区域的【方格】       case WM_PAINT:       hdc =BeginPaint (hwnd, &ps);       hpen =CreatePen (PS_SOLID,1,RGB(255,255,255));       SelectObject (hdc,hpen);       for (i=top; i<H-1; i++)       for(j=1; j<=W; j++)       if( cells[j][i] )       DrawCell (hdc, (j-1)*CELL, (i-1)*CELL, j*CELL, i*CELL);       DeleteObject (hpen);       EndPaint (hwnd, &ps);       return 0;       case WM_DESTROY:       KillTimer (hwnd, 1);       PostQuitMessage (0);       return 0;       }       return DefWindowProc (hwnd, iMsg, wParam, lParam);       }       /************************************************************/       /* 结束       * 注释时间: 2003/01/04 SAT       * 于 广东省三水市建行宿舍       */       /************************************************************/       -------------------------------------------------------------------------------------       // stdafx.h : include file for standard system include files,       // or project specific include files that are used frequently, but       // are changed infrequently       //       #if       !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)       #define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_       #if _MSC_VER > 1000       #pragma once       #endif // _MSC_VER > 1000       #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows       headers       #include <windows.h>       // TODO: reference additional headers your program requires here       //{{AFX_INSERT_LOCATION}}       // Microsoft Visual C++ will insert additional declarations immediately       before the divvious line.       #endif //       !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)       ----------------------------------------------------------------------------------------       // stdafx.cpp : source file that includes just the standard includes       // ToyBricks.pch will be the div-compiled header       // stdafx.obj will contain the div-compiled type information       #include "stdafx.h"       // TODO: reference any additional headers you need in STDAFX.H       // and not in this file       --------------------------------------------------------------------------------       

原创粉丝点击