俄罗斯方块源代码 C语言

来源:互联网 发布:4g数据移动数据 编辑:程序博客网 时间:2024/04/30 16:42
这段时间写了一个俄罗斯方块的程序,是基于win32的,C语言。现在把源码写在下面
总共包括三个文件,Main.cpp, TetrisControl.cpp, TetrisControl.h。
/////////////////////////////////////////////////////////////////////////////////////
//Main.cpp

#include"TetrisControl.h"
#include<windows.h>
#include<time.h>
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAMwParam,LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCEhPreInstance,LPSTR lpCmdLine,int 

nShowCmd)
{
HWND   hwnd=NULL;
MSG    msg={0};
TCHAR  AppName[]=TEXT("Tetris");
WNDCLASS wndcls={0};
wndcls.cbClsExtra=0;
wndcls.cbWndExtra=0;
wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
wndcls.hCursor=LoadCursor(NULL,IDC_ARROW);
wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);
//wndcls.hIcon=LoadIcon(hInstance,TEXT("icon1.ico"));
wndcls.hInstance=hInstance;
wndcls.lpfnWndProc=WndProc;
wndcls.lpszClassName=AppName;
wndcls.lpszMenuName=NULL;
wndcls.style=CS_HREDRAW|CS_VREDRAW;

if(!RegisterClass(&wndcls))
{
MessageBox(NULL,TEXT("RegisterClass Failed!"),0,MB_OK);
return 0;
}

hwnd=CreateWindow(AppName,TEXT("俄罗斯方块"),WS_OVERLAPPEDWINDOW,
 0,0,CW_USEDEFAULT,CW_USEDEFAULT,
 NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_SHOWNORMAL);
UpdateWindow(hwnd);

while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
 
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAMwParam,LPARAM lParam)
{
HDC    hdc;
PAINTSTRUCT ps;
HBRUSH     hBrush[2];
switch(msg)
{
case WM_CREATE:
srand((UINT)time(NULL));
SetTimer(hwnd,ID_Event,800,NULL);
ExportBlock();
break;
case WM_TIMER:
ChangeDirect(hwnd,VK_DOWN);
InvalidateRect(hwnd,NULL,TRUE);//重新绘制
break;
case WM_KEYDOWN:
ChangeDirect(hwnd,wParam);
InvalidateRect(hwnd,NULL,TRUE);//重新绘制
break;
case WM_PAINT:
hBrush[0]=CreateSolidBrush(RGB(0,0,255));
hBrush[1]=CreateSolidBrush(RGB(0,255,0));

hdc=BeginPaint(hwnd,&ps);
DrawFrame(hdc,hBrush[0]);    //画游戏区域
InitPlane(hdc,hBrush[1],hwnd);//画上帧方块
DrawRect(hdc,hBrush[1]);     //画顶部输出方块
EndPaint(hwnd,&ps);
DeleteObject(hBrush[0]);
DeleteObject(hBrush[1]);
break;
case WM_DESTROY:
KillTimer(hwnd,ID_Event);
MessageBox(0,TEXT("Game Over"),0,MB_OK);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,msg,wParam,lParam);
}
///////////////////////////////////////////////////////////////////////////////////////////////
//TetrisControl.h
//各种函数以及变量的声明
#ifndef DUAN_TETRIS_CONTROL_H
#define DUAN_TETRIS_CONTROL_H

#include
#define RowLine 20
#define ColLine 15
#define Block   20
#define cx     50
#define cy     100
#define ID_Event 1

extern int nPosx;
extern int nPosy;
extern int nShape;
extern int nOption;
extern int g_bState[RowLine][ColLine];

