| 注册
请输入搜索内容

热门搜索

Java Linux MySQL PHP JavaScript Hibernate jQuery Nginx
md3c
10年前发布

C++ 俄罗斯方块实现代码

#include <windows.h>  #include <stdio.h>  #include <time.h>     #define CELL 20  #define ROWS 25  #define COLS 15  //升级所需分数值  #define SCORE_LEVEL_INC 80  #define ID_TIMER 1     /////////////////全局变量/////////////////////////////  HWND hwnd;                  //保存窗口句柄     int score=0;                //分数  int level=0;                //级数  int interval_unit=25;       //随级数递增的时间间隔增量  int interval_base=300;      //时间间隔基量  int old_interval;           //保存当前的时间间隔,用于加速操作     int cur_left,cur_top;       //记录方块当前的位置  int width_block,height_block;   //方块的宽带和高度     bool isPause=false;             //暂停标识  UINT timer_id=0;                //保存计时器ID     static byte *block=NULL;        //方块,方块为随机大小,采用动态分配内存方式,所以这里是指针变量  byte g_panel[ROWS][COLS]={0};  ////////////////////////////////////////////////////  LRESULT CALLBACK WndProc ( HWND,UINT,WPARAM,LPARAM );  void DrawPanel ( HDC hdc );     //绘制表格  void RefreshPanel ( HDC hdc );      //刷新面板  void DoDownShift ( HDC hdc );       //下移  void DoLeftShift ( HDC hdc );       //左移  void DoRightShift ( HDC hdc );      //右移  void DoAccelerate ( HDC hdc );      //加速  void DoRedirection ( HDC hdc ); //改变方向  void ClearRow ( HDC hdc );          //消行  bool ExportBlock();     //输出方块,  //该函数会直接修改全局变量block,width_block,height_block,  //cur_left和cur_top  bool IsTouchBottom ( HDC hdc );         //判断是否到达底部     int main()  {      HINSTANCE hInstance=GetModuleHandle ( NULL );      TCHAR szAppName[]=TEXT ( "teris" );      MSG msg;      WNDCLASS wc;         wc.style=CS_HREDRAW|CS_VREDRAW;      wc.lpfnWndProc=WndProc;      wc.cbClsExtra=0;      wc.cbWndExtra=0;      wc.hInstance=hInstance;      wc.hIcon=LoadIcon ( NULL,IDI_APPLICATION );      wc.hCursor=LoadCursor ( NULL,IDC_ARROW );      wc.hbrBackground= ( HBRUSH ) GetStockObject ( WHITE_BRUSH );      wc.lpszMenuName=NULL;      wc.lpszClassName=szAppName;      if ( !RegisterClass ( &wc ) )      {          printf ( "RegisterClass occur errors!" );          return 0;      }      hwnd=CreateWindow ( szAppName,TEXT ( "Teris Demo" ),                          WS_OVERLAPPEDWINDOW,                          0,0,0,0,                          NULL,                          NULL,                          hInstance,                          NULL );      ShowWindow ( hwnd,SW_SHOW );      UpdateWindow ( hwnd );      while ( GetMessage ( &msg,NULL,0,0 ) )      {          TranslateMessage ( &msg );          DispatchMessage ( &msg );      }      return msg.wParam;  }     void DrawPanel ( HDC hdc )          //绘制游戏面板  {      int x,y;      RECT rect;         for ( y=0; y<ROWS; y++ )      {          for ( x=0; x<COLS; x++ )          {              //计算方块的边框范围              rect.top=y*CELL+1;              rect.bottom= ( y+1 ) *CELL-1;              rect.left=x*CELL+1;              rect.right= ( x+1 ) *CELL-1;              FrameRect ( hdc,&rect, ( HBRUSH ) GetStockObject ( BLACK_BRUSH ) );          }      }  }     void DoDownShift ( HDC hdc )        //下移  {      if ( NULL==block ) return;         //判断是否到达底部      if ( IsTouchBottom ( hdc ) )    //到底部      {          //消行处理          ClearRow ( hdc );          ExportBlock();      //输出下一个方块      }         cur_top++;      RefreshPanel ( hdc );  }     void DoLeftShift ( HDC hdc )        //左移  {      int x,y;      if ( NULL==block ) return;         if ( 0==cur_left ) return;      if ( cur_top<0 ) return; //方块没有完整显示前,不能左移      for ( y=0; y<height_block; y++ )      {          for ( x=0; x<width_block; x++ )          //从左边开始扫描,获取该行最左边的实心方格块          {              if ( * ( block+y*width_block+x ) )              {                  //判断当前方格在面板上面左边一个方格是否为实心,是就代表不能再左移                  if ( g_panel[cur_top+y][cur_left+x-1] ) return;                     break;      //只判断最左边的一个实心方格,之后直接扫描下一行              }          }      }      cur_left--;      RefreshPanel ( hdc );  }     void DoRightShift ( HDC hdc )       //右移  {      int x,y;      if ( NULL==block ) return;         if ( COLS-width_block==cur_left ) return;      if ( cur_top<0 ) return;     //方块完整显示前不能右移      for ( y=0; y<height_block; y++ )      {          for ( x=width_block-1; x>=0; x-- )   //从右边开始扫描,获取该行最右边的实心方格块          {              if ( * ( block+y*width_block+x ) )              {                  //判断当前方格在面板上右边一个方格是否为实心,是就代表不能再右移                  if ( g_panel[cur_top+y][cur_left+x+1] ) return;                     break;      //只判断最右边的一个实心方格              }          }      }      cur_left++;      RefreshPanel ( hdc );  }     void DoRedirection ( HDC hdc )      //改变方向  {      int i,j;      byte * temp=NULL;      if ( NULL==block ) return;      if ( cur_top<0 ) return;     //方块完整显示前不能转向         temp= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );      for ( i=0; i<width_block; i++ )      {          for ( j=0; j<height_block; j++ )          {              //temp[i][j]=block[height_block-j-1][i];              * ( temp+i*height_block+j ) =* ( block+ ( height_block-j-1 ) *width_block+i );          }      }         //给方块重新定位      int incHeight=width_block-height_block;      int incWidth=height_block-width_block;      int temp_cur_top=cur_top-incHeight/2;      int temp_cur_left=cur_left-incWidth/2;         //system("cls");      //printf("temp_top=%d, temp_left=%d",temp_cur_top,temp_cur_left);         //判断当前空间是否足够让方块改变方向      int max_len=max ( width_block,height_block );      //防止下标访问越界      if ( temp_cur_top+max_len-1>=ROWS||temp_cur_left<0||temp_cur_left+max_len-1>=COLS )      {          free ( temp );      //退出前必须先释放内存          return;      }      for ( i=0; i<max_len; i++ )      {          for ( j=0; j<max_len; j++ )          {              //转向所需的空间内有已被占用的实心方格存在,即转向失败              if ( g_panel[temp_cur_top+i][temp_cur_left+j] )              {                  free ( temp );      //退出前必须先释放内存                  return;              }          }      }         //把临时变量的值赋给block,只能赋值,而不能赋指针值      for ( i=0; i<height_block; i++ )      {          for ( j=0; j<width_block; j++ )          {              //block[i][j]=temp[i][j];              * ( block+i*width_block+j ) =* ( temp+i*width_block+j );          }      }         //全局变量重新被赋值      cur_top=temp_cur_top;      cur_left=temp_cur_left;      //交换      i=width_block;      width_block=height_block;      height_block=i;         free ( temp );      //释放为临时变量分配的内存      RefreshPanel ( hdc );  }     void DoAccelerate ( HDC hdc )       //加速  {      if ( NULL==block ) return;         if ( IsTouchBottom ( hdc ) )      {          //消行处理          ClearRow ( hdc );          ExportBlock();      }      cur_top++;      RefreshPanel ( hdc );  }     bool IsTouchBottom ( HDC hdc )  {      int x,y;      int i,j;         if ( NULL==block ) return false;      if ( ROWS==cur_top+height_block )      {          //固定方块          for ( i=0; i<height_block; i++ )          {              for ( j=0; j<width_block; j++ )              {                  if ( * ( block+i*width_block+j ) ) g_panel[cur_top+i][cur_left+j]=1;              }          }          return true;      }      for ( y=height_block-1; y>=0; y-- )          //从底行开始扫描      {          //判断第一个实心方块在面板上邻接的下方方格是否为实心,是就代表已经到达底部          for ( x=0; x<width_block; x++ )          {              if ( * ( block+y*width_block+x ) )              {                  if ( cur_top+y+1<0 ) return false;                  if ( g_panel[cur_top+y+1][cur_left+x] )                  {                      //判断是否gameover                      if ( cur_top<=0 )                      {                          if ( timer_id )                          {                              KillTimer ( hwnd,ID_TIMER );                              timer_id=0;                          }                          MessageBox ( hwnd,TEXT ( "游戏结束" ),TEXT ( "MSG" ),MB_OK|MB_ICONEXCLAMATION );                          SendMessage ( hwnd,WM_CLOSE,0,0 );                      }                      //                      //固定方块                      for ( i=0; i<height_block; i++ )                      {                          for ( j=0; j<width_block; j++ )                          {                              if ( * ( block+i*width_block+j ) ) g_panel[cur_top+i][cur_left+j]=1;                          }                      }                      return true;                  }              }          }      }      return false;  }     void ClearRow ( HDC hdc )               //消行  {      int i,j,k;      int count=0;        //消行次数      bool isFilled;      //消行处理      for ( i=ROWS-1; i>=0; i-- )      {          isFilled=true;          for ( j=0; j<COLS; j++ )          {              if ( !g_panel[i][j] )              {                  isFilled=false;                  break;              }          }          if ( isFilled )          {              for ( j=0; j<COLS; j++ )              {                  g_panel[i][j]=0;              }              //所有方块往下移              for ( k=i-1; k>=0; k-- )              {                  for ( j=0; j<COLS; j++ )                  {                      g_panel[k+1][j]=g_panel[k][j];                  }              }              i=i+1;              count++;          }      }         //最高级别为9级,所以分数极限为(9+1)*SCORE_LEVEL_INC-1      if ( score>=10*SCORE_LEVEL_INC-1 ) return;         //加分规则:消除行数,1行加10分,2行加15分,3行加20分,4行加30分      switch ( count )      {      case 1:          score+=10;          break;      case 2:          score+=15;          break;      case 3:          score+=20;          break;      case 4:          score+=30;          break;      }         int temp_level=score/SCORE_LEVEL_INC;      if ( temp_level>level )      {          level=temp_level;          //撤销当前计时器,然后重设          if ( timer_id ) KillTimer ( hwnd,ID_TIMER );          timer_id=SetTimer ( hwnd,ID_TIMER,interval_base-level*interval_unit,NULL );      }         system ( "cls" );      printf ( "score: %d, level: %d ",score,level );  }     void RefreshPanel ( HDC hdc )           //刷新面板  {      int x,y;      RECT rect;      HBRUSH h_bSolid= ( HBRUSH ) GetStockObject ( GRAY_BRUSH ),                       h_bEmpty= ( HBRUSH ) GetStockObject ( WHITE_BRUSH );      if ( NULL==block ) return;         //先刷屏      for ( y=0; y<ROWS; y++ )      {          for ( x=0; x<COLS; x++ )          {              //为避免刷掉方块的边框,rect范围必须比边框范围小1              rect.top=y*CELL+2;              rect.bottom= ( y+1 ) *CELL-2;              rect.left=x*CELL+2;              rect.right= ( x+1 ) *CELL-2;              if ( g_panel[y][x] )                  FillRect ( hdc,&rect,h_bSolid );              else                  FillRect ( hdc,&rect,h_bEmpty );          }      }      //再定位方块      for ( y=0; y<height_block; y++ )      {          for ( x=0; x<width_block; x++ )          {              if ( * ( block+y*width_block+x ) )          //实心              {                  rect.top= ( y+cur_top ) *CELL+2;                  rect.bottom= ( y+cur_top+1 ) *CELL-2;                  rect.left= ( x+cur_left ) *CELL+2;                  rect.right= ( x+cur_left+1 ) *CELL-2;                  FillRect ( hdc,&rect,h_bSolid );              }          }      }  }     bool ExportBlock()          //输出方块  {      int sel;      if ( block )      {          free ( block );     //释放之前分配的内存          block=NULL;      }         sel=rand() %7;      switch ( sel )      {      case 0:     //水平条          width_block=4;          height_block=1;          block= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );          * ( block+0 ) =1;       //可以理解为*(block+0*width_block+0)=1,即第一行的第一个方格,下面同理          * ( block+1 ) =1;       //*(block+0*width_block+1)=1          * ( block+2 ) =1;       //*(block+0*width_block+2)=1          * ( block+3 ) =1;       //*(block+0*width_block+3)=1             cur_top=0-height_block;          cur_left= ( COLS-width_block ) /2;          break;      case 1:     //三角          width_block=3;          height_block=2;          block= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );          * ( block+0 ) =0;       //可以理解为*(block+0*width_block+0)=0,即第一行的第一个方格,下面同理          * ( block+1 ) =1;       //*(block+0*width_block+1)=1          * ( block+2 ) =0;       //*(block+0*width_block+2)=0          * ( block+3 ) =1;       //*(block+1*width_block+0)=1,第二行开始          * ( block+4 ) =1;       //*(block+1*width_block+1)=1          * ( block+5 ) =1;       //*(block+1*width_block+2)=1             cur_top=0-height_block;          cur_left= ( COLS-width_block ) /2;          break;      case 2:     //左横折          width_block=3;          height_block=2;          block= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );          * ( block+0 ) =1;       //可以理解为*(block+0*width_block+0)=1,下面同理          * ( block+1 ) =0;       //*(block+0*width_block+1)=0          * ( block+2 ) =0;       //*(block+0*width_block+2)=0          * ( block+3 ) =1;       //*(block+1*width_block+0)=1          * ( block+4 ) =1;       //*(block+1*width_block+1)=1          * ( block+5 ) =1;       //*(block+1*width_block+2)=1             cur_top=0-height_block;          cur_left= ( COLS-width_block ) /2;          break;      case 3:     //右横折          width_block=3;          height_block=2;          block= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );          * ( block+0 ) =0;       //可以理解为*(block+0*width_block+0)=0,下面同理          * ( block+1 ) =0;       //*(block+0*width_block+1)=0          * ( block+2 ) =1;       //*(block+0*width_block+2)=1          * ( block+3 ) =1;       //*(block+1*width_block+0)=1          * ( block+4 ) =1;       //*(block+1*width_block+1)=1          * ( block+5 ) =1;       //*(block+1*width_block+2)=1             cur_top=0-height_block;          cur_left= ( COLS-width_block ) /2;          break;      case 4:     //左闪电          width_block=3;          height_block=2;          block= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );          * ( block+0 ) =1;       //可以理解为*(block+0*width_block+0)=1,下面同理          * ( block+1 ) =1;       //*(block+0*width_block+1)=1          * ( block+2 ) =0;       //*(block+0*width_block+2)=0          * ( block+3 ) =0;       //*(block+1*width_block+0)=0          * ( block+4 ) =1;       //*(block+1*width_block+1)=1          * ( block+5 ) =1;       //*(block+1*width_block+2)=1             cur_top=0-height_block;          cur_left= ( COLS-width_block ) /2;          break;      case 5:     //右闪电          width_block=3;          height_block=2;          block= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );          * ( block+0 ) =0;       //可以理解为*(block+0*width_block+0)=0,下面同理          * ( block+1 ) =1;       //*(block+0*width_block+1)=1          * ( block+2 ) =1;       //*(block+0*width_block+2)=1          * ( block+3 ) =1;       //*(block+1*width_block+0)=1          * ( block+4 ) =1;       //*(block+1*width_block+1)=1          * ( block+5 ) =0;       //*(block+1*width_block+2)=0             cur_top=0-height_block;          cur_left= ( COLS-width_block ) /2;          break;      case 6:     //石头          width_block=2;          height_block=2;          block= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );          * ( block+0 ) =1;       //可以理解为*(block+0*width_block+0)=1,下面同理          * ( block+1 ) =1;       //*(block+0*width_block+1)=1          * ( block+2 ) =1;       //*(block+1*width_block+0)=1          * ( block+3 ) =1;       //*(block+1*width_block+1)=1             cur_top=0-height_block;          cur_left= ( COLS-width_block ) /2;          break;      }      return block!=NULL;  }     LRESULT CALLBACK WndProc ( HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam )  {      HDC hdc;      PAINTSTRUCT ps;      //TCHAR szBuffer[1024];         switch ( message )      {      case WM_CREATE:          MoveWindow ( hwnd,400,10,CELL*COLS+8,CELL*ROWS+32,FALSE );      //补齐宽度和高度          srand ( time ( NULL ) );          ExportBlock();             timer_id=SetTimer ( hwnd,ID_TIMER,interval_base-level*interval_unit,NULL );          return 0;      case WM_TIMER:          hdc=GetDC ( hwnd );          DoDownShift ( hdc );          ReleaseDC ( hwnd,hdc );          return 0;      case WM_KEYDOWN:          hdc=GetDC ( hwnd );          switch ( wParam )          {          case VK_LEFT:                           //左移              if ( !isPause ) DoLeftShift ( hdc );              break;          case VK_RIGHT:                          //右移              if ( !isPause ) DoRightShift ( hdc );              break;          case VK_UP:                             //转向              if ( !isPause ) DoRedirection ( hdc );              break;          case VK_DOWN:                           //加速              if ( !isPause ) DoAccelerate ( hdc );              break;          case VK_SPACE:      //暂停              isPause=!isPause;              if ( isPause )              {                  if ( timer_id ) KillTimer ( hwnd,ID_TIMER );                  timer_id=0;              }              else              {                  timer_id=SetTimer ( hwnd,ID_TIMER,interval_base-level*interval_unit,FALSE );              }              break;          }          ReleaseDC ( hwnd,hdc );          return 0;      case WM_PAINT:          hdc=BeginPaint ( hwnd,&ps );          DrawPanel ( hdc );          //绘制面板          RefreshPanel ( hdc );       //刷新          EndPaint ( hwnd,&ps );          return 0;      case WM_DESTROY:          if ( block ) free ( block );          if ( timer_id ) KillTimer ( hwnd,ID_TIMER );          PostQuitMessage ( 0 );          return 0;      }      return DefWindowProc ( hwnd,message,wParam,lParam );  }