C++编写的俄罗斯方块代码

清华大佬耗费三个月吐血整理的几百G的资源,免费分享!....>>>

#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);
}