const POINT Shape[7][4][4]=
{
{// 正方形
-1,-1,0,-1,-1,0,0,0,
-1,-1,0,-1,-1,0,0,0,
-1,-1,0,-1,-1,0,0,0,
-1,-1,0,-1,-1,0,0,0
},
{//长条形
-2,-1,-1,-1,0,-1,1,-1,//横条
0,-1,0,0,0,1,0,2,  //竖条
-2,-1,-1,-1,0,-1,1,-1,//横条
0,-1,0,0,0,1,0,2     //竖条
},
{//上闪电
-2,-1,-1,-1,-1,0,0,0,
0,-1,0,0,-1,0,-1,1,//竖闪电
-2,-1,-1,-1,-1,0,0,0,
0,-1,0,0,-1,0,-1,1 //竖闪电
},
{//下闪电
-1,-1,0,-1,-2,0,-1,0,
-1,-1,-1,0,0,0,0,1,//竖闪电
-1,-1,0,-1,-2,0,-1,0,
-1,-1,-1,0,0,0,0,1 //竖闪电
},
{//左三角
-2,-1,-2,0,-1,0,0,0, 
0,-1,0,0,0,1,-1,-1, //竖三角
-2,-1,-1,-1,0,-1,0,0,
-1,0,-1,1,-1,2,0,2  //竖三角
},
{//右三角
-2,0,-1,0,0,0,0,-1,
0,-2,0,-1,0,0,1,0,
-2,-1,-1,-1,0,-1,-2,0,
0,-2,1,-2,1,-1,1,0
},
{//T形
0,-1,0,0,1,0,-1,0,  //横T
0,-1,0,0,0,1,1,0,   //竖T
-1,-1,0,-1,1,-1,0,0,//横T
1,-1,1,0,1,1,0,0 //竖T
}
};

void DrawFrame(HDC hdc,HBRUSH hbrush);
void InitPlane(HDC hdc,HBRUSH hbrush,HWND hwnd);
void DrawRect(HDC hdc,HBRUSH hbrush);
void ExportBlock();
int  ChangeDirect(HWND hwnd,WPARAMwParam);
bool CheckCrash();
void CheckFull();
void ClearLine(int nStart);
int  GetDgree(HWND hwnd);
#endif
//////////////////////////////////////////////////////////////////////////////////////////////
//实现函数
#include"TetrisControl.h"

int nPosx; //初始化位置编号
int nPosy; //初始化位置编号
int nShape;  //初始化形状
int nOption; //初始化变形
int nScore=0;//初始化分数
int nDgree=0;//初始化等级
int g_bState[RowLine][ColLine]={0};
TCHAR szBuffer[20];

void DrawFrame(HDC hdc,HBRUSH hbrush)
{
POINT      pt1,pt2;
RECT       rect;

pt1.x=cx;
pt1.y=cy;
pt2.x=cx+Block*ColLine;
pt2.y=cy+Block*RowLine;
SetRect(&rect,pt1.x,pt1.y,pt2.x,pt2.y);//游戏区域
FillRect(hdc,&rect,hbrush);
}

void DrawRect(HDC hdc,HBRUSH hbrush)
{
int i=0;
int px=0;
int py=0;
RECT    rect;
for(i=0;i<4;i++)
{
px=Shape[nShape][nOption][i].x+nPosx;
py=Shape[nShape][nOption][i].y+nPosy;
SetRect(&rect,cx+px*Block,cy+py*Block+1,cx+(px+1)*Block-1,cy+(py+1)*Block);//减1为了留出缝隙
FillRect(hdc,&rect,hbrush);
}
}

void ExportBlock()
{
nShape  =rand()%7;
nOption =rand()%4;
nPosx   =ColLine/2;
nPosy    =1;
}

