C++러시아 블록 구현(windows API)

본 고 에서 공유 한 이 러시아 블록 코드 들 은 제 가 최근 에 방학 동안 집에 서 직접 쓴 것 입 니 다.예전 에 다른 사람 이 쓴 코드 를 본 적 이 있 지만 그 게임 코드 는 전면적 이지 않 은 것 같 습 니 다.모든 블록 과 무 작위 로 임의의 방향 을 가 진 블록 을 실현 할 수 없 기 때문에 지금도 그 당시 의 코드 를 잊 어 버 렸 습 니 다.아래 의 코드 들 은 제 가 최근 에 쓴 것 입 니 다.다른 사람의 코드 를 참고 하지 않 고 러시아 블록 을 진정 으로 쓰 는 것 은 정말 어 려 운 일이 다.관건 은 사각형 의 회전 이다.물론 아래 의 코드 는 하나의 프레임 워 크 일 뿐 대체적인 기능 만 실현 할 수 있 고 전면적 이지 않 으 며 여러분 과 교류 학습 을 할 수 있 습 니 다.
컴 파일 러 는 code:block  +  MinGW,CB 라 는 IDE 가 정말 강력 하 다 고 생각 합 니 다.너무 좋 습 니 다.아래 코드 를 VC 로 직접 복사 해서 실행 하 는 것 이 잘못 되 지 않 을 것 입 니 다.문 제 는 어떻게 해결 해 야 할 지 모 르 겠 습 니 다.바로 고객 지역 을 업데이트 할 때 창 이 반 짝 거 려 서 어떤 달인 이 저 를 지적 해 줄 수 있 는 지 모 르 겠 습 니 다.windows API 가 쓴 것 도 있 고 windows 프로 그래 밍 에 대해 잘 모 르 니 댓 글 을 많이 남 겨 주세요.본인 에 게 조언 해 주세요.

