邪恶八进制信息安全团队技术讨论组's Archiver

恶猫 2005-1-16 18:40

[转载]分析SDK下的俄罗斯方块程序(仅供学习使用)

原作者姓名 毛建忠
文章原始出处 网络

介绍
对API有一定了解的可以看看

读者评分 3 评分次数 1

正文
[code]
// ToyBricks.cpp : Defines the entry point for the application.
//

#include "stdafx.h"


/*******************************************************/

/* 文 件 名: ToyBricks.c
* 完成时间: 2001年9月
* 完成地点: 华东地质学院综合楼507机房
* 开发模式: SDK程序
* 开发环境: MS VC++ 6.0
* 作   者: 毛建忠
* 工作单位: 中国建设银行三水市(广东省)支行
* E - Mail: [email]Mao_jzh@163.com[/email]     
*/

/* 备注:
*    这是一个简单的俄罗斯方块游戏程序,写程序时没有注释,
* 这是我写程序时的一个坏习惯。毕业有半年了,也就半年没有写
* 过程序,周末闲着没事,捡起那些旧程序看看,顺便加上一些注
* 释。很怀念在学校写程序的那段日子,很怀念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 previous 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 pre-compiled header
//   stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
[/code]
--------------------------------------------------------------------------------

正文完

页: [1]
© 1999-2008 EvilOctal Security Team