int ChangeDirect(HWND hwnd,WPARAM wParam)
{
int nPosxNext;
int nPosyNext;

switch(wParam)
{
case VK_LEFT:
nPosx--;
if(CheckCrash())
nPosx++;
break;
case VK_RIGHT:
nPosx++;
if(CheckCrash())
nPosx--;
break;
case VK_DOWN:
nPosy++;
if(CheckCrash())
{
nPosy--;
for(int i=0;i<4;i++)
{
nPosxNext=Shape[nShape][nOption][i].x+nPosx;//状态数组的横坐标
nPosyNext=Shape[nShape][nOption][i].y+nPosy;//状态数组的纵坐标
g_bState[nPosyNext][nPosxNext]=1;//此处要注意数组先后序号
}
CheckFull();
if(nPosy<2)
{
//KillTimer(hwnd,ID_Event);
SendMessage(hwnd,WM_DESTROY,NULL,NULL);
return 0;//碰撞后空间小于2就不再输出
}
else
ExportBlock();
}
break;
case VK_UP:
nOption=(nOption+1)%4;
if(CheckCrash())
nOption=(nOption+3)%4;
break;
}
return 1;
}

bool CheckCrash()
{
int nPosxNext;
int nPosyNext;
bool bEdge;
for(int i=0;i<4;i++)
{
nPosxNext=Shape[nShape][nOption][i].x+nPosx;//状态数组的横坐标
nPosyNext=Shape[nShape][nOption][i].y+nPosy;//状态数组的纵坐标
bEdge=nPosyNext==RowLine||nPosyNext==-1||nPosxNext==-1||nPosxNext==ColLine;
if(g_bState[nPosyNext][nPosxNext]||bEdge)
return true;
}
return false;
}
void InitPlane(HDC hdc,HBRUSH hbrush,HWND hwnd)
{
int i,j;
RECT rect;
for(i=0;i
for(j=0;j
{
if(g_bState[i][j])
{
SetRect(&rect,cx+j*Block,cy+i*Block+1,cx+(j+1)*Block-1,cy+(i+1)*Block);//减1留出缝隙
FillRect(hdc,&rect,hbrush);
}
}
//显示分数
TextOut(hdc,cx+(ColLine+5)*Block,cy+3*Block,szBuffer,wsprintf(szBuffer,TEXT("%s"),TEXT("Score")));
TextOut(hdc,cx+(ColLine+5)*Block,cy+5*Block,szBuffer,wsprintf(szBuffer,TEXT("]"),nScore));
//显示等级
nDgree=GetDgree(hwnd);
TextOut(hdc,cx+(ColLine+5)*Block,cy+8*Block,szBuffer,wsprintf(szBuffer,TEXT("%s"),TEXT("Dgree")));
TextOut(hdc,cx+(ColLine+5)*Block,cy+10*Block,szBuffer,wsprintf(szBuffer,TEXT("]"),nDgree));
//显示作者
TextOut(hdc,cx+(ColLine+5)*Block,cy+13*Block,szBuffer,wsprintf(szBuffer,TEXT("%s"),TEXT("Author")));
TextOut(hdc,cx+(ColLine+5)*Block,cy+15*Block,szBuffer,wsprintf(szBuffer,TEXT("%s"),TEXT("DXXXY")));

}
void CheckFull()
{
int i,j,nTemp;
int nMin=1000;
int nMax=-100;
int nCnt=0;
int nInc=0;
//找到方块碰撞后最小最大行数
for(i=0;i<4;i++)
{
nTemp=Shape[nShape][nOption][i].y+nPosy;
if(nTemp>nMax)
nMax=nTemp;
if(nTemp
nMin=nTemp;
}
//检测满行
for(i=nMin;i<=nMax;i++)
{
for(j=0;j
{
if(g_bState[i][j])nCnt++;
}
if(nCnt==ColLine)
{
nInc++;
ClearLine(i);
}
nCnt=0;
}
//获取分数
switch(nInc)
{
case 0:break;
case 1:nScore+=10;break;
case 2:nScore+=25;break;
case 3:nScore+=40;break;
case 4:nScore+=55;break;

}
}
void ClearLine(int nStart)
{
for(int i=nStart;i>0;i--)
{
for(int j=0;j
g_bState[i][j]=g_bState[i-1][j];
}
}

int GetDgree(HWND hwnd)
{
if(nScore>10000)
{
MessageBox(hwnd,TEXT("You have played so long and please havea rest!"),0,0);
return 100;
}
else 
return nScore/100+1;

}