[Java] 俄罗斯方块 →→→→→进入此内容的聊天室

来自 , 2020-01-08, 写在 Java, 查看 153 次.
URL http://www.code666.cn/view/a60937eb
  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <time.h>
  4.  
  5. #define CELL 20
  6. #define ROWS 25
  7. #define COLS 15
  8. //升级所需分数值
  9. #define SCORE_LEVEL_INC 80
  10. #define ID_TIMER 1
  11.  
  12. /////////////////全局变量/////////////////////////////
  13. HWND hwnd;                  //保存窗口句柄
  14.  
  15. int score=0;                //分数
  16. int level=0;                //级数
  17. int interval_unit=25;       //随级数递增的时间间隔增量
  18. int interval_base=300;      //时间间隔基量
  19. int old_interval;           //保存当前的时间间隔,用于加速操作
  20.  
  21. int cur_left,cur_top;       //记录方块当前的位置
  22. int width_block,height_block;   //方块的宽带和高度
  23.  
  24. bool isPause=false;             //暂停标识
  25. UINT timer_id=0;                //保存计时器ID
  26.  
  27. static byte *block=NULL;        //方块,方块为随机大小,采用动态分配内存方式,所以这里是指针变量
  28. byte g_panel[ROWS][COLS]={0};
  29. ////////////////////////////////////////////////////
  30. LRESULT CALLBACK WndProc ( HWND,UINT,WPARAM,LPARAM );
  31. void DrawPanel ( HDC hdc );     //绘制表格
  32. void RefreshPanel ( HDC hdc );      //刷新面板
  33. void DoDownShift ( HDC hdc );       //下移
  34. void DoLeftShift ( HDC hdc );       //左移
  35. void DoRightShift ( HDC hdc );      //右移
  36. void DoAccelerate ( HDC hdc );      //加速
  37. void DoRedirection ( HDC hdc ); //改变方向
  38. void ClearRow ( HDC hdc );          //消行
  39. bool ExportBlock();     //输出方块,
  40. //该函数会直接修改全局变量block,width_block,height_block,
  41. //cur_left和cur_top
  42. bool IsTouchBottom ( HDC hdc );         //判断是否到达底部
  43.  
  44. int main()
  45. {
  46.     HINSTANCE hInstance=GetModuleHandle ( NULL );
  47.     TCHAR szAppName[]=TEXT ( "teris" );
  48.     MSG msg;
  49.     WNDCLASS wc;
  50.  
  51.     wc.style=CS_HREDRAW|CS_VREDRAW;
  52.     wc.lpfnWndProc=WndProc;
  53.     wc.cbClsExtra=0;
  54.     wc.cbWndExtra=0;
  55.     wc.hInstance=hInstance;
  56.     wc.hIcon=LoadIcon ( NULL,IDI_APPLICATION );
  57.     wc.hCursor=LoadCursor ( NULL,IDC_ARROW );
  58.     wc.hbrBackground= ( HBRUSH ) GetStockObject ( WHITE_BRUSH );
  59.     wc.lpszMenuName=NULL;
  60.     wc.lpszClassName=szAppName;
  61.     if ( !RegisterClass ( &wc ) )
  62.     {
  63.         printf ( "RegisterClass occur errors!" );
  64.         return 0;
  65.     }
  66.     hwnd=CreateWindow ( szAppName,TEXT ( "Teris Demo" ),
  67.                         WS_OVERLAPPEDWINDOW,
  68.                         0,0,0,0,
  69.                         NULL,
  70.                         NULL,
  71.                         hInstance,
  72.                         NULL );
  73.     ShowWindow ( hwnd,SW_SHOW );
  74.     UpdateWindow ( hwnd );
  75.     while ( GetMessage ( &msg,NULL,0,0 ) )
  76.     {
  77.         TranslateMessage ( &msg );
  78.         DispatchMessage ( &msg );
  79.     }
  80.     return msg.wParam;
  81. }
  82.  
  83. void DrawPanel ( HDC hdc )          //绘制游戏面板
  84. {
  85.     int x,y;
  86.     RECT rect;
  87.  
  88.     for ( y=0; y<ROWS; y++ )
  89.     {
  90.         for ( x=0; x<COLS; x++ )
  91.         {
  92.             //计算方块的边框范围
  93.             rect.top=y*CELL+1;
  94.             rect.bottom= ( y+1 ) *CELL-1;
  95.             rect.left=x*CELL+1;
  96.             rect.right= ( x+1 ) *CELL-1;
  97.             FrameRect ( hdc,&rect, ( HBRUSH ) GetStockObject ( BLACK_BRUSH ) );
  98.         }
  99.     }
  100. }
  101.  
  102. void DoDownShift ( HDC hdc )        //下移
  103. {
  104.     if ( NULL==block ) return;
  105.  
  106.     //判断是否到达底部
  107.     if ( IsTouchBottom ( hdc ) )    //到底部
  108.     {
  109.         //消行处理
  110.         ClearRow ( hdc );
  111.         ExportBlock();      //输出下一个方块
  112.     }
  113.  
  114.     cur_top++;
  115.     RefreshPanel ( hdc );
  116. }
  117.  
  118. void DoLeftShift ( HDC hdc )        //左移
  119. {
  120.     int x,y;
  121.     if ( NULL==block ) return;
  122.  
  123.     if ( 0==cur_left ) return;
  124.     if ( cur_top<0 ) return; //方块没有完整显示前,不能左移
  125.     for ( y=0; y<height_block; y++ )
  126.     {
  127.         for ( x=0; x<width_block; x++ )          //从左边开始扫描,获取该行最左边的实心方格块
  128.         {
  129.             if ( * ( block+y*width_block+x ) )
  130.             {
  131.                 //判断当前方格在面板上面左边一个方格是否为实心,是就代表不能再左移
  132.                 if ( g_panel[cur_top+y][cur_left+x-1] ) return;
  133.  
  134.                 break;      //只判断最左边的一个实心方格,之后直接扫描下一行
  135.             }
  136.         }
  137.     }
  138.     cur_left--;
  139.     RefreshPanel ( hdc );
  140. }
  141.  
  142. void DoRightShift ( HDC hdc )       //右移
  143. {
  144.     int x,y;
  145.     if ( NULL==block ) return;
  146.  
  147.     if ( COLS-width_block==cur_left ) return;
  148.     if ( cur_top<0 ) return;     //方块完整显示前不能右移
  149.     for ( y=0; y<height_block; y++ )
  150.     {
  151.         for ( x=width_block-1; x>=0; x-- )   //从右边开始扫描,获取该行最右边的实心方格块
  152.         {
  153.             if ( * ( block+y*width_block+x ) )
  154.             {
  155.                 //判断当前方格在面板上右边一个方格是否为实心,是就代表不能再右移
  156.                 if ( g_panel[cur_top+y][cur_left+x+1] ) return;
  157.  
  158.                 break;      //只判断最右边的一个实心方格
  159.             }
  160.         }
  161.     }
  162.     cur_left++;
  163.     RefreshPanel ( hdc );
  164. }
  165.  
  166. void DoRedirection ( HDC hdc )      //改变方向
  167. {
  168.     int i,j;
  169.     byte * temp=NULL;
  170.     if ( NULL==block ) return;
  171.     if ( cur_top<0 ) return;     //方块完整显示前不能转向
  172.  
  173.     temp= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );
  174.     for ( i=0; i<width_block; i++ )
  175.     {
  176.         for ( j=0; j<height_block; j++ )
  177.         {
  178.             //temp[i][j]=block[height_block-j-1][i];
  179.             * ( temp+i*height_block+j ) =* ( block+ ( height_block-j-1 ) *width_block+i );
  180.         }
  181.     }
  182.  
  183.     //给方块重新定位
  184.     int incHeight=width_block-height_block;
  185.     int incWidth=height_block-width_block;
  186.     int temp_cur_top=cur_top-incHeight/2;
  187.     int temp_cur_left=cur_left-incWidth/2;
  188.  
  189.     //system("cls");
  190.     //printf("temp_top=%d, temp_left=%d",temp_cur_top,temp_cur_left);
  191.  
  192.     //判断当前空间是否足够让方块改变方向
  193.     int max_len=max ( width_block,height_block );
  194.     //防止下标访问越界
  195.     if ( temp_cur_top+max_len-1>=ROWS||temp_cur_left<0||temp_cur_left+max_len-1>=COLS )
  196.     {
  197.         free ( temp );      //退出前必须先释放内存
  198.         return;
  199.     }
  200.     for ( i=0; i<max_len; i++ )
  201.     {
  202.         for ( j=0; j<max_len; j++ )
  203.         {
  204.             //转向所需的空间内有已被占用的实心方格存在,即转向失败
  205.             if ( g_panel[temp_cur_top+i][temp_cur_left+j] )
  206.             {
  207.                 free ( temp );      //退出前必须先释放内存
  208.                 return;
  209.             }
  210.         }
  211.     }
  212.  
  213.     //把临时变量的值赋给block,只能赋值,而不能赋指针值
  214.     for ( i=0; i<height_block; i++ )
  215.     {
  216.         for ( j=0; j<width_block; j++ )
  217.         {
  218.             //block[i][j]=temp[i][j];
  219.             * ( block+i*width_block+j ) =* ( temp+i*width_block+j );
  220.         }
  221.     }
  222.  
  223.     //全局变量重新被赋值
  224.     cur_top=temp_cur_top;
  225.     cur_left=temp_cur_left;
  226.     //交换
  227.     i=width_block;
  228.     width_block=height_block;
  229.     height_block=i;
  230.  
  231.     free ( temp );      //释放为临时变量分配的内存
  232.     RefreshPanel ( hdc );
  233. }
  234.  
  235. void DoAccelerate ( HDC hdc )       //加速
  236. {
  237.     if ( NULL==block ) return;
  238.  
  239.     if ( IsTouchBottom ( hdc ) )
  240.     {
  241.         //消行处理
  242.         ClearRow ( hdc );
  243.         ExportBlock();
  244.     }
  245.     cur_top++;
  246.     RefreshPanel ( hdc );
  247. }
  248.  
  249. bool IsTouchBottom ( HDC hdc )
  250. {
  251.     int x,y;
  252.     int i,j;
  253.  
  254.     if ( NULL==block ) return false;
  255.     if ( ROWS==cur_top+height_block )
  256.     {
  257.         //固定方块
  258.         for ( i=0; i<height_block; i++ )
  259.         {
  260.             for ( j=0; j<width_block; j++ )
  261.             {
  262.                 if ( * ( block+i*width_block+j ) ) g_panel[cur_top+i][cur_left+j]=1;
  263.             }
  264.         }
  265.         return true;
  266.     }
  267.     for ( y=height_block-1; y>=0; y-- )          //从底行开始扫描
  268.     {
  269.         //判断第一个实心方块在面板上邻接的下方方格是否为实心,是就代表已经到达底部
  270.         for ( x=0; x<width_block; x++ )
  271.         {
  272.             if ( * ( block+y*width_block+x ) )
  273.             {
  274.                 if ( cur_top+y+1<0 ) return false;
  275.                 if ( g_panel[cur_top+y+1][cur_left+x] )
  276.                 {
  277.                     //判断是否gameover
  278.                     if ( cur_top<=0 )
  279.                     {
  280.                         if ( timer_id )
  281.                         {
  282.                             KillTimer ( hwnd,ID_TIMER );
  283.                             timer_id=0;
  284.                         }
  285.                         MessageBox ( hwnd,TEXT ( "游戏结束" ),TEXT ( "MSG" ),MB_OK|MB_ICONEXCLAMATION );
  286.                         SendMessage ( hwnd,WM_CLOSE,0,0 );
  287.                     }
  288.                     //
  289.                     //固定方块
  290.                     for ( i=0; i<height_block; i++ )
  291.                     {
  292.                         for ( j=0; j<width_block; j++ )
  293.                         {
  294.                             if ( * ( block+i*width_block+j ) ) g_panel[cur_top+i][cur_left+j]=1;
  295.                         }
  296.                     }
  297.                     return true;
  298.                 }
  299.             }
  300.         }
  301.     }
  302.     return false;
  303. }
  304.  
  305. void ClearRow ( HDC hdc )               //消行
  306. {
  307.     int i,j,k;
  308.     int count=0;        //消行次数
  309.     bool isFilled;
  310.     //消行处理
  311.     for ( i=ROWS-1; i>=0; i-- )
  312.     {
  313.         isFilled=true;
  314.         for ( j=0; j<COLS; j++ )
  315.         {
  316.             if ( !g_panel[i][j] )
  317.             {
  318.                 isFilled=false;
  319.                 break;
  320.             }
  321.         }
  322.         if ( isFilled )
  323.         {
  324.             for ( j=0; j<COLS; j++ )
  325.             {
  326.                 g_panel[i][j]=0;
  327.             }
  328.             //所有方块往下移
  329.             for ( k=i-1; k>=0; k-- )
  330.             {
  331.                 for ( j=0; j<COLS; j++ )
  332.                 {
  333.                     g_panel[k+1][j]=g_panel[k][j];
  334.                 }
  335.             }
  336.             i=i+1;
  337.             count++;
  338.         }
  339.     }
  340.  
  341.     //最高级别为9级,所以分数极限为(9+1)*SCORE_LEVEL_INC-1
  342.     if ( score>=10*SCORE_LEVEL_INC-1 ) return;
  343.  
  344.     //加分规则:消除行数,1行加10分,2行加15分,3行加20分,4行加30分
  345.     switch ( count )
  346.     {
  347.     case 1:
  348.         score+=10;
  349.         break;
  350.     case 2:
  351.         score+=15;
  352.         break;
  353.     case 3:
  354.         score+=20;
  355.         break;
  356.     case 4:
  357.         score+=30;
  358.         break;
  359.     }
  360.  
  361.     int temp_level=score/SCORE_LEVEL_INC;
  362.     if ( temp_level>level )
  363.     {
  364.         level=temp_level;
  365.         //撤销当前计时器,然后重设
  366.         if ( timer_id ) KillTimer ( hwnd,ID_TIMER );
  367.         timer_id=SetTimer ( hwnd,ID_TIMER,interval_base-level*interval_unit,NULL );
  368.     }
  369.  
  370.     system ( "cls" );
  371.     printf ( "score: %d, level: %d ",score,level );
  372. }
  373.  
  374. void RefreshPanel ( HDC hdc )           //刷新面板
  375. {
  376.     int x,y;
  377.     RECT rect;
  378.     HBRUSH h_bSolid= ( HBRUSH ) GetStockObject ( GRAY_BRUSH ),
  379.                      h_bEmpty= ( HBRUSH ) GetStockObject ( WHITE_BRUSH );
  380.     if ( NULL==block ) return;
  381.  
  382.     //先刷屏
  383.     for ( y=0; y<ROWS; y++ )
  384.     {
  385.         for ( x=0; x<COLS; x++ )
  386.         {
  387.             //为避免刷掉方块的边框,rect范围必须比边框范围小1
  388.             rect.top=y*CELL+2;
  389.             rect.bottom= ( y+1 ) *CELL-2;
  390.             rect.left=x*CELL+2;
  391.             rect.right= ( x+1 ) *CELL-2;
  392.             if ( g_panel[y][x] )
  393.                 FillRect ( hdc,&rect,h_bSolid );
  394.             else
  395.                 FillRect ( hdc,&rect,h_bEmpty );
  396.         }
  397.     }
  398.     //再定位方块
  399.     for ( y=0; y<height_block; y++ )
  400.     {
  401.         for ( x=0; x<width_block; x++ )
  402.         {
  403.             if ( * ( block+y*width_block+x ) )          //实心
  404.             {
  405.                 rect.top= ( y+cur_top ) *CELL+2;
  406.                 rect.bottom= ( y+cur_top+1 ) *CELL-2;
  407.                 rect.left= ( x+cur_left ) *CELL+2;
  408.                 rect.right= ( x+cur_left+1 ) *CELL-2;
  409.                 FillRect ( hdc,&rect,h_bSolid );
  410.             }
  411.         }
  412.     }
  413. }
  414.  
  415. bool ExportBlock()          //输出方块
  416. {
  417.     int sel;
  418.     if ( block )
  419.     {
  420.         free ( block );     //释放之前分配的内存
  421.         block=NULL;
  422.     }
  423.  
  424.     sel=rand() %7;
  425.     switch ( sel )
  426.     {
  427.     case 0:     //水平条
  428.         width_block=4;
  429.         height_block=1;
  430.         block= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );
  431.         * ( block+0 ) =1;       //可以理解为*(block+0*width_block+0)=1,即第一行的第一个方格,下面同理
  432.         * ( block+1 ) =1;       //*(block+0*width_block+1)=1
  433.         * ( block+2 ) =1;       //*(block+0*width_block+2)=1
  434.         * ( block+3 ) =1;       //*(block+0*width_block+3)=1
  435.  
  436.         cur_top=0-height_block;
  437.         cur_left= ( COLS-width_block ) /2;
  438.         break;
  439.     case 1:     //三角
  440.         width_block=3;
  441.         height_block=2;
  442.         block= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );
  443.         * ( block+0 ) =0;       //可以理解为*(block+0*width_block+0)=0,即第一行的第一个方格,下面同理
  444.         * ( block+1 ) =1;       //*(block+0*width_block+1)=1
  445.         * ( block+2 ) =0;       //*(block+0*width_block+2)=0
  446.         * ( block+3 ) =1;       //*(block+1*width_block+0)=1,第二行开始
  447.         * ( block+4 ) =1;       //*(block+1*width_block+1)=1
  448.         * ( block+5 ) =1;       //*(block+1*width_block+2)=1
  449.  
  450.         cur_top=0-height_block;
  451.         cur_left= ( COLS-width_block ) /2;
  452.         break;
  453.     case 2:     //左横折
  454.         width_block=3;
  455.         height_block=2;
  456.         block= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );
  457.         * ( block+0 ) =1;       //可以理解为*(block+0*width_block+0)=1,下面同理
  458.         * ( block+1 ) =0;       //*(block+0*width_block+1)=0
  459.         * ( block+2 ) =0;       //*(block+0*width_block+2)=0
  460.         * ( block+3 ) =1;       //*(block+1*width_block+0)=1
  461.         * ( block+4 ) =1;       //*(block+1*width_block+1)=1
  462.         * ( block+5 ) =1;       //*(block+1*width_block+2)=1
  463.  
  464.         cur_top=0-height_block;
  465.         cur_left= ( COLS-width_block ) /2;
  466.         break;
  467.     case 3:     //右横折
  468.         width_block=3;
  469.         height_block=2;
  470.         block= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );
  471.         * ( block+0 ) =0;       //可以理解为*(block+0*width_block+0)=0,下面同理
  472.         * ( block+1 ) =0;       //*(block+0*width_block+1)=0
  473.         * ( block+2 ) =1;       //*(block+0*width_block+2)=1
  474.         * ( block+3 ) =1;       //*(block+1*width_block+0)=1
  475.         * ( block+4 ) =1;       //*(block+1*width_block+1)=1
  476.         * ( block+5 ) =1;       //*(block+1*width_block+2)=1
  477.  
  478.         cur_top=0-height_block;
  479.         cur_left= ( COLS-width_block ) /2;
  480.         break;
  481.     case 4:     //左闪电
  482.         width_block=3;
  483.         height_block=2;
  484.         block= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );
  485.         * ( block+0 ) =1;       //可以理解为*(block+0*width_block+0)=1,下面同理
  486.         * ( block+1 ) =1;       //*(block+0*width_block+1)=1
  487.         * ( block+2 ) =0;       //*(block+0*width_block+2)=0
  488.         * ( block+3 ) =0;       //*(block+1*width_block+0)=0
  489.         * ( block+4 ) =1;       //*(block+1*width_block+1)=1
  490.         * ( block+5 ) =1;       //*(block+1*width_block+2)=1
  491.  
  492.         cur_top=0-height_block;
  493.         cur_left= ( COLS-width_block ) /2;
  494.         break;
  495.     case 5:     //右闪电
  496.         width_block=3;
  497.         height_block=2;
  498.         block= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );
  499.         * ( block+0 ) =0;       //可以理解为*(block+0*width_block+0)=0,下面同理
  500.         * ( block+1 ) =1;       //*(block+0*width_block+1)=1
  501.         * ( block+2 ) =1;       //*(block+0*width_block+2)=1
  502.         * ( block+3 ) =1;       //*(block+1*width_block+0)=1
  503.         * ( block+4 ) =1;       //*(block+1*width_block+1)=1
  504.         * ( block+5 ) =0;       //*(block+1*width_block+2)=0
  505.  
  506.         cur_top=0-height_block;
  507.         cur_left= ( COLS-width_block ) /2;
  508.         break;
  509.     case 6:     //石头
  510.         width_block=2;
  511.         height_block=2;
  512.         block= ( byte * ) malloc ( sizeof ( byte ) *width_block*height_block );
  513.         * ( block+0 ) =1;       //可以理解为*(block+0*width_block+0)=1,下面同理
  514.         * ( block+1 ) =1;       //*(block+0*width_block+1)=1
  515.         * ( block+2 ) =1;       //*(block+1*width_block+0)=1
  516.         * ( block+3 ) =1;       //*(block+1*width_block+1)=1
  517.  
  518.         cur_top=0-height_block;
  519.         cur_left= ( COLS-width_block ) /2;
  520.         break;
  521.     }
  522.     return block!=NULL;
  523. }
  524.  
  525. LRESULT CALLBACK WndProc ( HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam )
  526. {
  527.     HDC hdc;
  528.     PAINTSTRUCT ps;
  529.     //TCHAR szBuffer[1024];
  530.  
  531.     switch ( message )
  532.     {
  533.     case WM_CREATE:
  534.         MoveWindow ( hwnd,400,10,CELL*COLS+8,CELL*ROWS+32,FALSE );      //补齐宽度和高度
  535.         srand ( time ( NULL ) );
  536.         ExportBlock();
  537.  
  538.         timer_id=SetTimer ( hwnd,ID_TIMER,interval_base-level*interval_unit,NULL );
  539.         return 0;
  540.     case WM_TIMER:
  541.         hdc=GetDC ( hwnd );
  542.         DoDownShift ( hdc );
  543.         ReleaseDC ( hwnd,hdc );
  544.         return 0;
  545.     case WM_KEYDOWN:
  546.         hdc=GetDC ( hwnd );
  547.         switch ( wParam )
  548.         {
  549.         case VK_LEFT:                           //左移
  550.             if ( !isPause ) DoLeftShift ( hdc );
  551.             break;
  552.         case VK_RIGHT:                          //右移
  553.             if ( !isPause ) DoRightShift ( hdc );
  554.             break;
  555.         case VK_UP:                             //转向
  556.             if ( !isPause ) DoRedirection ( hdc );
  557.             break;
  558.         case VK_DOWN:                           //加速
  559.             if ( !isPause ) DoAccelerate ( hdc );
  560.             break;
  561.         case VK_SPACE:      //暂停
  562.             isPause=!isPause;
  563.             if ( isPause )
  564.             {
  565.                 if ( timer_id ) KillTimer ( hwnd,ID_TIMER );
  566.                 timer_id=0;
  567.             }
  568.             else
  569.             {
  570.                 timer_id=SetTimer ( hwnd,ID_TIMER,interval_base-level*interval_unit,FALSE );
  571.             }
  572.             break;
  573.         }
  574.         ReleaseDC ( hwnd,hdc );
  575.         return 0;
  576.     case WM_PAINT:
  577.         hdc=BeginPaint ( hwnd,&ps );
  578.         DrawPanel ( hdc );          //绘制面板
  579.         RefreshPanel ( hdc );       //刷新
  580.         EndPaint ( hwnd,&ps );
  581.         return 0;
  582.     case WM_DESTROY:
  583.         if ( block ) free ( block );
  584.         if ( timer_id ) KillTimer ( hwnd,ID_TIMER );
  585.         PostQuitMessage ( 0 );
  586.         return 0;
  587.     }
  588.     return DefWindowProc ( hwnd,message,wParam,lParam );
  589. }
  590.  

回复 "俄罗斯方块"

这儿你可以回复上面这条便签

captcha