主要由两个头文件和两个源文件构成;
elsHead.h
#ifndef DEF_ELS_HEAD
#define DEF_ELS_HEAD
#include <windows.h>
#include <time.h>
#define DEF_TIMER1 1234
void OnPaint(HDC hDc);
void OnCreatte();
//显示方块
void PaintSqare(HDC hMemDC);
//产生随机块
int CreateRandomSqare();
//随机块贴近背景
void CopySqareToBack();
void OnCreate();
void OnReturn(HWND hWnd);
//方块下落
void sqareDown();
void sqareLeft();
void sqareRight();
//定时器响应函数
void OnTimer(HWND hWnd);
void OnLeft(HWND hWnd);
void OnRight(HWND hWnd);
void OnDown(HWND hWnd);
void OnChangeSqare(HWND hWnd);
//方块停在最底下
int CanSqareDown();
int CanSqareDown2();
int CanSqareLeft();
int CanSqareLeft2();
int CanSqareRight();
int CanSqareRight2();
int CanSqareChangeShape();
int CanLineSqareChange();
int CanGameOver();
//1变成2
void Change1To2();
void ChangeSqare();
void ChangeLineSqare();
void DestroyOneLineSqare();
//显示2
void ShowSqare2(HDC hMemDC);
void ShowScore(HDC hMemDC);
#endif
resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 square.rc 使用
//
#define IDI_ICON1 101
#define IDI_ICON2 102
#define IDI_ICON3 103
#define IDC_NODROP 106
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
源文件 elsHeaed.c
#include "elsHead.h"
char g_arrBackGroud[20][10]={0};
char g_arrSqare[2][4]={0};
int g_nSqareID=-1;
int g_nLine=-1;
int g_nList=-1;
int g_nScore=0;
void OnPaint(HDC hDc)
{
HDC hMemDC=CreateCompatibleDC(hDc);
//创建一张纸
HBITMAP hBitmapBack=CreateCompatibleBitmap(hDc,500,600);
//关联起来
SelectObject(hMemDC,hBitmapBack);
ShowScore(hMemDC);
PaintSqare(hMemDC);
ShowSqare2(hMemDC);
//传递源
BitBlt(hDc,0,0,500,600,hMemDC,0,0,SRCCOPY);
DeleteObject(hBitmapBack);
DeleteDC(hMemDC);
}
void ShowScore(HDC hMemDC)
{
char strScore[10]={0};
Rectangle(hMemDC,300,0,500,600);
itoa(g_nScore*10,strScore,10);
TextOut(hMemDC,400,12,strScore,strlen(strScore));
}
void OnCreatte()
{
srand((unsigned int)time(NULL));
CreateRandomSqare();
CopySqareToBack();
}
void PaintSqare(HDC hMemDC)
{
int i,j;
//画大方块
Rectangle(hMemDC,0,0,300,600);
/*g_arrBackGroud[2][4]=1;
g_arrBackGroud[2][5]=1;
g_arrBackGroud[2][6]=1;
g_arrBackGroud[3][5]=1;*/
//遍历
for(i=0;i<20;i++)
{
for(j=0;j<10;j++)
{
if(g_arrBackGroud[i][j])
{
//画方块
Rectangle(hMemDC,j*30,i*30,j*30+30,i*30+30);
}
}
}
//Rectangle(hMemDC,30,30,60,60);
}
//创建随机块
int CreateRandomSqare()
{
int nIndex=rand()%7;
switch(nIndex)
{
case 0:
g_arrSqare[0][0]=1;
g_arrSqare[0][1]=1;
g_arrSqare[0][2]=0;
g_arrSqare[0][3]=0;
g_arrSqare[1][0]=0;
g_arrSqare[1][1]=1;
g_arrSqare[1][2]=1;
g_arrSqare[1][3]=0;
g_nLine=0;
g_nList=3;
break;
case 1:
g_arrSqare[0][0]=0;
g_arrSqare[0][1]=1;
g_arrSqare[0][2]=1;
g_arrSqare[0][3]=0;
g_arrSqare[1][0]=1;
g_arrSqare[1][1]=1;
g_arrSqare[1][2]=0;
g_arrSqare[1][3]=0;
g_nLine=0;
g_nList=3;
break;
case 2:
g_arrSqare[0][0]=1;
g_arrSqare[0][1]=0;
g_arrSqare[0][2]=0;
g_arrSqare[0][3]=0;
g_arrSqare[1][0]=1;
g_arrSqare[1][1]=1;
g_arrSqare[1][2]=1;
g_arrSqare[1][3]=0;
g_nLine=0;
g_nList=3;
break;
case 3:
g_arrSqare[0][0]=0;
g_arrSqare[0][1]=0;
g_arrSqare[0][2]=1;
g_arrSqare[0][3]=0;
g_arrSqare[1][0]=1;
g_arrSqare[1][1]=1;
g_arrSqare[1][2]=1;
g_arrSqare[1][3]=0;
g_nLine=0;
g_nList=3;
break;
case 4:
g_arrSqare[0][0]=0;
g_arrSqare[0][1]=1;
g_arrSqare[0][2]=0;
g_arrSqare[0][3]=0;
g_arrSqare[1][0]=1;
g_arrSqare[1][1]=1;
g_arrSqare[1][2]=1;
g_arrSqare[1][3]=0;
g_nLine=0;
g_nList=3;
break;
case 5:
g_arrSqare[0][0]=0;
g_arrSqare[0][1]=1;
g_arrSqare[0][2]=1;
g_arrSqare[0][3]=0;
g_arrSqare[1][0]=0;
g_arrSqare[1][1]=1;
g_arrSqare[1][2]=1;
g_arrSqare[1][3]=0;
g_nLine=0;
g_nList=4;
break;
case 6:
g_arrSqare[0][0]=1;
g_arrSqare[0][1]=1;
g_arrSqare[0][2]=1;
g_arrSqare[0][3]=1;
g_arrSqare[1][0]=0;
g_arrSqare[1][1]=0;
g_arrSqare[1][2]=0;
g_arrSqare[1][3]=0;
g_nLine=0;
g_nList=4;
break;
}
g_nSqareID=nIndex;
return nIndex;
}
void CopySqareToBack()
{
int i,j;
for(i=0;i<2;i++)
{
for(j=0;j<4;j++)
{
g_arrBackGroud[i][j+3]=g_arrSqare[i][j];
}
}
}
void OnReturn(HWND hWnd)
{
//打开定时器
SetTimer(hWnd,DEF_TIMER1,500,NULL);
}
//方块下落
void sqareDown()
{
int i,j;
for(i=19;i>=0;i--)
{
for(j=0;j<10;j++)
{
if(1==g_arrBackGroud[i][j])
{
g_arrBackGroud[i+1][j]=g_arrBackGroud[i][j];
g_arrBackGroud[i][j]=0;
}
}
}
}
//定时器响应函数
void OnTimer(HWND hWnd)
{
HDC hDc=GetDC(hWnd);//内核对象
if(1==CanSqareDown()&&1==CanSqareDown2())
{
sqareDown();
g_nLine++;
}
else
{
//1变成2
Change1To2();
DestroyOneLineSqare();
if(0==CanGameOver())
{
//结束
KillTimer(hWnd,DEF_TIMER1);
//return 0;
}
//ShowSqare2(hMemDC)
//产生随机块
CreateRandomSqare();
//复制到背景上
CopySqareToBack();
}
//显示方块
//PaintSqare(hDc);
OnPaint(hDc);
ReleaseDC(hWnd,hDc);
}
int CanGameOver()
{
int i=0;
for(i=0;i<10;i++)
{
if(2==g_arrBackGroud[0][i])
{
//游戏结束
MessageBox(NULL,"GameOver","提示",MB_YESNO);
return 0;
}
}
return 1;
}
//方块停在最底下,0不可以,1可以下落
int CanSqareDown()
{
int i=0;
for(i=0;i<10;i++)
{
if(1==g_arrBackGroud[19][i])
{
return 0;
}
}
return 1;
}
void Change1To2()
{
int i,j;
for(i=0;i<20;i++)
{
for(j=0;j<10;j++)
{
if(1==g_arrBackGroud[i][j])
{
g_arrBackGroud[i][j]=2;
}
}
}
}
void ShowSqare2(HDC hMemDC)
{
int i,j;
HBRUSH hOldBrush;
HBRUSH hNewBrush=CreateSolidBrush(RGB(63,191,49));
hOldBrush=SelectObject(hMemDC,hNewBrush);
for(i=0;i<20;i++)
{
for(j=0;j<10;j++)
{
if(2==g_arrBackGroud[i][j])
{
//画方块
Rectangle(hMemDC,j*30,i*30,j*30+30,i*30+30);
}
}
}
hOldBrush = SelectObject(hMemDC,hNewBrush);
DeleteObject(hNewBrush);
}
int CanSqareDown2()
{
int i,j;
for(i=19;i>=0;i--)
{
for(j=0;j<10;j++)
{
if(1==g_arrBackGroud[i][j])
{
if(2==g_arrBackGroud[i+1][j])
{
return 0;
}
}
}
}
return 1;
}
void OnLeft(HWND hWnd)
{
//方块左移
if(1==CanSqareLeft()&&1==CanSqareLeft2())
{
HDC hDc=GetDC(hWnd);
sqareLeft();
g_nList--;
//显示方块
OnPaint(hDc);
ReleaseDC(hWnd,hDc);
}
}
void sqareLeft()
{
int i,j;
for(i=0;i<20;i++)
{
for(j=0;j<10;j++)
{
if(1==g_arrBackGroud[i][j])
{
g_arrBackGroud[i][j-1]=g_arrBackGroud[i][j];
g_arrBackGroud[i][j]=0;
}
}
}
}
int CanSqareLeft()
{
int i=0;
for(i=0;i<20;i++)
{
if(1==g_arrBackGroud[i][0])
{
return 0;
}
}
return 1;
}
int CanSqareLeft2()
{
int i,j;
for(i=0;i<20;i++)
{
for(j=0;j<10;j++)
{
if(1==g_arrBackGroud[i][j])
{
if(2==g_arrBackGroud[i][j-1])
{
return 0;
}
}
}
}
return 1;
}
void OnRight(HWND hWnd)
{
if(1==CanSqareRight()&&1==CanSqareRight2())
{
HDC hDc=GetDC(hWnd);
//方块右移
sqareRight();
g_nList++;
OnPaint(hDc);
ReleaseDC(hWnd,hDc);
}
}
void sqareRight()
{
int i,j;
for(i=0;i<20;i++)
{
for(j=9;j>=0;j--)
{
if(1==g_arrBackGroud[i][j])
{
g_arrBackGroud[i][j+1]=g_arrBackGroud[i][j];
g_arrBackGroud[i][j]=0;
}
}
}
}
int CanSqareRight()
{
int i=0;
for(i=0;i<20;i++)
{
if(1==g_arrBackGroud[i][9])
{
return 0;
}
}
return 1;
}
int CanSqareRight2()
{
int i,j;
for(i=0;i<20;i++)
{
for(j=9;j>=0;j--)
{
if(1==g_arrBackGroud[i][j])
{
if(2==g_arrBackGroud[i][j+1])
{
return 0;
}
}
}
}
return 1;
}
void OnDown(HWND hWnd)
{
OnTimer(hWnd);
}
void OnChangeSqare(HWND hWnd)
{
HDC hDc=GetDC(hWnd);
switch(g_nSqareID)
{
case 0:
case 1:
case 2:
case 3:
case 4:
//普通变形
if(1==CanSqareChangeShape())
{
ChangeSqare();
}
else
{
return;
}
break;
case 5://正方形
return;
case 6://长条形状
//变形
if(1==CanLineSqareChange())
{
ChangeLineSqare();
}
break;
}
OnPaint(hDc);
ReleaseDC(hWnd,hDc);
}
void ChangeSqare()
{
int i,j;
int nTemp=2;
char arrSqare[3][3]={0};
//背景块复制出来
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
arrSqare[i][j]=g_arrBackGroud[g_nLine+i][g_nList+j];
}
}
//变形复制回去
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
g_arrBackGroud[g_nLine+i][g_nList+j]=arrSqare[nTemp][i];
nTemp--;
}
nTemp=2;
}
}
int CanSqareChangeShape()
{
int i,j;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
if(2==g_arrBackGroud[g_nLine+i][g_nList+j])
{
return 0;
}
}
}
//if(g_nList<0||g_nList+2>9)
//{
// return 0;
//}
if(g_nList<0)
{
g_nList=0;
}
else if(g_nList+2>9)
{
g_nList=7;
}
return 1;
}
void ChangeLineSqare()
{
if(1==g_arrBackGroud[g_nLine][g_nList-1])//横着
{
//清零
g_arrBackGroud[g_nLine][g_nList-1]=0;
g_arrBackGroud[g_nLine][g_nList+1]=0;
g_arrBackGroud[g_nLine][g_nList+2]=0;
if(2==g_arrBackGroud[g_nLine+1][g_nList])
{
//赋值
g_arrBackGroud[g_nLine-1][g_nList]=1;
g_arrBackGroud[g_nLine-2][g_nList]=1;
g_arrBackGroud[g_nLine-3][g_nList]=1;
}
else if(2==g_arrBackGroud[g_nLine+2][g_nList])
{
//赋值
g_arrBackGroud[g_nLine+1][g_nList]=1;
g_arrBackGroud[g_nLine-1][g_nList]=1;
g_arrBackGroud[g_nLine-2][g_nList]=1;
}
else
{
//元素赋值
g_arrBackGroud[g_nLine-1][g_nList]=1;
g_arrBackGroud[g_nLine+1][g_nList]=1;
g_arrBackGroud[g_nLine+2][g_nList]=1;
}
}
else
{
//清零
g_arrBackGroud[g_nLine-1][g_nList]=0;
g_arrBackGroud[g_nLine+1][g_nList]=0;
g_arrBackGroud[g_nLine+2][g_nList]=0;
if(2==g_arrBackGroud[g_nLine+2][g_nList]||9==g_nList)
{
//元素赋值
g_arrBackGroud[g_nLine][g_nList-1]=1;
g_arrBackGroud[g_nLine][g_nList-2]=1;
g_arrBackGroud[g_nLine][g_nList-3]=1;
//标记改变
g_nList=g_nList-2;
}
else if(2==g_arrBackGroud[g_nLine][g_nList+2]||8==g_nList)
{
//元素赋值
g_arrBackGroud[g_nLine][g_nList+1]=1;
g_arrBackGroud[g_nLine][g_nList-1]=1;
g_arrBackGroud[g_nLine][g_nList-2]=1;
//标记改变
g_nList=g_nList-1;
}
else if(2==g_arrBackGroud[g_nLine][g_nList-1]||0==g_nList)
{
//元素赋值
g_arrBackGroud[g_nLine][g_nList+1]=1;
g_arrBackGroud[g_nLine][g_nList+2]=1;
g_arrBackGroud[g_nLine][g_nList+3]=1;
//标记改变
g_nList=g_nList+1;
}
else
{
//元素赋值
g_arrBackGroud[g_nLine][g_nList-1]=1;
g_arrBackGroud[g_nLine][g_nList+1]=1;
g_arrBackGroud[g_nLine][g_nList+2]=1;
}
}
}
int CanLineSqareChange()
{
int i=0;
int j=0;
for(i=1;i<4;i++)//右
{
if(2==g_arrBackGroud[g_nLine][g_nList+i]||g_nList+i>9)
{
break;
}
}
for(j=1;j<4;j++)
{
if(2==g_arrBackGroud[g_nLine][g_nList-j]||g_nList-j<0)
{
break;
}
}
if((i-1+j-1)<3)
{
return 0;
}
return 1;
}
void DestroyOneLineSqare()
{
int i,j;
int nTempi=0;
int nSum=0;
for(i=19;i>=0;i--)
{
for(j=0;j<10;j++)
{
nSum+=g_arrBackGroud[i][j];
}
if(20==nSum)
{
//消除一行
for(nTempi=i-1;nTempi>=0;nTempi--)
{
for(j=0;j<10;j++)
{
g_arrBackGroud[nTempi+1][j]=g_arrBackGroud[nTempi][j];
}
}
g_nScore++;
//
i=20;
}
nSum=0;//清除
}
}
main.c
#include"elsHead.h"
#include"resource.h"
#include<stdio.h>
LRESULT CALLBACK PELouSi(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPreInstance,LPTSTR lpCmdLine,int NCmdShow)
{
WNDCLASSEX wc;
HWND hWnd;
MSG mSg;
wc.cbClsExtra=0;
wc.cbSize=sizeof(WNDCLASSEX);
wc.cbWndExtra=0;
wc.hbrBackground=(HBRUSH)COLOR_WINDOW;
wc.hCursor=LoadCursor(NULL,IDC_HELP);//TODO 测试
wc.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON2)); //TODO 测试
wc.hIconSm=NULL;
wc.hInstance=hInstance;
wc.lpfnWndProc=PELouSi;//回调函数地址
wc.lpszClassName="els";
wc.lpszMenuName=NULL;
wc.style=CS_HREDRAW|CS_VREDRAW;
if(0==RegisterClassEx(&wc))
{
int a=GetLastError();
return 0;
}
hWnd=CreateWindowEx(WS_EX_TOPMOST,"els","俄罗斯方块",WS_OVERLAPPEDWINDOW,100,30,500,650,NULL,NULL,hInstance,NULL);
if(NULL==hWnd)
{
return 0;
}
ShowWindow(hWnd,SW_SHOWNORMAL);
while(GetMessage(&mSg,NULL,0,0))
{
TranslateMessage(&mSg);
DispatchMessage(&mSg);
}
return 0;
}
LRESULT CALLBACK PELouSi(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)
{
PAINTSTRUCT pt;
HDC hDc;
switch(nMsg)
{
case WM_CREATE:
//GetLastError();
OnCreatte();
break;
case WM_TIMER:
//printf("aaaaa");
// GetLastError();
OnTimer(hWnd);
break;
case WM_PAINT:
hDc=BeginPaint(hWnd,&pt);
OnPaint(hDc);
EndPaint(hWnd,&pt);
break;
case WM_KEYDOWN:
switch(wParam)
{
case VK_RETURN:
OnReturn(hWnd);
break;
case VK_LEFT:
OnLeft(hWnd);
break;
case VK_RIGHT:
OnRight(hWnd);
break;
case VK_UP:
OnChangeSqare(hWnd);
break;
case VK_DOWN:
OnDown(hWnd);
break;
}
break;
case WM_DESTROY:
KillTimer(hWnd,DEF_TIMER1);
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd,nMsg,wParam,lParam);
}
运行效果如下