首页 VC 6.0 MFC 俄罗斯方块 自动求解 代码 源程序

VC 6.0 MFC 俄罗斯方块 自动求解 代码 源程序

举报
开通vip

VC 6.0 MFC 俄罗斯方块 自动求解 代码 源程序 #include #include #include #include #define tDown      1    //方块下落定时器的标识(编号) #define tPaint      2    //重绘定时器的标识(编号) #define tDownTime  500    //方块下落一行位置的时间间隔 #define tPaintTime  50    //窗口重绘的时间间隔 #define ROW        24    //地图的行数目(第23行不用) #define COL     ...

VC   6.0 MFC 俄罗斯方块 自动求解 代码 源程序
#include #include #include #include #define tDown      1    //方块下落定时器的标识(编号) #define tPaint      2    //重绘定时器的标识(编号) #define tDownTime  500    //方块下落一行位置的时间间隔 #define tPaintTime  50    //窗口重绘的时间间隔 #define ROW        24    //地图的行数目(第23行不用) #define COL        14    //地图的列数目(第0列和第13列不用) #define MAX_CLASS  7    //方块形状数目 #define LEN        20    //每个方格大小为20×20像素 #define StartY      -1 * LEN + 5    //-15,绘制俄罗斯方块地图时的边界起始位置 #define StartX      -1 * LEN + 5    //-15 int    iDeleteRows = 0;    //总共清除的行 int    iTotalNum = 0;        //总得分 char    WindowTxt[100] = "俄罗斯方块游戏 自动求解已关闭";    //窗口标题 char    s1[] = "关闭", s2[] = "启动";    //用于启动/关闭自动求解功能时显示不同的标题 bool    bAuto;    //是否自动求解的标志 bool    Pause;        //是否暂停的标志 int    Map[ROW][COL];    //俄罗斯方块的地图(被占据的方格为1,否则为0) int    CurrentBox[4][4];    //当前落下的方块 int    CurrentY, CurrentX;    //当前落下方块的当前位置(指左上角位置) int    NextBox[4][4];        //下一个将落下的方块 int    Box[MAX_CLASS][4][4] =    //7种方块形状 { { {0,0,0,0}, {1,1,1,1}, {0,0,0,0}, {0,0,0,0} }, { {0,0,0,0}, {0,1,0,0}, {1,1,1,0}, {0,0,0,0} }, { {0,0,0,0}, {1,1,0,0}, {0,1,1,0}, {0,0,0,0} }, { {0,0,0,0}, {0,1,1,0}, {1,1,0,0}, {0,0,0,0} }, { {0,1,1,0}, {0,0,1,0}, {0,0,1,0}, {0,0,0,0} }, { {0,1,1,0}, {0,1,0,0}, {0,1,0,0}, {0,0,0,0} }, { {0,0,0,0}, {0,1,1,0}, {0,1,1,0}, {0,0,0,0} } }; void InitMap( );    //初始化地图 int  NewFall( );    //新的方块落下 void BuildNextBox( );    //产生下一个随机的方块 int  Test( int y, int x, int box[4][4] );    //测试在(y,x)位置是否能放置方块box,能放置返回1,否则返回0 int  Drop( );    //定时时间到,当前方块下降一行位置 void PutBox( );    //放置当前方块 int  Move( int Right );    //(通过方向键)移动方块,参数right为1表示向右移动,为0表示向左移动 void Clear( );    //清除满足条件的行 int  Rotate( );    //测试旋转是否可行,如果可行则旋转当前方块 int  RotateTest( int Box1[4][4], int Box2[4][4] );    //旋转当前方块 int  count1( int y, int x, int box[4][4] );    //新增函数 int  BestStartX( );    //新增函数 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );    //窗口处理函数声明 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )    //入口函数 { static TCHAR szAppName[ ] = TEXT ("Russion"); HWND        hwnd; MSG          msg; WNDCLASS    wndclass; wndclass.style        = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc  = 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( WHITE_BRUSH ); wndclass.lpszMenuName  = NULL; wndclass.lpszClassName = szAppName; if( !RegisterClass( &wndclass ) ) { MessageBox( NULL, TEXT ("Program requires Windows NT!" ), szAppName, MB_ICONERROR ); return 0; } hwnd = CreateWindow( szAppName, WindowTxt, WS_OVERLAPPED | WS_SYSMENU | WS_BORDER, CW_USEDEFAULT, CW_USEDEFAULT, (COL + 4) * LEN,    //窗口宽度:(14+4)×20=360像素 ROW * LEN,        //窗口高度:24×20=480像素(包括标题栏部分) NULL, NULL, hInstance, NULL ); ShowWindow( hwnd, iCmdShow ); UpdateWindow( hwnd ); while( GetMessage( &msg, NULL, 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } return msg.wParam; } //初始化地图(将第0列和第13列、第23行设置为1(被占据),其他位置设置为0) void InitMap( ) { int y, x; for( y = 0; y < ROW; y++ ) { for( x = 0; x < COL; x++ ) { //第0列、第13列、第23行设置为1(被占据) if( x < 1 || x > COL - 2 || y > ROW - 2 ) Map[y][x] = 1; else Map[y][x] = 0; } } } //计算在(y,x)位置(左上角位置)上放置方块box后空出的方格数 int count1( int y, int x, int box[4][4] ) { if( !Test(y,x,box) )  return 100;    //不能在(y,x)位置放置box,返回∞ if( Test(y+1,x,box) )  return 100;    //如果box还能下降,也返回∞ int tmpy, tmpx; int c = 0;    //空出的方格数 for( tmpx = 0; tmpx < 4; tmpx++ )    //考虑第0~3列 { for( tmpy = 3; tmpy >= 0; tmpy-- ) { if( box[tmpy][tmpx] )  break; }tmpy++; if( tmpy>0 ) { for( ; tmpy<4; tmpy++ ) { if( tmpy+y<0 || tmpy+y>=ROW || tmpx+x<0 || tmpx+x>=COL )  continue; if(!Map[tmpy+y][tmpx+x])  c++;    //空出的方格 } } } return c; } //当启动自动求解功能时,求下一个方块的最佳下降位置 //策略1为:放置后,空出的方格数最少,为MinC1,此时能达到最高位置为MaxY1,该位置为BestX1; //策略2为:放置后,能下降的位置最高,为MaxY2,此时空出的方格数为MinC2,该位置为BestX2; //必有MaxY1<=MaxY2, MinC1>=MinC2 //取二者的折衷,策略为:优先采取策略1,但如果MinC2==MinC1或MaxY2>=MaxY1+2,则取策略2 int BestStartX( ) { int X, Y, tmpx, tmpy;    //循环变量 int BestX = 0, MaxY = 0, MinC = 100;//最终所求的最佳下降位置 int BestX1, MaxY1, MinC1;    //策略1:MinC:最佳位置处放置方块时,空出的空格最少,BestX:最佳下降位置,MaxY:能下降到的位置 int BestX2, MaxY2, MinC2;    //策略2:最佳位置为能下降的位置最高 int c;    //以上策略求最值时用到的辅助变量 int tBox1[4][4], tBox2[4][4];    //tBox2为实现旋转时用到的临时变量 int Rotates = 0, Rotates1 = 0, Rotates2 = 0;//找到最佳位置后,当前方块需要旋转的次数 int Last1, Last2;    //Last1为下一个方块未旋转时最下一个方格所在的行,Last2为旋转后最下一个方格所在的行 memcpy(tBox1, NextBox, sizeof(tBox1));  memcpy(tBox2, NextBox, sizeof(tBox1)); for( tmpy=3; tmpy>=0; tmpy-- )    //统计tBox1中最下一个方格所在的行 { for( tmpx=0; tmpx<4; tmpx++ )  if(tBox1[tmpy][tmpx])  break; if(tmpx<4)  break; } Last1 = tmpy; BestX1 = 0, MaxY1 = 0, MinC1 = 100;  BestX2 = 0, MaxY2 = 0, MinC2 = 100; //枚举从第0~COL-4列下落 for( X=0; X<=COL-4; X++ ) { for( Y=0; Y<=ROW-1; Y++ ) if( !Test( Y, X, tBox1 ) )  break; Y--; c = count1(Y,X,tBox1); if( cMaxY1 ) MinC1 = c,  BestX1 = X,  MaxY1 = Y+Last1; if( Y+Last1>MaxY2 || Y+Last1==MaxY2 && cMaxY1 ) MinC1 = c,  BestX1 = X,  MaxY1 = Y+Last2, Rotates1 = 1; if( Y+Last2>MaxY2 || Y+Last2==MaxY2 && cMaxY1 ) MinC1 = c,  BestX1 = X,  MaxY1 = Y+Last2, Rotates1 = 2; if( Y+Last2>MaxY2 || Y+Last2==MaxY2 && cMaxY1 ) MinC1 = c,  BestX1 = X,  MaxY1 = Y+Last2, Rotates1 = 3; if( Y+Last2>MaxY2 || Y+Last2==MaxY2 && c=MaxY1+2 ) MinC = MinC2,  BestX = BestX2,  MaxY = MaxY2,  Rotates = Rotates2; if( Rotates>0 ) { for( int i=0; i 0; DelY-- ) { for( DelX = 1; DelX < COL - 1; DelX++ ) Map[DelY][DelX] = Map[DelY-1][DelX]; } for( DelX = 1; DelX < COL - 1; DelX++ )    //第0行置为0 Map[0][DelX] = 0; } } } int Rotate( )    //测试旋转是否可行,如果可行则旋转当前方块 { int y, x; int TmpBox[4][4]; RotateTest( CurrentBox, TmpBox );  if( Test( CurrentY, CurrentX, TmpBox ) ) { for( y = 0; y < 4; y++ ) { for( x = 0; x < 4; x++ ) CurrentBox[y][x] = TmpBox[y][x]; } return 1; } else return 0; } /* 0000    0000    0000    //旋转规律是:Box3[y][x] = Box1[y][3-x] -> 方块绕竖直方向对称变换 0100->    0010->    0010    //Box2[x][y] = Box3[y][x] -> 沿着主对角线对称变换(相当于矩阵转置) 1110    0111    0110 0000    0000    0010    */ int RotateTest( int Box1[4][4], int Box2[4][4] )    //旋转当前方块 {    //新增返回值为:旋转后的Box2中最下一个方格所在的行 int y, x; for( y = 0; y < 4; y++ ) { for( x = 3; x >=0; x-- ) Box2[x][y] = Box1[y][3 - x]; } for( y=3; y>=0; y-- )    //统计Box2中最下一个方格所在的行 { for( x=0; x<4; x++ ) { if(Box2[y][x])  break; } if(x<4)  break; } return y; } LRESULT CALLBACK WndProc( HWND hwnd, UINT Message,    //窗口处理函数 WPARAM wParam, LPARAM lParam ) { HDC          hdc, hdcMem; int          y, x; PAINTSTRUCT  ps; HBITMAP      hBitMap; HPEN        hPen; HBRUSH      hBrush; static int  cxClient, cyClient;    //窗口客户区宽度和高度 char str[20];    //用于显示得分的变量 switch( Message ) { case WM_CREATE: SetTimer( hwnd, tDown, tDownTime, NULL );    //开启两个定时器 SetTimer( hwnd, tPaint, tPaintTime, NULL ); srand( (unsigned)time( NULL ) ); bAuto = false; Pause = false; InitMap( ); BuildNextBox( );    //先随机产生一个方块 NewFall( );    //方块落下并随机产生下一个方块 sprintf( str, " 得分:%d", iTotalNum );  strcat( WindowTxt, str ); SetWindowText(hwnd,WindowTxt); return 0; case WM_SIZE: cxClient = LOWORD( lParam );    //取得窗口客户区宽度和高度 cyClient = HIWORD( lParam ); return 0; case WM_TIMER: switch( wParam ) { case tDown:    //下降定时器        if( !Drop( ) )    //如果不能下降则放置当前方块 { PutBox( ); MessageBeep( -1 ); Clear( );    //清除 //刷新得分 sprintf( str, "%d", iTotalNum );  WindowTxt[36] = 0; strcat( WindowTxt, str );  SetWindowText(hwnd,WindowTxt); if( !NewFall( ) )    //如果新的方块不能落下,则程序结束 { KillTimer(hwnd, tDown ); KillTimer(hwnd, tPaint ); //PostMessage( hwnd, WM_CLOSE, NULL, NULL ); } } break; case tPaint:    //重绘定时器 InvalidateRect(hwnd, NULL, FALSE);    //强制重绘窗口工作区 break; } case WM_KEYDOWN: switch( wParam ) { case VK_LEFT:    //"向左"方向键 if(bAuto)  break; Move(0);  break; case VK_RIGHT:    //"向右"方向键 if(bAuto)  break; Move(1);  break; case VK_UP:        //"向上"方向键:旋转 if(bAuto)  break; Rotate( );  break; case VK_DOWN:    //"向下"方向键:当前方块下移一行位置 if(bAuto)  break; MessageBeep( -1 );  Drop( );  break; case VK_return:    //回车键:暂停 Pause = !Pause; if( Pause )    //暂停、自动求解时也可以暂停 KillTimer( hwnd, tDown ); else    //启动 { if(bAuto)  SetTimer( hwnd, tDown, tDownTime/5, NULL ); else  SetTimer( hwnd, tDown, tDownTime, NULL ); } break; case VK_SPACE: if(bAuto)  break; while( 1 )    //使用永真循环,使得当前方块一直下降到不能下降为止 { if( !Drop( ) ) { PutBox( );  Clear( ); sprintf( str, "%d", iTotalNum );  WindowTxt[36] = 0; strcat( WindowTxt, str );  SetWindowText(hwnd,WindowTxt); if( !NewFall( ) )    //如果新的方块不能落下,则程序结束 { KillTimer(hwnd, tDown ); KillTimer(hwnd, tPaint ); //PostMessage( hwnd, WM_CLOSE, NULL, NULL ); } break; } } break; case VK_F1: bAuto = !bAuto; if(bAuto)    //自动求解 { KillTimer(hwnd, tDown ); SetTimer( hwnd, tDown, tDownTime/5, NULL ); memcpy( WindowTxt+25, s2, strlen(s2) );    //修改标题 } else { KillTimer(hwnd, tDown ); SetTimer( hwnd, tDown, tDownTime, NULL ); memcpy( WindowTxt+25, s1, strlen(s1) );    //修改标题 } SetWindowText(hwnd,WindowTxt); break; } case WM_PAINT:    //重绘窗口工作区 hdc = BeginPaint( hwnd, &ps ); hdcMem = CreateCompatibleDC( hdc ); hBitMap = CreateCompatibleBitmap( hdc, cxClient, cyClient ); SelectObject( hdcMem, hBitMap ); //画地图最外面的矩形(4, 4, 246, 446) Rectangle( hdcMem, StartX + LEN * 1 - 1,StartY + LEN * 1 - 1, StartX + LEN * (COL - 1) + 1, StartY + LEN * (ROW - 1) + 1 ); hPen = CreatePen( PS_SOLID, 1, RGB(180, 180, 180) ); SelectObject( hdcMem, hPen ); hBrush = CreateSolidBrush( RGB(250, 250, 250) ); SelectObject( hdcMem, hBrush ); for( y = 1; y < ROW - 1; y++ )    //画地图中的每一格 { for( x = 1; x < COL - 1; x++ ) { Rectangle( hdcMem, StartX + LEN * x, StartY + LEN * y, StartX + LEN * (x + 1), StartY + LEN * (y + 1) ); } } DeleteObject( hPen ); DeleteObject( hBrush ); hPen = CreatePen( PS_SOLID, 1, RGB(180, 180, 180) ); SelectObject( hdcMem, hPen ); hBrush = CreateSolidBrush( RGB(255, 100, 100) ); SelectObject(hdcMem, hBrush); for( y = 1; y < ROW - 1; y++ )    //画出地图中每个被占据的方格 { for( x = 1; x < COL - 1; x++ ) { if( Map[y][x] ) { Rectangle( hdcMem, StartX + LEN * x, StartY + LEN * y, StartX +LEN * (x + 1), StartY + LEN * (y + 1) ); } } } for( y = 0; y < 4; y++ )    //画当前方块 { for( x = 0; x < 4; x++ ) { if( CurrentBox[y][x] ) { if( y + CurrentY > 0 ) { Rectangle( hdcMem, (x + CurrentX) * LEN + StartX, (y + CurrentY) * LEN +StartY, (x + CurrentX + 1) * LEN + StartX, (y + CurrentY + 1) * LEN + StartY ); } } } } for( y = 0; y < 4; y++ )//在窗口右边区域画下一个方块 { for( x = 0; x < 4; x++ ) { if( NextBox[y][x] ) { Rectangle( hdcMem, (x + COL) * LEN + StartX, (y + 2) * LEN + StartY, (x+ COL + 1) * LEN + StartX,  (y + 3) * LEN + StartY ); } } } DeleteObject( hPen ); DeleteObject( hBrush ); DeleteObject( hBitMap ); BitBlt( hdc, 0, 0, cxClient, cyClient, hdcMem, 0, 0, SRCCOPY ); DeleteDC( hdcMem ); EndPaint( hwnd, &ps ); return 0; case WM_DESTROY: KillTimer(hwnd, tDown ); KillTimer(hwnd, tPaint ); PostQuitMessage( 0 ); return 0; }//end of switch( message ) return DefWindowProc( hwnd, message, wParam, lParam ); }
本文档为【VC 6.0 MFC 俄罗斯方块 自动求解 代码 源程序】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_435706
暂无简介~
格式:doc
大小:68KB
软件:Word
页数:37
分类:互联网
上传时间:2019-05-04
浏览量:43