整个游戏方块就是一个二维数组,一个格子就是一个方块,这正好跟二维数组类似
二维数组哪个地方置1就表示有方块
单个小方块就是一个4*4的二维数组.
流戏中的数据结构就是这些
首先我们把全部方块数据记录起来
static int box[][4][4]={
{1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0},//0
{0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0},//1
{2,2,2,0,2,0,0,0,0,0,0,0,0,0,0,0},//2
{2,2,0,0,0,2,0,0,0,2,0,0,0,0,0,0},//3
{0,0,0,0,0,0,2,0,2,2,2,0,0,0,0,0},//4
{2,0,0,0,2,0,0,0,2,2,0,0,0,0,0,0},//5
{3,3,0,0,3,0,0,0,3,0,0,0,0,0,0,0},//6
{3,3,3,0,0,0,3,0,0,0,0,0,0,0,0,0},//7
{0,0,3,0,0,0,3,0,0,3,3,0,0,0,0,0},//8
{0,0,0,0,3,0,0,0,3,3,3,0,0,0,0,0},//9
{4,4,0,0,0,4,4,0,0,0,0,0,0,0,0,0},//10
{0,4,0,0,4,4,0,0,4,0,0,0,0,0,0,0},//11
{0,5,5,0,5,5,0,0,0,0,0,0,0,0,0,0},//12
{5,0,0,0,5,5,0,0,0,5,0,0,0,0,0,0},//13
{0,6,0,0,6,6,6,0,0,0,0,0,0,0,0,0},//14
{6,0,0,0,6,6,0,0,6,0,0,0,0,0,0,0},//15
{0,0,0,0,6,6,6,0,0,6,0,0,0,0,0,0},//16
{0,6,0,0,6,6,0,0,0,6,0,0,0,0,0,0},//17
{7,7,0,0,7,7,0,0,0,0,0,0,0,0,0,0}//18
};
再定义游戏板数据
int board[21][14] ={0}; //游戏主板,边界为墙
类似0号方块
1111
0000
0000
0000
其实就是一个长横着的方块
就像这样□□□□
我们要显示一个方块
for(i=0;i<4;i++)//如果对应方块信息不为0就显示画图
for(j=0;j<4;j++)
{
if(box[num][i][j]!=0)
{
Rectangle(hdc,x+j*ITEMSIZE,y+i*ITEMSIZE,x+j*ITEMSIZE+ITEMSIZE,y+i*ITEMSIZE+ITEMSIZE);//显示方块
}
}
显示游戏中的全部方块
for(i=0;i<HEIGHT;i++)
for(j=1;j<=WIDTH;j++)
if(board[i][j]==1)
Rectangle(hdc,(j-1)*20,i*20,(j-1)*20+20,i*20+20);
整个思想就是操作一个二维数组.
不多说了
贴上代码,直接复制粘贴编译就可以了..
#include<windows.h>
#include<time.h>
#define ID_TIMER 1 //记时器
#define ID_TIMERLAY 2 //延时用
#define WM_BOXSINK WM_USER+1 //方块沉底消息
#define WM_NEWBOX WM_USER+2 //新方块
#define WM_GAMEOVER WM_USER+3 //游戏结束
#define ITEMSIZE 20 //方块大小
#define NUMBOX 19 //方块种类数目
#define WIDTH 12 //宽度
#define HEIGHT 20 //高度
#define TOP 0 //顶点
#define BOTTOM 400 //底部点
const RECT rcClient={0,0,240,400};
const RECT rcNext ={260,60,340,140};
const RECT rcLevel ={300,260,400,300};
const RECT rcPause ={260,280,360,300};
const RECT rcStart ={100,0,180,80};
int level =1; //级别
int score =0; //分数
int cur_box =0; //当前方块编号
int next_box =0; //下一方块编号
int cur_x =100; //当前横坐标
int cur_y =0; //当前纵坐标
BOOL gameover =FALSE; //游戏结束标记
BOOL blay =FALSE;
HWND g_hWnd;
int board[21][14] ={0}; //游戏主板,边界为墙
static BOOL pause=FALSE; //暂停标记
//方块数据
static int box[][4][4]={
{1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0},//0
{0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0},//1
{2,2,2,0,2,0,0,0,0,0,0,0,0,0,0,0},//2
{2,2,0,0,0,2,0,0,0,2,0,0,0,0,0,0},//3
{0,0,0,0,0,0,2,0,2,2,2,0,0,0,0,0},//4
{2,0,0,0,2,0,0,0,2,2,0,0,0,0,0,0},//5
{3,3,0,0,3,0,0,0,3,0,0,0,0,0,0,0},//6
{3,3,3,0,0,0,3,0,0,0,0,0,0,0,0,0},//7
{0,0,3,0,0,0,3,0,0,3,3,0,0,0,0,0},//8
{0,0,0,0,3,0,0,0,3,3,3,0,0,0,0,0},//9
{4,4,0,0,0,4,4,0,0,0,0,0,0,0,0,0},//10
{0,4,0,0,4,4,0,0,4,0,0,0,0,0,0,0},//11
{0,5,5,0,5,5,0,0,0,0,0,0,0,0,0,0},//12
{5,0,0,0,5,5,0,0,0,5,0,0,0,0,0,0},//13
{0,6,0,0,6,6,6,0,0,0,0,0,0,0,0,0},//14
{6,0,0,0,6,6,0,0,6,0,0,0,0,0,0,0},//15
{0,0,0,0,6,6,6,0,0,6,0,0,0,0,0,0},//16
{0,6,0,0,6,6,0,0,0,6,0,0,0,0,0,0},//17
{7,7,0,0,7,7,0,0,0,0,0,0,0,0,0,0}//18
};
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);//窗口过程声明
int showgame(HDC);//游戏框架显示
int showhelp(HDC);//显示帮助
int showscore(HDC);//显示分数
int showlevel(HDC);//显示级别
int showbox(HDC,int,int,int);//显示一个方块结构
int erasebox(HDC,int,int,int,int);//擦除一个方块结构
int OnLeft(HDC,int);//左移动处理
int OnRight(HDC,int);//右移动处理
int OnDown(HDC,int);//下降处理
int OnUp(HDC,int&);//变形处理
int CanOnup(int);//变形判断
int Sink(int);//沉底判断
int ShowAll(HDC);//显示全部方块
int putdata(int);//将沉底方块写入主板
int deal_full();//满行处理
int check_full();//检查是否满行
int CanDown(int);//下落检查
int CanLeft(int);//
int CanRight(int);
int set_empty(int);//将该行置空
int showpause(HDC);
int showversion(HDC);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR CmdLine,int nCmdShow)
{
char classname[10]="brick";//窗口类名
char wndname[20] ="俄罗斯方块";//窗口标题
WNDCLASS wnd;//定义一个窗口类
wnd.cbClsExtra = 0;
wnd.cbWndExtra = 0;
wnd.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//背景画刷
wnd.hCursor = LoadCursor(NULL,IDC_ARROW);//鼠标样式
wnd.hIcon = LoadIcon(NULL,IDI_APPLICATION);//图标
wnd.lpfnWndProc = WndProc;//窗口过程
wnd.hInstance = hInstance;//窗口实例
wnd.lpszClassName = classname;//窗口类名
wnd.lpszMenuName = NULL;//菜单名
wnd.style = CS_VREDRAW|CS_HREDRAW;//窗口样式
if(!RegisterClass(&wnd))//注册窗口
{
MessageBox(NULL,"注册失败!","提示",MB_ICONWARNING);
return 0;//不成功便返回
}
HWND hwnd;
hwnd=CreateWindow(
classname,
wndname,
WS_OVERLAPPEDWINDOW^WS_MAXIMIZEBOX^WS_THICKFRAME,//不可调大小
50,
50,
350,
430,
NULL,
NULL,
hInstance,
NULL);
if(hwnd==NULL)
{
MessageBox(NULL,"创建窗口失败!","提示",MB_ICONWARNING);//创建失败直接返回
return 0;
}
ShowWindow(hwnd,nCmdShow);//显示窗口
UpdateWindow(hwnd);//更新窗口
MSG msg;//消息定义
while(GetMessage(&msg,NULL,0,0))//消息循环
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
static int n=0;
HDC hdc;
PAINTSTRUCT ps;
if(!gameover)
switch(message)
{
case WM_CREATE:
int i;
for(i=0;i<14;i++)
board[20][i]=1;//墙底设1
for(i=0;i<21;i++)//两侧的墙设1
{
board[i][0]=1;
board[i][13]=1;
}
SetTimer(hwnd,ID_TIMER,900,NULL);//设置计时器
srand(time(NULL));
cur_box=rand()%NUMBOX;
next_box=rand()%NUMBOX;
g_hWnd = hwnd;
return 0;
case WM_PAINT:
hdc= BeginPaint(hwnd,&ps);
ShowAll(hdc);//显示游戏区中的方块
showgame(hdc);//界面
showhelp(hdc);//帮助
showscore(hdc);//分数
showlevel(hdc);//级别
showpause(hdc);//运行状态
showversion(hdc);//作者信息
showbox(hdc,cur_x,cur_y,cur_box);//显示当前方块
showbox(hdc,260,60,next_box);//显示下一方块
EndPaint(hwnd,&ps);
return 0;
case WM_KEYDOWN:
hdc=GetDC(hwnd);
switch(wParam)
{
case VK_UP:if(!pause)OnUp(hdc,cur_box);return 0;
case VK_DOWN:if(!pause&&!blay)OnDown(hdc,cur_box);return 0;//这里下降落底的时候会有点延时,要判断下
case VK_LEFT:if(!pause)OnLeft(hdc,cur_box);return 0;
case VK_RIGHT:if(!pause)OnRight(hdc,cur_box);return 0;
case VK_SPACE:pause=!pause;InvalidateRect(hwnd,&rcPause,TRUE);return 0;
}
ReleaseDC(hwnd,hdc);
return 0;
case WM_TIMER:
if(!pause&&wParam==ID_TIMER)
{
hdc=GetDC(hwnd);
OnDown(hdc,cur_box);
ReleaseDC(hwnd,hdc);
}
else if(wParam==ID_TIMERLAY)
{
SendMessage(hwnd,WM_BOXSINK,0,0);
blay = FALSE;
KillTimer(hwnd,ID_TIMERLAY);
}
return 0;
case WM_BOXSINK:
if(!pause)
{
putdata(cur_box);//写入数据
deal_full();//处理满行
SetTimer(hwnd,ID_TIMER,900-level*150,NULL);//下落速度控制
cur_box=next_box;
next_box=rand()%NUMBOX;//得到下一方块
cur_x=100;//位置重置
cur_y=0;//
InvalidateRect(hwnd,&rcNext,TRUE);
InvalidateRect(hwnd,&rcStart,TRUE);
}
return 0;
case WM_GAMEOVER:
{
KillTimer(hwnd,ID_TIMER);
if(IDOK==MessageBox(hwnd,"游戏结束","提示",MB_OK))
PostQuitMessage(0);//发送退出消息
}
return 0;
case WM_DESTROY:
KillTimer(hwnd,ID_TIMER);//销毁计时器
PostQuitMessage(0);//发送退出消息
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);//默认窗口处理函数
}
int showgame(HDC hdc)
{
HPEN pen=CreatePen(PS_SOLID,2,RGB(0,0,255));
SelectObject(hdc,pen);
int i;
for(i = 0 ; i <= HEIGHT ; i++)
{
MoveToEx(hdc , TOP , i * ITEMSIZE , NULL);
LineTo(hdc , ITEMSIZE * WIDTH , i * ITEMSIZE);//横线
}
for(i = 0 ; i <= WIDTH ; i++)
{
MoveToEx(hdc , i * ITEMSIZE , TOP ,NULL);
LineTo(hdc , i * ITEMSIZE , BOTTOM);//竖线
}
for( i = 0 ; i <= 4 ; i++ )
{
MoveToEx(hdc , 260 + i * ITEMSIZE , 60 , NULL);
LineTo(hdc , 260 + i * ITEMSIZE , 140);
MoveToEx(hdc , 260 , 60 + i * ITEMSIZE , NULL);
LineTo(hdc , 340 , 60 + i * ITEMSIZE);
}
SetTextColor(hdc,RGB(255,0,0));
TextOut(hdc,270,40,"下一方块",8);
SetTextColor(hdc,RGB(0,0,0));
DeleteObject(pen);
return 0;
}
int showhelp(HDC hdc)
{
SetTextColor(hdc,RGB(0,0,255));
TextOut(hdc,260,142,"旋转 ↑",strlen("上移 ↑"));
TextOut(hdc,260,160,"下移 ↓",strlen("下移 ↓"));
TextOut(hdc,260,180,"左移 ←",strlen("左移 ←"));
TextOut(hdc,260,200,"右移 →",strlen("右移 →"));
TextOut(hdc,260,220,"暂停 空格键",strlen("暂停 空格键"));
return 0;
}
int showscore(HDC hdc)
{
SetTextColor(hdc,RGB(255,0,255));
char str_score[10];
itoa(score,str_score,10);//转换为文本
TextOut(hdc,260,240,"分数",4);
TextOut(hdc,300,240,str_score,strlen(str_score));
return 0;
}
int showlevel(HDC hdc)
{
SetTextColor(hdc,RGB(255,0,255));
char str_level[4];
itoa(level,str_level,10);
TextOut(hdc,260,260,"级别",4);
TextOut(hdc,300,260,str_level,strlen(str_level));
return 0;
}
int showpause(HDC hdc)
{
SetTextColor(hdc,RGB(255,0,0));
if(pause)
TextOut(hdc,260,280,"已暂停",6);
else TextOut(hdc,260,280,"正在运行",8);
return 1;
}
int showversion(HDC hdc)
{
SetTextColor(hdc,RGB(255,0,0));
TextOut(hdc,260,300,"**制作",8);
return 0;
}
int showbox(HDC hdc,int x,int y,int num)//在xy处显示方块
{
int i,j;
HPEN pen=CreatePen(PS_SOLID|PS_INSIDEFRAME,1,RGB(0,0,255));//创建画笔
HBRUSH brush=CreateSolidBrush(RGB(114,71,164));//创建画刷
SelectObject(hdc,brush);//选进设备
SelectObject(hdc,pen);//选进设备
for(i=0;i<4;i++)//如果对应方块信息不为0就显示画图
for(j=0;j<4;j++)
{
if(box[num][i][j]!=0)
{
Rectangle(hdc,x+j*ITEMSIZE,y+i*ITEMSIZE,x+j*ITEMSIZE+ITEMSIZE,y+i*ITEMSIZE+ITEMSIZE);//显示方块
}
}
DeleteObject(brush);//删除画刷
DeleteObject(pen);//删除画笔
return 0;//返回0值
}
int erasebox(HDC hdc,int x,int y,int num)//擦掉xy处的方块
{
int i,j;//意思同上,只是画刷不同
HBRUSH brush=CreateSolidBrush(RGB(255,255,255));
SelectObject(hdc,brush);
HPEN pen=CreatePen(PS_SOLID|PS_INSIDEFRAME,1,RGB(0,0,255));
SelectObject(hdc,pen);
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
if(box[num][i][j]!=0)
{
Rectangle(hdc,x+j*ITEMSIZE,y+i*ITEMSIZE,x+j*ITEMSIZE+ITEMSIZE,y+i*ITEMSIZE+ITEMSIZE);
}
}
DeleteObject(brush);
DeleteObject(pen);
return 0;
}
int CanLeft(int num)
{
int i,j,key=1;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(box[num][i][j]!=0)
if(board[cur_y/ITEMSIZE+i][(cur_x+j*ITEMSIZE)/ITEMSIZE]==1)
return 0;
return 1;
}
int OnLeft(HDC hdc,int num)//当前方块左移动处理
{
if(CanLeft(num))
{
erasebox(hdc,cur_x,cur_y,num);
cur_x-=ITEMSIZE;
showbox(hdc,cur_x,cur_y,num);
}
return 0;
}
int CanRight(int num)
{
int i,j,key=1;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(box[num][i][j]!=0)
if(board[cur_y/ITEMSIZE+i][(cur_x+j*ITEMSIZE)/ITEMSIZE+2]==1)
return 0;
return 1;
}
int OnRight(HDC hdc,int num)//当前方块右移处理
{
if(CanRight(num))
{
erasebox(hdc,cur_x,cur_y,num);
cur_x +=ITEMSIZE;
showbox(hdc,cur_x,cur_y,num);
}
return 0;
}
int CanDown(int num)
{
int i,j,key=1;
for(j=0;j<4;j++)
for(i=3;i>=0;i--)
if(box[num][i][j]!=0)
if(board[cur_y/ITEMSIZE+i+1][(cur_x+j*ITEMSIZE)/ITEMSIZE+1]==1)
return 0;
return 1;
}
int OnDown(HDC hdc,int num)//当前方块下落处理
{
int nRet = CanDown(num);
if(nRet==1)
{
erasebox(hdc,cur_x,cur_y,num);
cur_y+=20;
showbox(hdc,cur_x,cur_y,num);
}
//不能下降了,发送游戏结束消息
else if(nRet==0)
{
SendMessage(g_hWnd,WM_GAMEOVER,0,0);
return 0;
}
//这里会有一点点的延时,
if(Sink(num))
{
blay = TRUE;
SetTimer(g_hWnd,ID_TIMERLAY,200,NULL);
KillTimer(g_hWnd,ID_TIMER);
}
return 0;
}
int CanOnup(int num)
{
int i,j;
int key=1;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(box[num][i][j]!=0)
{
if(board[cur_y/ITEMSIZE+i][cur_x/ITEMSIZE+j+1]==1)
{
key=0;
break;
}
}
return key;
}
int OnUp(HDC hdc,int &num)//变形处理
{
int next_box=0;//这里这个是局部的
switch(num)
{
case 0:next_box=1;break;
case 1:next_box=0;break;
case 2:next_box=3;break;
case 3:next_box=4;break;
case 4:next_box=5;break;
case 5:next_box=2;break;
case 6:next_box=7;break;
case 7:next_box=8;break;
case 8:next_box=9;break;
case 9:next_box=6;break;
case 10:next_box=11;break;
case 11:next_box=10;break;
case 12:next_box=13;break;
case 13:next_box=12;break;
case 14:next_box=15;break;
case 15:next_box=16;break;
case 16:next_box=17;break;
case 17:next_box=14;break;
case 18:next_box=18;break;
}
if(CanOnup(next_box))
{
erasebox(hdc,cur_x,cur_y,num);
num=next_box;
showbox(hdc,cur_x,cur_y,num);
}
return 0;
}
//是否下沉了
int Sink(int num)
{
int i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(box[num][i][j]!=0)
if(board[cur_y/ITEMSIZE+i+1][cur_x/ITEMSIZE+j+1]==1)
return 1;
return 0;
}
//将下沉的方块写进游戏数组里面
int putdata(int num)
{
int i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(box[num][i][j]!=0)
board[cur_y/ITEMSIZE+i][cur_x/ITEMSIZE+j+1]=1;
return 1;
}
int ShowAll(HDC hdc)
{
HBRUSH brush=CreateSolidBrush(RGB(114,71,164));
HPEN pen=CreatePen(PS_SOLID,1,RGB(0,0,255));
SelectObject(hdc,pen);
SelectObject(hdc,brush);
int i,j;
for(i=0;i<HEIGHT;i++)
for(j=1;j<=WIDTH;j++)
if(board[i][j]==1)
Rectangle(hdc,(j-1)*20,i*20,(j-1)*20+20,i*20+20);
DeleteObject(pen);
DeleteObject(brush);
return 1;
}
int check_full(int i)//检查i行是否满行[0-20] 满行 返回1
{
int j;
for(j=1;j<=WIDTH;j++)
if(board[i][j]==0)
return 0;
return 1;
}
int set_empty(int i)//置空
{
int j;
for(j=1;j<=WIDTH;j++)
board[i][j]=0;
return 1;
}
int deal_fall(int i)//i为空行,下落处理,下落
{
int k,j;
for(k=i;k>=1;k--)
for(j=1;j<=WIDTH;j++)
{
board[k][j]=board[k-1][j];
}
return 1;
}
int deal_full()//处理满行
{
int i;
int n=0;
for(i=19;i>=0;i--)
{
if(check_full(i))//找到了
{
set_empty(i);//将这行置空
deal_fall(i);//上面的下移
n++;//记数
i++;//i重置,这里主要是因为有多行存在满行的情况
}
}
switch(n)
{
case 1:score+=100;break;
case 2:score+=300;break;
case 3:score+=500;break;
case 4:score+=700;break;
}
if(n)
{
level=score/1000+1;
InvalidateRect(g_hWnd,NULL,TRUE);
}
return 0;
}