先说这种俄罗斯方块的游戏规则('w','a','s','d' -> 旋转,左边,快速下降,右边): 1、右边4x4方块群内左键自造积木,右键放下积木(只有等当前积木下落停靠后,右键放下新的积木才有效)。 2、右面的墙是粘性墙,会黏住最右边的积木而只能下降不能向左(这会形成分散型积木,从而出现真空静止的积木)。 3、靠上固定的积木就会一同固定(也就是说每块积木之间都有粘性)
左手键盘wasd,右手(或者女朋友的手)操作鼠标左键来构造新积木,右键放下构造的积木。
总共237行,代码如下: (VC08下编译通过)
1/**//* SelfTetris.h */ 2 3 4#include <windows.h> 5 6class SelfTetris 7{ 8#define DELTA_LEFTTOP 20 9#define PV(v) (DELTA_LEFTTOP+(v)*D_LEN) 10#define BIN_FOR_BEGINE(i,j,topi,topj) for(i=0;i!=(topi);++i)for(j=0;j!=(topj);++j) 11public: 12 void Action(); 13 int IsMove(int x,int y);/**//* 是否能向(x,y)向量移动 */ 14 int IsDis(int y);/**//* 是否消除第y行 */ 15 int GoCurdle(int x,int y,int isFall,int isX);/**//* 按(x,y)向量*/ 16 void KeyDown(WPARAM wparam); 17 void Run(int x,int y,int isX);/**//* 一次移动 */ 18 void RotateBlocks(); 19 void CastBlocks(); 20 void SetBlocks(int mx,int my); 21 int Rectangle(int i,int j,int isStill);/**//* 在游戏矩阵内画矩形,isStill为是否画静止类型的矩形 */ 22 SelfTetris(int dtime_=100); 23public: 24 static const int W_NUM=18,H_NUM=35,D_LEN=15,H_HIDE=1;/**//* 游戏区域宽,高,单位长度象素,顶部是否隐藏*/ 25 int canDrop,_x,_y,obj[4][4];/**//* _x,_y 为当前下落积木重心 ,obj为当前构造积木形状, canDrop为是否可下新积木*/ 26 int scores;/**//* 分数,临时变量*/ 27 int board[H_NUM][W_NUM];/**//* 俄罗斯方块游戏区域矩阵 */ 28 int x,y,dtime,i,j;/**//* x,y,i,j为临时变量 dtime为游戏action周期*/ 29 HDC hdc; 30}; 31
1/**//* SelfTetris.cpp */ 2 3#include "SelfTetris.h" 4 5int SelfTetris::Rectangle(int i,int j,int isStill) 6{ 7 isStill=isStill?GRAY_BRUSH:WHITE_BRUSH; 8 SelectObject (hdc, GetStockObject (isStill)) ; 9 ::Rectangle(hdc,PV(j),PV(i),PV(j+1),PV(i+1)); 10 SelectObject (hdc, GetStockObject (GRAY_BRUSH)) ; 11 return 0; 12} 13int SelfTetris::IsMove(int x,int y) 14{ 15 BIN_FOR_BEGINE(i,j,H_NUM,W_NUM) 16 if((board[i][j]==2)&&((i+y>=H_NUM||i+y<=-1)||(board[i+y][j+x]==1))) 17 return -1; 18 else if((board[i][j]==2)&&((j+x>=W_NUM||j+x<=-1))) 19 return 0; 20 return 1; 21} 22int SelfTetris::IsDis(int y) 23{ 24 for(j=0;j!=W_NUM;j++) 25 if(board[y][j]!=1) return 0; 26 for(j=0;j!=W_NUM;j++) board[y][j]=0; 27 for(int i=y-1;i!=-1;--i) 28 for(int j=0;j!=W_NUM;++j) 29 if(board[i][j]==1) 30 { 31 board[i+1][j]=1; 32 i>=H_HIDE?Rectangle(i+1,j,1):1; 33 board[i][j]=0; 34 } 35 return 1; 36} 37int SelfTetris::GoCurdle(int x,int y,int isFall,int isX) 38{ 39 int tag=0,a,b,d; 40 a=W_NUM-1,b=-1,d=-1; 41 if(x==-1) b=W_NUM-1,a=0,d=1; 42 for(i=H_NUM-1;i!=-1;--i) 43 for(j=a;j!=b;j+=d) 44 if(board[i][j]==2) 45 { 46 if(isFall==-1){ 47 canDrop=1; 48 board[i][j]=1; 49 i>=H_HIDE&&isX==0?Rectangle(i,j,1):1; 50 }else if(isFall==1) 51 { 52 board[i+y][j+x]=2,board[i][j]=0; 53 i>=H_HIDE&&isX==0?Rectangle(i+y,j+x,0):1; 54 tag=1; 55 } 56 }else if(board[i][j]==1) 57 i>=H_HIDE&&isX==0?Rectangle(i,j,1):1; 58 if(tag==1) _x+=x,_y+=y; 59 if(isX==0) 60 BIN_FOR_BEGINE(i,j,4,4) 61 Rectangle(H_NUM/2+4+i,W_NUM+4+j,!(obj[i][j]==1)); 62 return isFall; 63} 64void SelfTetris::KeyDown(WPARAM wparam) 65{ 66 switch (wparam) 67 { 68 case 0x41:i=-1;break; 69 case 0x57: RotateBlocks();break; 70 case 0x53:i=2;break; 71 case 0x44:i=1; 72 } 73} 74void SelfTetris::Run(int x,int y,int isX) 75{ 76 SelectObject (hdc, GetStockObject (BLACK_PEN)) ; 77 ::Rectangle(hdc,DELTA_LEFTTOP,DELTA_LEFTTOP+H_HIDE*D_LEN,DELTA_LEFTTOP+W_NUM*D_LEN,DELTA_LEFTTOP+H_NUM*D_LEN); 78 SelectObject (hdc, GetStockObject (GRAY_BRUSH)) ; 79 int mul=0; 80 GoCurdle(x,y,IsMove(x,y),isX); 81 for(i=0;i!=H_NUM;i++) 82 IsDis(i)?++mul>=2?scores+=10*mul:scores+=10:1; 83 static wchar_t str[40]; 84 SelectObject (hdc, GetStockObject (BLACK_PEN)); 85 wsprintf(str,L" Total Score : %d ",scores); 86 TextOut(hdc,320,200,str,wcslen(str)); 87 wsprintf(str,L" Game Level : %d ",scores/10+1); 88 TextOut(hdc,320,250,str,wcslen(str)); 89} 90 91void SelfTetris::RotateBlocks() 92{ 93 int _board[H_NUM][W_NUM]={0}; 94 BIN_FOR_BEGINE(x,y,H_NUM,W_NUM) 95 if(board[x][y]==2) 96 if((_x+_y-x)>=W_NUM||(_x+_y-x)<=-1||(_y-(_x-y))>=H_NUM|| 97 (_y-(_x-y))<=-1||board[_y-(_x-y)][_x+(_y-x)]==1) 98 return; 99 BIN_FOR_BEGINE(x,y,H_NUM,W_NUM) 100 if(board[x][y]==2) 101 board[x][y]=0,_board[_y-(_x-y)][_x+(_y-x)]=2; 102 BIN_FOR_BEGINE(x,y,H_NUM,W_NUM) 103 if(_board[x][y]==2) 104 board[x][y]=_board[x][y]; 105} 106void SelfTetris::SetBlocks(int mx,int my) 107{ 108 BIN_FOR_BEGINE(x,y,4,4) 109 if(my>PV(H_NUM/2+4+x)&& 110 my<PV(H_NUM/2+4+x+1)&& 111 mx>PV(W_NUM+4+y)&& 112 mx<PV(W_NUM+4+y+1)) 113 obj[x][y]=(obj[x][y]+1)%2; 114} 115void SelfTetris::CastBlocks() 116{ 117 if(canDrop==0) 118 return; 119 BIN_FOR_BEGINE(x,y,4,4) 120 if(obj[x][y]==1) 121 board[0+x][W_NUM/2+y]=2; 122 canDrop=0; 123 _x=W_NUM/2+2; 124 _y=2; 125} 126void SelfTetris::Action() 127{ 128 if(i==2) Run(0,1,1); 129 else if(i!=0) Run(i,0,1); 130 for(x=0;x!=scores/10+1;x++) 131 Run(0,1,0); 132 i=0; 133} 134SelfTetris::SelfTetris(int dtime_) 135{ 136 canDrop=0; 137 memset(obj,0,sizeof(int)*16); 138 memset(board,0,sizeof(int)*H_NUM*W_NUM); 139 board[0][W_NUM/2-1]=board[0][W_NUM/2+2]=board[0][W_NUM/2+4]=board[0][W_NUM/2+3]=2; 140 _x=W_NUM/2+2; 141 _y=2; 142 i=j=0; 143 scores=0; 144 dtime=dtime_; 145}
1/**//* TetrisGame.cpp */ 2 3#include "SelfTetris.h" 4 5SelfTetris aTetris(100); 6 7LRESULT CALLBACK WindowProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam) 8{ 9 aTetris.hdc=GetDC(hwnd); 10 int mx = (int)LOWORD(lparam),my = (int)HIWORD(lparam); 11 switch(msg) 12 { 13 case WM_KEYDOWN: 14 aTetris.KeyDown(wparam); 15 break; 16 case WM_LBUTTONDOWN: 17 aTetris.SetBlocks(mx,my); 18 break; 19 case WM_RBUTTONUP: 20 aTetris.CastBlocks(); 21 break; 22 case WM_CREATE: 23 SetTimer(hwnd,10,aTetris.dtime,0); 24 break; 25 case WM_TIMER: 26 27 aTetris.Action(); 28 break; 29 case WM_PAINT: 30 break; 31 case WM_CLOSE : 32 MessageBoxW(0,L"非常感谢测试~",L"SelfTetrisv1.0",0); 33 break; 34 case WM_QUIT: 35 case WM_DESTROY: 36 PostQuitMessage(0); 37 break; 38 default:break; 39 } 40 ReleaseDC(hwnd,aTetris.hdc); 41 return DefWindowProc(hwnd, msg, wparam, lparam); 42} 43 44 45int WINAPI WinMain(HINSTANCE hinstance,HINSTANCE hprevinstance,LPSTR lpcmdline,int ncmdshow) 46{ 47 WNDCLASSEX winclass={sizeof(WNDCLASSEX),CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW, 48 WindowProc,0,0,hinstance,LoadIcon(NULL, IDI_APPLICATION), 49 LoadCursor(NULL, IDC_ARROW),(HBRUSH__*)GetStockObject(BLACK_BRUSH),0, 50 L"SelfTetris",0}; 51 HWND hwnd; 52 MSG msg; 53 if (!RegisterClassEx(&winclass)) 54 return 0; 55 if (!(hwnd = CreateWindowEx(NULL,L"SelfTetris",L"SelfTetrisV1.0", 56 WS_OVERLAPPEDWINDOW | WS_VISIBLE,0,0,455,600,NULL,NULL,hinstance,NULL))) 57 return 0; 58 59 while(GetMessage(&msg,NULL,0,0)) 60 { 61 TranslateMessage(&msg); 62 DispatchMessage(&msg); 63 } 64 return msg.wParam; 65}
源文件这里下载: SelfTetrisV1.1.rar
|