#include <windows.h> 
#include <iostream> 
#include <cstdlib> 
#include <ctime> 
using namespace std; 
#define CellWidth 20 
#define MAP_WIDTH 12 
#define MAP_HEIGHT 18 
#define ID_TIMER 1 
class map_floor; 
class Block; 
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); 
/* Make the class name into a global variable */ 
char szClassName[ ] = "CodeBlocksWindowsApp"; 
int WINAPI WinMain (HINSTANCE hThisInstance, 
           HINSTANCE hPrevInstance, 
           LPSTR lpszArgument, 
           int nCmdShow) 
{ 
  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|CS_HREDRAW | CS_VREDRAW;         /* 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 colour as the background of the window */ 
  wincl.hbrBackground =(HBRUSH) GetStockObject(WHITE_BRUSH);//COLOR_BACKGROUND; 
 
  /* 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 */ 
      "Code::Blocks Template Windows App",    /* Title Text */ 
      WS_OVERLAPPEDWINDOW, /* default window */ 
      CW_USEDEFAULT,    /* Windows decides the position */ 
      CW_USEDEFAULT,    /* where the window ends up on the screen */ 
      CW_USEDEFAULT,         /* The programs width */ 
      CW_USEDEFAULT,         /* and height in pixels */ 
      NULL,    /* 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, nCmdShow); 
 
  /* 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; 
} 
 
enum{e_LINE,e_CORNER,e_STAIR,e_TANCK,e_TIAN}; 
const int TOTAL_BLOCK_STYLE = 5;//     4  
class Block 
{ 
  public: 
      Block(int x = 100, int y = 100); 
      Block(const Block & rh)//      ,      ,         
      { 
        this->m_style = rh.m_style; 
        this->m_direct = rh.m_direct; 
        for(int i = 0 ; i < 4 ; i ++) 
          this->m_block[i] = rh.m_block[i]; 
      } 
      Block & operator = (const Block& rh)//  = ,        
      { 
        this->m_style = rh.m_style; 
        this->m_direct = rh.m_direct; 
        for(int i = 0 ; i < 4 ; i ++) 
          this->m_block[i] = rh.m_block[i]; 
        return *this; 
      } 
      ~Block(){} 
  int   create_block(int x = 100 , int y = 100); 
  //             
  int   show_block(HDC hdc,const POINT& GameLeftTop); 
  //         ,          
  int   show_next_block(HDC hdc); 
  //  ,        ,       ,          ,         
  int   rotate(); 
  //       
  int   random_block(); 
 
  //             
  int   get_block_height(){ return m_block[1].y;} 
  int   move_down(const RECT& GameClient); 
  int   move_left(const RECT& GameClient); 
  int   move_right(const RECT& GameClient); 
  int   move_up(const RECT& GameClient); 
  int   move_to(int x , int y); 
  //            
//  int   check_block(const map_floor& map, const RECT& GameClent); 
  int   check_block(const map_floor& map, const POINT& LeftTopScrCdnt); 
  int   print_to_map(map_floor& map , const POINT& LeftTopScrCdnt); 
  private: 
  int   m_style;//       ,           
  int   m_direct;//     ,  m_style      
 POINT   m_block[4];//   1        ,            ,              
}; 
class map_floor 
{ 
  public: 
    map_floor() 
    { 
      ZeroMemory(m_block_bar,sizeof(int )*12*18); 
    } 
    ~map_floor(){} 
  void show_block_bar(HDC hdc , const POINT& LeftTopScrCdnt) 
  { 
    for(int i = 0 ; i < MAP_HEIGHT ; ++ i) 
    { 
      for(int j = 0 ; j < MAP_WIDTH ; ++ j) 
      { 
        if(m_block_bar[i][j]) 
        { 
          Rectangle(hdc,LeftTopScrCdnt.x + j*CellWidth , LeftTopScrCdnt.y + i*CellWidth, 
                 LeftTopScrCdnt.x + (j+1)*CellWidth , LeftTopScrCdnt.y + (i+1)*CellWidth); 
        } 
      } 
    } 
 
  } 
  friend class Block; 
  protected: 
 
  private: 
 
  int     m_block_bar[MAP_HEIGHT][MAP_WIDTH];//      , 18*12        
 
 
}; 
 
Block::Block(int x , int y) 
{ 
//  ZeroMemory(m_block_bar,sizeof(int )*12*18); 
  srand( (unsigned)time( NULL ) );//      ,       
//  POINT pt = {100,100}; 
  create_block(x,y); 
} 
int Block::random_block() 
{ 
  m_style = rand()%TOTAL_BLOCK_STYLE; 
//  m_style = e_CORNER; //     
//  m_style = e_LINE; //     
  if(m_style == e_STAIR || m_style == e_TANCK) 
    m_direct = rand()%4; 
  else if(m_style == e_LINE) 
    m_direct = rand()%2; 
  else if(m_style == e_CORNER) 
    m_direct = rand()%8; 
  else if(m_style == e_TIAN) 
    m_direct = 0; 
  m_direct = 1; 
 
} 
int  Block::check_block(const map_floor& map, const POINT& LeftTopScrCdnt) 
{ 
  int x , y ; //x , y            ,    (0,0) 
  for(int i = 0 ; i < 4 ; i ++) 
  { 
    x = (m_block[i].x - LeftTopScrCdnt.x)/CellWidth; 
    y = (m_block[i].y - LeftTopScrCdnt.y)/CellWidth; 
    if(x < 0 || x >= MAP_WIDTH || y >= MAP_HEIGHT)//    y < 0     
    return 0; 
    if(y < 0) continue; 
    if(map.m_block_bar[y][x]) 
    return 0; 
  } 
  return 1; 
} 
int Block::move_down(const RECT& GameClient)//  ,         
{ 
  int i; 
//  for (i = 0 ; i < 4 ; i ++ ) 
//  { 
//   if(m_block[i].y == GameClient.bottom - CellWidth) 
//   return 0; 
//  } 
  for (i = 0; i < 4 ;i ++ ) 
  { 
    m_block[i].y += CellWidth; 
  } 
  return 1; 
} 
int Block::move_up(const RECT& GameClient) 
{ 
  move_to(m_block[1].x,m_block[1].y - CellWidth); 
  return 1; 
} 
int Block::move_left(const RECT& GameClient) 
{ 
  move_to(m_block[1].x - CellWidth,m_block[1].y); 
  return 1; 
} 
int Block::move_right(const RECT& GameClient) 
{ 
  move_to(m_block[1].x + CellWidth , m_block[1].y); 
  return 1; 
} 
int Block::create_block(int x , int y) 
{ 
  m_block[1].x = x; 
  m_block[1].y = y; 
  random_block(); 
  rotate(); 
  return 1; 
} 
int Block::move_to(int x , int y) 
{ 
  int Vx = x - m_block[1].x; 
  int Vy = y - m_block[1].y; 
  for(int i = 0 ; i < 4 ; i ++) 
  { 
    m_block[i].x += Vx; 
    m_block[i].y += Vy; 
  } 
} 
int Block::print_to_map(map_floor& map , const POINT& LeftTopScrCdnt) 
{ 
  int x , y; 
  int i , j; 
  for(i = 0 ; i < 4 ; i ++ ) 
  { 
    x = (m_block[i].x - LeftTopScrCdnt.x)/CellWidth; 
    y = (m_block[i].y - LeftTopScrCdnt.y)/CellWidth; 
    if(x<0 || x >= MAP_WIDTH || y <0 || y >= MAP_HEIGHT)//     ,    ,         
      return 0; 
    map.m_block_bar[y][x] = 1 ; 
    for(j = 0 ; j < MAP_WIDTH ; j ++) 
    { 
      if(map.m_block_bar[y][j] != 1) 
        break; 
    } 
    if(MAP_WIDTH == j) 
    { 
      for(j = 0 ; j < MAP_WIDTH ; j ++) 
      { 
        map.m_block_bar[y][j] = 5;//  5        
      } 
    } 
 
  } 
  int idx; 
  for(i = 0 ; i < MAP_WIDTH ; i ++) 
  { 
    for(idx = j = MAP_HEIGHT - 1 ; j >= 0 ; j --) 
    { 
      if(map.m_block_bar[j][i] != 5) 
      { 
        map.m_block_bar[idx--][i] = map.m_block_bar[j][i]; 
      } 
    } 
    while(idx >= 0) 
    { 
      map.m_block_bar[idx--][i] = 0; 
    } 
  } 
  return 1; 
} 
 
//              ,      【     】     ,        
//      block【4】  ,  3       block【1】  ,           
//  ,      7 ,          ,               ,   : 
// 
//e_LINE              ,        ,               ,   
//         m_direct  ,        
// 
//e_TANCK              ,     ,  m_direct 4              
//           ,                      ,           , 
//                   。 
// 
//e_STAIR                     ,           ,          
//              ,      m_direct      ,      e_STAIR_BACK e_STAIR_FRONT 
//              ,                     block【0】 block【1】      
//          ,    block【2】 block【3】,block【2】  block【1】     ,x   block【1】 
//          ,block【3】.y   block【1】    ,        
// 
//e_CORNER                    ,       ,       e_CORNER_FRONT , e_CORNER_BACK 
//          ,          ,                     ,  block【3】     
//          m_direct        
 
int Block::rotate() 
{ 
      switch (m_style) 
      { 
        case e_LINE: 
        { 
          switch(m_direct) 
          { 
            case 0://       
            { 
              for(int i = 0 ; i < 4 ; i ++) 
                { 
                  m_block[i].x = m_block[1].x; 
                  m_block[i].y = m_block[1].y + (1-i)*CellWidth; 
                } 
              m_direct = 1; 
            } 
              break; 
            case 1://       
            { 
              for(int i = 0 ; i < 4 ; i ++) 
              { 
                  m_block[i].y = m_block[1].y; 
                  m_block[i].x = m_block[1].x + (1-i)*CellWidth; 
              } 
              m_direct = 0; 
            } 
              break; 
          } 
        } 
          break; 
        //          ,               ,           , 
        //m_direct% == 0           
        case e_STAIR: 
        { 
          int flag; 
          flag = m_direct < 2 ? 1 : -1; 
          m_block[0].x = m_block[1].x + flag*CellWidth; 
          m_block[0].y = m_block[1].y; 
          m_block[2].x = m_block[1].x; 
          m_block[3].y = m_block[1].y + CellWidth; 
          if(m_direct%2 == 0) 
          { 
            m_block[2].y = m_block[1].y - CellWidth; 
            m_block[3].x = m_block[1].x + flag*CellWidth; 
            m_direct++; 
          } 
          else 
          { 
            m_block[2].y = m_block[1].y + CellWidth; 
            m_block[3].x = m_block[1].x - flag*CellWidth; 
            if(m_direct < 2) m_direct = 0; 
            else       m_direct = 2; 
          } 
        } 
          break; 
        //    ,           ,      ,       , 
        //    m_direct%4           ,   ,        
        //     ,  block【3】       ,              
        case e_CORNER: 
        { 
          switch (m_direct%4) 
          { 
            case 0: 
            { 
              m_block[0].x = m_block[1].x+CellWidth; 
              m_block[0].y = m_block[2].y = m_block[1].y; 
              m_block[2].x = m_block[1].x-CellWidth; 
              m_block[3].x = m_block[1].x-CellWidth; 
              if(m_direct>=4) m_block[3].y = m_block[1].y-CellWidth; 
              else       m_block[3].y = m_block[1].y+CellWidth; 
              m_direct ++; 
            } 
              break; 
            case 1: 
            { 
              m_block[0].x = m_block[2].x = m_block[1].x; 
              m_block[0].y = m_block[1].y+CellWidth; 
              m_block[2].y = m_block[1].y-CellWidth; 
              if(m_direct>=4)   m_block[3].x = m_block[1].x+CellWidth; 
              else       m_block[3].x = m_block[1].x-CellWidth; 
              m_block[3].y = m_block[1].y-CellWidth; 
              m_direct ++; 
            } 
              break; 
            case 2: 
            { 
              m_block[0].x = m_block[1].x-CellWidth; 
              m_block[0].y = m_block[2].y = m_block[1].y; 
              m_block[2].x = m_block[1].x+CellWidth; 
              m_block[3].x = m_block[1].x+CellWidth; 
              if (m_direct>=4)  m_block[3].y = m_block[1].y+CellWidth; 
              else       m_block[3].y = m_block[1].y-CellWidth; 
 
              m_direct ++; 
            } 
              break; 
            case 3: 
            { 
              m_block[0].x = m_block[2].x = m_block[1].x; 
              m_block[0].y = m_block[1].y-CellWidth; 
              m_block[2].y = m_block[1].y+CellWidth; 
              if(m_direct>=4)  { m_block[3].x = m_block[1].x-CellWidth; m_direct = 4;} 
              else       { m_block[3].x = m_block[1].x+CellWidth; m_direct = 0;} 
              m_block[3].y = m_block[1].y+CellWidth; 
            } 
              break; 
            default: 
              break; 
          } 
 
        } 
          break; 
        case e_TANCK://     ,           ,      
        { 
          switch (m_direct%2) 
          { 
            case 0: 
            { 
              m_block[0].x = m_block[2].x = m_block[1].x; 
              m_block[0].y = m_block[1].y - CellWidth; 
              m_block[2].y = m_block[1].y + CellWidth; 
              int flag = m_direct == 0 ? 1 : -1; 
              m_block[3].x = m_block[1].x + flag*CellWidth; 
              m_block[3].y = m_block[1].y; 
              m_direct++; 
            } 
              break; 
            case 1: 
            { 
              m_block[0].y = m_block[2].y = m_block[1].y; 
              m_block[0].x = m_block[1].x - CellWidth; 
              m_block[2].x = m_block[1].x + CellWidth; 
              m_block[3].x = m_block[1].x; 
              int flag = m_direct == 3 ? -1:1; 
              m_block[3].y = m_block[1].y + flag*CellWidth; 
              if(m_direct == 3) m_direct = 0; 
              else m_direct++; 
 
            } 
              break; 
            default: 
              break; 
          } 
 
        } 
          break; 
        case e_TIAN: 
        { 
          m_block[0].y = m_block[1].y; 
          m_block[0].x = m_block[1].x + CellWidth; 
          m_block[2].x = m_block[1].x; 
          m_block[2].y = m_block[1].y + CellWidth; 
          m_block[3].x = m_block[1].x + CellWidth; 
          m_block[3].y = m_block[1].y + CellWidth; 
        } 
          break; 
 
        default: 
          break; 
      } 
 
        return 0; 
} 
int Block::show_block(HDC hdc,const POINT& GameLeftTop) 
{ 
  for (int i = 0 ; i < 4 ; i ++ ) 
  { 
    if(m_block[i].y >= GameLeftTop.y) 
      Rectangle(hdc,m_block[i].x,m_block[i].y,m_block[i]. 
           x+CellWidth,m_block[i].y+CellWidth); 
    if(i==0)//    ,          
    {MoveToEx(hdc,m_block[i].x,m_block[i].y,NULL); 
    LineTo(hdc,m_block[i].x+CellWidth,m_block[i].y+CellWidth);} 
 
  } 
  return 1; 
} 
int Block::show_next_block(HDC hdc) 
{ 
   for (int i = 0 ; i < 4 ; i ++ ) 
  { 
 
    Rectangle(hdc,m_block[i].x,m_block[i].y,m_block[i]. 
           x+CellWidth,m_block[i].y+CellWidth); 
  } 
  return 1; 
} 
Block block , next_block , try_block; 
map_floor map;int d = 0; 
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
   HDC     hdc ; 
   PAINTSTRUCT ps ; 
   //      
   static RECT GameClient; 
   //        CellWidth = 20      12       18     
   const int  Width = 240 ,Height = 360; 
   static POINT LeftTopScrCdnt;//          
 
   switch (message) 
   { 
   case WM_CREATE: 
     SetTimer(hwnd,ID_TIMER,500,NULL); 
     return 0 ; 
   case WM_SIZE: 
     GetClientRect(hwnd,&GameClient); 
     LeftTopScrCdnt.x = (GameClient.right-GameClient.left)/2 - Width/2; 
     LeftTopScrCdnt.y = GameClient.top + 50; 
     GameClient.left  = LeftTopScrCdnt.x; 
     GameClient.top  = LeftTopScrCdnt.y; 
     GameClient.right = LeftTopScrCdnt.x + Width; 
     GameClient.bottom = LeftTopScrCdnt.y + Height; 
     //             
     next_block.create_block(GameClient.right+2*CellWidth,(GameClient.bottom+GameClient.top)/2-3*CellWidth); 
     block.move_to((GameClient.right+GameClient.left)/2,GameClient.top-CellWidth); 
 
     break; 
   case WM_TIMER: 
     block.move_down(GameClient); 
     if(!block.check_block(map,LeftTopScrCdnt))//       ,           ,            
     { 
       block.move_up(GameClient); 
       if(!block.check_block(map,LeftTopScrCdnt) || 
         block.get_block_height() <= LeftTopScrCdnt.y )//         
         { 
           KillTimer(hwnd,ID_TIMER); 
           d = 4; 
         } 
       block.print_to_map(map,LeftTopScrCdnt); 
       SendMessage(hwnd,WM_KEYDOWN,VK_ESCAPE,0); 
     } 
     InvalidateRect(hwnd,NULL,true); 
     break; 
   case WM_PAINT: 
     hdc = BeginPaint (hwnd, &ps) ; 
     MoveToEx(hdc,LeftTopScrCdnt.x,LeftTopScrCdnt.y,NULL); 
     Rectangle(hdc,GameClient.left,GameClient.top,GameClient.right,GameClient.bottom);//      
     SelectObject(hdc,GetStockObject(BLACK_BRUSH)); 
     map.show_block_bar(hdc,LeftTopScrCdnt); 
     block.show_block(hdc,LeftTopScrCdnt); 
     next_block.show_next_block(hdc); 
     EndPaint (hwnd, &ps); 
     break; 
   case WM_KEYDOWN: 
     InvalidateRect(hwnd,NULL,true); 
     switch (wParam) 
     { 
      case VK_SPACE: 
      { 
        try_block = block; 
        try_block.rotate(); 
        if(try_block.check_block(map ,LeftTopScrCdnt)) 
          block = try_block; 
        break; 
      } 
      case VK_LEFT: 
      { 
        block.move_left(GameClient); 
        if(!block.check_block(map ,LeftTopScrCdnt)) 
          block.move_right(GameClient); 
      } 
        break; 
      case VK_RIGHT: 
      { 
        block.move_right(GameClient); 
        if (!block.check_block(map ,LeftTopScrCdnt)) 
          block.move_left(GameClient); 
      } 
        break; 
      case VK_DOWN: 
      { 
//        block.move_down(GameClient); 
         SendMessage(hwnd,WM_TIMER,0,0); 
      } 
        break; 
 
      case VK_ESCAPE://   ,          
      { 
        block = next_block; 
        next_block.create_block(GameClient.right+2*CellWidth,(GameClient.bottom+GameClient.top)/2-3*CellWidth); 
        block.move_to((GameClient.right+GameClient.left)/2,GameClient.top-CellWidth); 
      } 
        break; 
      default: 
        break; 
     } 
     break; 
   case WM_DESTROY: 
     PostQuitMessage (0) ; 
     return 0 ; 
   } 
   return DefWindowProc (hwnd, message, wParam, lParam) ; 
} 
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기