C++編寫的俄羅斯方塊代碼
#ifndef DATAHdefine DATAH
/*
- index:7行10列數組 每行對應一種方塊類別。
- 每行的前四列為x坐標,中間四列為y坐標
- 第九列為方塊類別代碼,最后一列為該類型方塊有幾種變形
- 用一個55的矩陣表示 7種類別方塊 共19種變形/ #include<windows.h> static const int KINDS=7;//方塊種類數量 static const int COLS=10;//數據列數
//每種方塊的代號 static const int TYPE1=1; static const int TYPE2=2; static const int TYPE3=3; static const int TYPE4=4; static const int TYPE5=5; static const int TYPE6=6; static const int TYPE7=7;
//變形的種類 static const int RTYPE1=1; static const int RTYPE2=2; static const int RTYPE3=4;
static int rTypeNext; static int rTypeDown;
//初始化方塊坐標及對應的類別和變形種類 static const int index[KINDS][COLS]={ {0,1,0,1,0,0,-1,-1,TYPE1,RTYPE1}, {-1,0,1,2,0,0,0,0,TYPE2,RTYPE2}, {0,0,1,1,1,0,0,-1,TYPE3,RTYPE2}, {0,0,1,1,-1,0,0,1,TYPE4,RTYPE2}, {-1,0,0,1,0,0,1,0,TYPE5,RTYPE3}, {-1,0,1,1,0,0,0,-1,TYPE6,RTYPE3}, {-1,0,1,1,0,0,0,1,TYPE7,RTYPE3} };
//定時器ID static const int TIMER=1; // //初始游戲級別對應的時間間隔 static int CURRENTLEVEL=600; static int level=1;
//每種圖形所包含的小方塊數 static const int CTN=4;
//方塊形狀定義 typedef struct { int x; int y; }sCord; sCord sDown[CTN],sNext[CTN];
//下一個方塊的坐標 static RECT rectNext[CTN]; //正在下落方塊的坐標 static RECT rectDown[CTN];
//顯示區域的大小 static const int cxSize=25; static const int cySize=35;
//方塊偏離(0,0)得位置 static int offsetx; static int offsety;
static int offsetxNext; static int offsetyNext;
//自定義消息 static const int MS_DOWN=10001; //暫停 static bool go=true; //開始 static bool startGame=false; //結束 static bool gameOver=false; //得分 static int score;
RECT rt={326,81,425,455};
//每個方格包含的像素 static const int pelsSize=13;
//顯示區域大小的定義 static const POINT area[]={0,455,326,455,326,0}; //顯示區域的表示方法 最后一列最后一行分別對應該行該列所具有的方塊總數 0表示沒有方塊1表示有 static int fillArea[cySize+1][cxSize+1];
HBRUSH hBrush1=CreateSolidBrush(RGB(0,0,0));//方塊顏色 //HBRUSH hBrush1=CreateSolidBrush(RGB(240,250,100));//黃色 HBRUSH hBrush2=CreateSolidBrush(RGB(255,255,255)); HPEN hPen1=CreatePen(PS_SOLID,0,RGB(230,230,230));//背景格顏色
endif / DATAH /
include"Data.h"
include<iostream>
include<cstdlib>
using namespace std;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); /*
- 逆時針方向旋轉方格 返回能否旋轉
- @param lpsCord 要旋轉的方塊坐標指針
- @param rType 旋轉類型
- @param rNumber 旋轉次數
- @param 是否第一次旋轉 / bool rotate(sCord lpsCord,int rType,int rNumber,bool firstRotate); void getRandom();//初始化方格形狀 void getNext(sCord targ,const sCord sur);//取出下一個方塊 void draw();//繪出方格 void start();//開始游戲 bool downAble();//能否下落 bool leftAble();//能否左移 bool rightAble();//能否右移 bool disRows(HWND hwnd);//判斷能否消行
//int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, // // PSTR szCmdLine, int iCmdShow)
//void paintRect(HDC hdc,RECT&,HBRUSH hBrush);
int main() { HINSTANCE hInstance=NULL; static TCHAR szAppName[]=TEXT("ELS"); HWND hwnd; MSG msg; WNDCLASS wndclass;
wndclass.style=CS_HREDRAW|CS_VREDRAW;//|~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX) ; 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);// CreateSolidBrush(RGB(195,195,237)); wndclass.lpszMenuName= NULL; wndclass.lpszClassName= szAppName;
if(!RegisterClass(&wndclass)) { MessageBox(NULL,TEXT("REGISTER ERROR"),szAppName,MB_ICONERROR); return 0; } hwnd=CreateWindow(szAppName,TEXT("俄羅斯方塊"),WS_DLGFRAME|WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX,//(WS_OVERLAPPED|WS_SYSMENU|WS_MINIMIZEBOX)&~WS_BORDER,//WS_SIZEBOX WS_OVERLAPPEDWINDOW&~WS_MAXIMIZEBOX,WS_CAPTION|//&~WS_MAXIMIZEBOX禁用最大化選項 300,100,429,480, NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_SHOWNORMAL); UpdateWindow(hwnd);
while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }
void getRandom() { int k=rand()%KINDS+1;
for(int i=0;i<KINDS;i++) { if(index[i][COLS-2]==k) { rTypeNext=index[i][COLS-1];//獲得旋轉類型 for(int j=0;j<CTN;j++) { sNext[j].x=index[i][j]; sNext[j].y=index[i][j+4];
} break; }
} rotate(sNext,rTypeNext,rand()%rTypeNext+1,true); int min_y=0; for (int t = 0; t < CTN; t++) min_y = min_y > sNext[t].y ? sNext[t].y : min_y;
offsetxNext=(int)(cxSize/2)pelsSize+(int)(pelsSize/2);//x方向的中間顯示 offsetyNext=(-min_y)pelsSize+(int)(pelsSize/2);//保證置頂顯示
} bool rotate(sCord *lpsCord,int rType,int rNumber,bool firstRotate) { int tempx; int tempy; int temp; int tx=(offsetx-(int)(pelsSize/2))/pelsSize; int ty=(offsety-(int)(pelsSize/2))/pelsSize;
bool ra=true; switch(rType) { case RTYPE1: ra=false; break; case RTYPE2: { if(rNumber%2!=0) { for (int j = 0; j < CTN; j++) { tempx=-lpsCord->y+tx; tempy=lpsCord->x+ty; lpsCord++; if(!firstRotate&&(fillArea[tempx][tempy]>0||tempx>24||tempx<0||tempy<0||tempy>34)) { ra=false; } } lpsCord-=4; } if(ra) { if (rNumber % 2 != 0) for (int k = 0; k < CTN; k++) { temp = -lpsCord->x; lpsCord->x = lpsCord->y; lpsCord->y = temp; lpsCord++; } }
} break; case RTYPE3: for(int k=0;k<rNumber;k++) { for(int l=0;l<CTN;l++) { tempx=lpsCord->y+tx; tempy=(-lpsCord->x)+ty; lpsCord++; if(!firstRotate&&(fillArea[tempx][tempy]>0||tempx>24||tempx<0||tempy<0||tempy>34)) { ra = false; } } lpsCord-=4; }
if(ra) for (int i = 0; i < rNumber; i++) { for (int j = 0; j < CTN; j++) { temp = -lpsCord->x; lpsCord->x = lpsCord->y; lpsCord->y = temp; lpsCord++; } lpsCord=lpsCord-4; } break; }
return ra;
} void getNext(sCord targ,const sCord sur) { rTypeDown=rTypeNext; offsetx=offsetxNext; offsety=offsetyNext; for(int i=0;i<CTN;i++) { targ->x=sur->x; targ->y=sur->y; sur++; targ++; } getRandom(); } void draw(HWND hwnd,const sCord shape,RECT rect,HBRUSH hBrush,int offsetx,int offsety) {
HDC hdc=GetDC(hwnd); SelectObject(hdc,hBrush); SelectObject(hdc,hPen1); // SelectObject(hdc,hPen2); // for(int i=0;i<CTN;i++) // { //// cout<<"draw:x="<<shape->x<<"y="<<shape->y<<endl; // SetRect(rect,pelsSizeshape->x-(int)(pelsSize/2)+offsetx,pelsSizeshape->y-(int)(pelsSize/2)+offsety, // pelsSizeshape->x+(int)(pelsSize/2)+offsetx,pelsSizeshape->y+(int)(pelsSize/2)+offsety); // FillRect(hdc,rect,hBrush); // shape++; // rect++; // } for(int i=0;i<CTN;i++) { Rectangle(hdc,pelsSizeshape->x-(int)(pelsSize/2)+offsetx,pelsSizeshape->y-(int)(pelsSize/2)+offsety, pelsSizeshape->x+(int)(pelsSize/2)+offsetx+2,pelsSizeshape->y+(int)(pelsSize/2)+offsety+2); shape++; // rect++; }
ReleaseDC(hwnd,hdc); } void start() { if(!startGame) { for (int i = 0; i < cySize + 1; i++) for (int j = 0; j < cxSize + 1; j++) fillArea[i][j] = 0; startGame=true; go=true; score=0; } } bool downAble() { bool da=true; int x=(offsetx-(int)(pelsSize/2))/pelsSize; int y=(offsety-(int)(pelsSize/2))/pelsSize; int xtemp; int ytemp; for(int i=0;i<CTN;i++) { xtemp=sDown[i].x+x; ytemp=sDown[i].y+y+1; if(fillArea[ytemp][xtemp]>0||ytemp>34) { da=false; break; } }
if (!da) { for (int k = 0; k < CTN; k++) { xtemp = sDown[k].x + x; ytemp = sDown[k].y + y; fillArea[ytemp][xtemp] = 1; fillArea[ytemp][cxSize]++; fillArea[cySize][xtemp]++; } } return da; } bool leftAble() { bool la = true; int x = (offsetx - (int) (pelsSize / 2)) / pelsSize; int y = (offsety - (int) (pelsSize / 2)) / pelsSize; int xtemp; int ytemp; for (int i = 0; i < CTN; i++) { xtemp = sDown[i].x + x-1; ytemp = sDown[i].y + y; if (fillArea[ytemp][xtemp] > 0 || xtemp <0) { la = false; break; } } return la; } bool rightAble() { bool ra = true; int x = (offsetx - (int) (pelsSize / 2)) / pelsSize; int y = (offsety - (int) (pelsSize / 2)) / pelsSize ; int xtemp; int ytemp; for (int i = 0; i < CTN; i++) { xtemp = sDown[i].x + x+1; ytemp = sDown[i].y + y; if (fillArea[ytemp][xtemp] > 0 || xtemp > 24) { ra = false; break; } } return ra; } bool disRows(HWND hwnd) { HDC hdc=GetDC(hwnd); bool da=false; int row[CTN];//可以消除的行 for (int ii = 0; ii < CTN; ii++) row[ii] = 0; int number = 0;//可連續消的行數 static int levelScore;
SelectObject(hdc,hPen1); for (int i = 0; i < cySize; i++) { if (fillArea[i][cxSize] == cxSize) row[number++] = i; } if (number > 0)//可以消行 { da=true; levelScore+=(number + 1) number / 2; score += (number + 1) number / 2; cout<<"levelScore:"<<levelScore<<endl; if(levelScore>19)//增加游戲級別 { levelScore=0; CURRENTLEVEL=(int)CURRENTLEVEL2/3; SetTimer(hwnd,TIMER,CURRENTLEVEL,NULL); cout<<"currentlevel:"<<CURRENTLEVEL<<endl; for(int i=0;i<15;i++) { if((int)CURRENTLEVEL3*(i+1)/2>=600) { level=i+2; cout<<"level"<<i+2<<endl; break; } } } InvalidateRect(hwnd,&rt,true); for (int k = 0; k < number; k++) { for(int i=row[k];i>0;i--) { for(int j=0;j<cxSize+1;j++) { fillArea[i][j]=fillArea[i-1][j];
}
} }
InvalidateRect(hwnd,NULL,true); } ReleaseDC(hwnd,hdc); return da; } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; RECT r; static bool down=false; bool isSend=false; switch(message) { case WM_CREATE: { SetTimer(hwnd,TIMER,CURRENTLEVEL,NULL); cout<<"level1"<<endl; return 0; } case WM_SIZE: // cout<<LOWORD(lParam)<<endl // <<HIWORD(lParam)<<endl; return 0; // case WM_GETMINMAXINFO: // return 0; case WM_TIMER: { if(startGame&&go) { if (down) { if(!downAble())//不能再下落條件 { cout<<"can not down"<<endl; down=false; disRows(hwnd); if(!isSend) { SendMessage(hwnd,MS_DOWN,0,0); isSend=true; }
}
else
{
draw(hwnd, sDown, rectDown,(HBRUSH)GetStockObject(WHITE_BRUSH), offsetx, offsety);
offsety += pelsSize;
draw(hwnd, sDown, rectDown,hBrush1, offsetx, offsety);
}
} }
return 0; } case MS_DOWN: { draw(hwnd,sNext,rectNext,(HBRUSH)GetStockObject(WHITE_BRUSH),369,44); getNext(sDown,sNext);
draw(hwnd,sNext,rectNext,hBrush1,369,44); draw(hwnd,sDown,rectDown,hBrush1,offsetx,offsety); //判斷游戲是否結束 offsety-=pelsSize; if(downAble()) { offsety+=pelsSize; isSend=false; down=true; } else { cout<<"game over!"<<endl; startGame=false; gameOver=true; InvalidateRect(hwnd,&rt,true);
}
} case WM_PAINT: { hdc = BeginPaint(hwnd, &ps); GetClientRect(hwnd, &r); SelectObject(hdc,hPen1); SelectObject(hdc,hBrush1); for(int i=1;i<cxSize+8;i++) { MoveToEx(hdc,ipelsSize,0,NULL); LineTo(hdc,ipelsSize,476); } for(int j=1;j<cySize;j++) { MoveToEx(hdc,0,jpelsSize,NULL); LineTo(hdc,425,jpelsSize); }
SaveDC(hdc); for(int t=0;t<cySize;t++) for(int k=0;k<cxSize;k++) { if(fillArea[t][k]>0) { Rectangle(hdc,kpelsSize,tpelsSize,(k+1)pelsSize+1,(t+1)pelsSize+1); } } if(startGame) { draw(hwnd,sNext,rectNext,hBrush1,369,44); draw(hwnd,sDown,rectDown,hBrush1,offsetx,offsety); } FillRect(hdc,&rt,hBrush2); char ss[20]; char ll[20]; wsprintf(ss,"score:%d",score); wsprintf(ll,"level:%d",level); TextOut(hdc,330,300,ll,lstrlen(ll)); TextOut(hdc,330,320,ss,lstrlen(ss));
if(gameOver) { char g[]="Game Over!!"; TextOut(hdc,330,200,g,lstrlen(g)); }
SelectObject(hdc, GetStockObject(BLACK_PEN)); Polyline(hdc, area, 3);//繪制一個矩形 MoveToEx(hdc, 325, 80, NULL); LineTo(hdc, 425, 80);
EndPaint(hwnd, &ps);
return 0; } case WM_KEYDOWN: switch(wParam) { case VK_UP: { if(go&&startGame) { down=false; draw(hwnd,sDown,rectDown,(HBRUSH)GetStockObject(WHITE_BRUSH),offsetx,offsety); rotate(sDown,rTypeDown,1,false); draw(hwnd,sDown,rectDown,hBrush1,offsetx,offsety);
}
}
return 0; case VK_DOWN: { if(go&&startGame) { down=false; draw(hwnd,sDown,rectDown,(HBRUSH)GetStockObject(WHITE_BRUSH),offsetx,offsety); int k=(offsety-(int)(pelsSize)/2)/pelsSize; while(k<cySize) { if(downAble()) { offsety+=pelsSize; } else break; } draw(hwnd,sDown,rectDown,hBrush1,offsetx,offsety); disRows(hwnd); SendMessage(hwnd,MS_DOWN,0,0); }
return 0; } case VK_LEFT: { if(leftAble()&&go&&startGame) { down=false; draw(hwnd,sDown,rectDown,(HBRUSH)GetStockObject(WHITE_BRUSH),offsetx,offsety); offsetx-=pelsSize; draw(hwnd,sDown,rectDown,hBrush1,offsetx,offsety);
}
return 0; } case VK_RIGHT: { if(rightAble()&&go&&startGame) { down=false; draw(hwnd, sDown, rectDown, (HBRUSH) GetStockObject(WHITE_BRUSH), offsetx, offsety); offsetx+=pelsSize; draw(hwnd, sDown, rectDown, hBrush1, offsetx, offsety);
}
return 0; } case VK_SPACE: { go=!go; return 0;
} case VK_RETURN: { if(!startGame&&!gameOver) { cout<<"startGame"<<endl; gameOver=false; start(); getRandom(); SendMessage(hwnd,MS_DOWN,0,0);
} if(!startGame&&gameOver) { cout<<"RestartGame!"<<endl; gameOver=false; start(); level=1; InvalidateRect(hwnd,NULL,true); getRandom(); SendMessage(hwnd,MS_DOWN,0,0); } return 0; } }
return 0; case WM_KEYUP: switch(wParam) { case VK_UP: if(go) down=true; return 0; case VK_LEFT: if(go) down=true; return 0; case VK_RIGHT: if(go) down=true; return 0; } return 0;
case WM_DESTROY: DeleteObject(hBrush1); DeleteObject(hBrush2); DeleteObject(hPen1); KillTimer(hwnd,TIMER); PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}</pre>