- #ifndef DATA_H_
- #define DATA_H_
- /*
- * index:7行10列数组 每行对应一种方块类别。
- * 每行的前四列为x坐标,中间四列为y坐标
- * 第九列为方块类别代码,最后一列为该类型方块有几种变形
- * 用一个5*5的矩阵表示 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 /* DATA_H_ */
- #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,pelsSize*shape->x-(int)(pelsSize/2)+offsetx,pelsSize*shape->y-(int)(pelsSize/2)+offsety,
- // pelsSize*shape->x+(int)(pelsSize/2)+offsetx,pelsSize*shape->y+(int)(pelsSize/2)+offsety);
- // FillRect(hdc,rect,hBrush);
- // shape++;
- // rect++;
- // }
- for(int i=0;i<CTN;i++)
- {
- Rectangle(hdc,pelsSize*shape->x-(int)(pelsSize/2)+offsetx,pelsSize*shape->y-(int)(pelsSize/2)+offsety,
- pelsSize*shape->x+(int)(pelsSize/2)+offsetx+2,pelsSize*shape->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)CURRENTLEVEL*2/3;
- SetTimer(hwnd,TIMER,CURRENTLEVEL,NULL);
- cout<<"currentlevel:"<<CURRENTLEVEL<<endl;
- for(int i=0;i<15;i++)
- {
- if((int)CURRENTLEVEL*3*(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,i*pelsSize,0,NULL);
- LineTo(hdc,i*pelsSize,476);
- }
- for(int j=1;j<cySize;j++)
- {
- MoveToEx(hdc,0,j*pelsSize,NULL);
- LineTo(hdc,425,j*pelsSize);
- }
- SaveDC(hdc);
- for(int t=0;t<cySize;t++)
- for(int k=0;k<cxSize;k++)
- {
- if(fillArea[t][k]>0)
- {
- Rectangle(hdc,k*pelsSize,t*pelsSize,(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);
- }
来源: http://www.phpxs.com/code/1004221/