俄罗斯方块.docx
《俄罗斯方块.docx》由会员分享,可在线阅读,更多相关《俄罗斯方块.docx(18页珍藏版)》请在冰点文库上搜索。
![俄罗斯方块.docx](https://file1.bingdoc.com/fileroot1/2023-8/5/6ec97cae-05e1-4531-8bb9-c8657c5ad732/6ec97cae-05e1-4531-8bb9-c8657c5ad7321.gif)
俄罗斯方块
俄罗斯方块(Tetris)VC源代码
0
作者:
krissi
童年的经典游戏~~ 。
界面上没有做额外的修饰,需要的可以自己增加。
执行效果如下:
代码如下:
////////////////////////////////////////////
//程序名称:
俄罗斯方块
//编译环境:
VisualC++6.0/2010,EasyX_v20130322(beta)
//程序编写:
krissi
//更新记录:
2010-12-18zhaoh1987@编写
// 2011-9-28yw80@修改了下落超时的逻辑
//
#include
#include
#include
/////////////////////////////////////////////
//定义常量、枚举量、结构体、全局变量
/////////////////////////////////////////////
#defineWIDTH10//游戏区宽度
#defineHEIGHT22//游戏区高度
#defineSIZE20//每个游戏区单位的实际像素
//定义操作类型
enumCMD
{
CMD_ROTATE,//方块旋转
CMD_LEFT,CMD_RIGHT,CMD_DOWN,//方块左、右、下移动
CMD_SINK,//方块沉底
CMD_QUIT//退出游戏
};
//定义绘制方块的方法
enumDRAW
{
SHOW,//显示方块
HIDE,//隐藏方块
FIX//固定方块
};
//定义七种俄罗斯方块
structBLOCK
{
WORDdir[4];//方块的四个旋转状态
COLORREFcolor;//方块的颜色
}g_Blocks[7]={{0x0F00,0x4444,0x0F00,0x4444,RED},//I
{0x0660,0x0660,0x0660,0x0660,BLUE},//口
{0x4460,0x02E0,0x0622,0x0740,MAGENTA},//L
{0x2260,0x0E20,0x0644,0x0470,YELLOW},//反L
{0x0C60,0x2640,0x0C60,0x2640,CYAN},//Z
{0x0360,0x4620,0x0360,0x4620,GREEN},//反Z
{0x4E00,0x4C40,0x0E40,0x4640,BROWN}};//T
//定义当前方块、下一个方块的信息
structBLOCKINFO
{
byteid;//方块ID
charx,y;//方块在游戏区中的坐标
bytedir:
2;//方向
}g_CurBlock,g_NextBlock;
//定义游戏区
BYTEg_World[WIDTH][HEIGHT]={0};
/////////////////////////////////////////////
//函数声明
/////////////////////////////////////////////
voidInit();//初始化游戏
voidQuit();//退出游戏
voidNewGame();//开始新游戏
voidGameOver();//结束游戏
CMDGetCmd();//获取控制命令
voidDispatchCmd(CMD_cmd);//分发控制命令
voidNewBlock();//生成新的方块
boolCheckBlock(BLOCKINFO_block);//检测指定方块是否可以放下
voidDrawBlock(BLOCKINFO_block,DRAW_draw=SHOW);//画方块
voidOnRotate();//旋转方块
voidOnLeft();//左移方块
voidOnRight();//右移方块
voidOnDown();//下移方块
voidOnSink();//沉底方块
/////////////////////////////////////////////
//函数定义
/////////////////////////////////////////////
//主函数
voidmain()
{
Init();
CMDc;
while(true)
{
c=GetCmd();
DispatchCmd(c);
//按退出时,显示对话框咨询用户是否退出
if(c==CMD_QUIT)
{
HWNDwnd=GetHWnd();
if(MessageBox(wnd,_T("您要退出游戏吗?
"),_T("提醒"),MB_OKCANCEL|MB_ICONQUESTION)==IDOK)
Quit();
}
}
}
//初始化游戏
voidInit()
{
initgraph(640,480);
srand((unsigned)time(NULL));
//显示操作说明
setfont(14,0,_T("宋体"));
outtextxy(20,330,_T("操作说明"));
outtextxy(20,350,_T("上:
旋转"));
outtextxy(20,370,_T("左:
左移"));
outtextxy(20,390,_T("右:
右移"));
outtextxy(20,410,_T("下:
下移"));
outtextxy(20,430,_T("空格:
沉底"));
outtextxy(20,450,_T("ESC:
退出"));
//设置坐标原点
setorigin(220,20);
//绘制游戏区边界
rectangle(-1,-1,WIDTH*SIZE,HEIGHT*SIZE);
rectangle((WIDTH+1)*SIZE-1,-1,(WIDTH+5)*SIZE,4*SIZE);
//开始新游戏
NewGame();
}
//退出游戏
voidQuit()
{
closegraph();
exit(0);
}
//开始新游戏
voidNewGame()
{
//清空游戏区
setfillcolor(BLACK);
bar(0,0,WIDTH*SIZE-1,HEIGHT*SIZE-1);
ZeroMemory(g_World,WIDTH*HEIGHT);
//生成下一个方块
g_NextBlock.id=rand()%7;
g_NextBlock.dir=rand()%4;
g_NextBlock.x=WIDTH+1;
g_NextBlock.y=HEIGHT-1;
//获取新方块
NewBlock();
}
//结束游戏
voidGameOver()
{
HWNDwnd=GetHWnd();
if(MessageBox(wnd,_T("游戏结束。
\n您想重新来一局吗?
"),_T("游戏结束"),MB_YESNO|MB_ICONQUESTION)==IDYES)
NewGame();
else
Quit();
}
//获取控制命令
DWORDm_oldtime;
CMDGetCmd()
{
//获取控制值
while(true)
{
//如果超时,自动下落一格
DWORDnewtime=GetTickCount();
if(newtime-m_oldtime>=500)
{
m_oldtime=newtime;
returnCMD_DOWN;
}
//如果有按键,返回按键对应的功能
if(kbhit())
{
switch(getch())
{
case'w':
case'W':
returnCMD_ROTATE;
case'a':
case'A':
returnCMD_LEFT;
case'd':
case'D':
returnCMD_RIGHT;
case's':
case'S':
returnCMD_DOWN;
case27:
returnCMD_QUIT;
case'':
returnCMD_SINK;
case0:
case0xE0:
switch(getch())
{
case72:
returnCMD_ROTATE;
case75:
returnCMD_LEFT;
case77:
returnCMD_RIGHT;
case80:
returnCMD_DOWN;
}
}
}
//延时(降低CPU占用率)
Sleep(20);
}
}
//分发控制命令
voidDispatchCmd(CMD_cmd)
{
switch(_cmd)
{
caseCMD_ROTATE:
OnRotate();break;
caseCMD_LEFT:
OnLeft();break;
caseCMD_RIGHT:
OnRight();break;
caseCMD_DOWN:
OnDown();break;
caseCMD_SINK:
OnSink();break;
caseCMD_QUIT:
break;
}
}
//生成新的方块
voidNewBlock()
{
g_CurBlock.id=g_NextBlock.id,g_NextBlock.id=rand()%7;
g_CurBlock.dir=g_NextBlock.dir,g_NextBlock.dir=rand()%4;
g_CurBlock.x=(WIDTH-4)/2;
g_CurBlock.y=HEIGHT+2;
//下移新方块直到有局部显示
WORDc=g_Blocks[g_CurBlock.id].dir[g_CurBlock.dir];
while((c&0xF)==0)
{
g_CurBlock.y--;
c>>=4;
}
//绘制新方块
DrawBlock(g_CurBlock);
//绘制下一个方块
setfillcolor(BLACK);
bar((WIDTH+1)*SIZE,0,(WIDTH+5)*SIZE-1,4*SIZE-1);
DrawBlock(g_NextBlock);
//设置计时器,用于判断自动下落
m_oldtime=GetTickCount();
}
//画方块
voidDrawBlock(BLOCKINFO_block,DRAW_draw)
{
WORDb=g_Blocks[_block.id].dir[_block.dir];
intx,y;
intcolor=BLACK;
switch(_draw)
{
caseSHOW:
color=g_Blocks[_block.id].color;break;
caseHIDE:
color=BLACK;break;
caseFIX:
BYTEr=GetRValue(g_Blocks[_block.id].color)*2/3;
BYTEg=GetGValue(g_Blocks[_block.id].color)*2/3;
BYTEb=GetBValue(g_Blocks[_block.id].color)*2/3;
color=RGB(r,g,b);
break;
}
setfillcolor(color);
for(inti=0;i<16;i++)
{
if(b&0x8000)
{
x=_block.x+i%4;
y=_block.y-i/4;
if(y{
if(_draw!
=HIDE)
bar3d(x*SIZE+2,(HEIGHT-y-1)*SIZE+2,(x+1)*SIZE-4,(HEIGHT-y)*SIZE-4,3,true);
else
bar(x*SIZE,(HEIGHT-y-1)*SIZE,(x+1)*SIZE-1,(HEIGHT-y)*SIZE-1);
}
}
b<<=1;
}
}
//检测指定方块是否可以放下
boolCheckBlock(BLOCKINFO_block)
{
WORDb=g_Blocks[_block.id].dir[_block.dir];
intx,y;
for(inti=0;i<16;i++)
{
if(b&0x8000)
{
x=_block.x+i%4;
y=_block.y-i/4;
if((x<0)||(x>=WIDTH)||(y<0))
returnfalse;
if((yreturnfalse;
}
b<<=1;
}
returntrue;
}
//旋转方块
voidOnRotate()
{
//获取可以旋转的x偏移量
intdx;
BLOCKINFOtmp=g_CurBlock;
tmp.dir++;if(CheckBlock(tmp)){dx=0;gotorotate;}
tmp.x=g_CurBlock.x-1;if(CheckBlock(tmp)){dx=-1;gotorotate;}
tmp.x=g_CurBlock.x+1;if(CheckBlock(tmp)){dx=1;gotorotate;}
tmp.x=g_CurBlock.x-2;if(CheckBlock(tmp)){dx=-2;gotorotate;}
tmp.x=g_CurBlock.x+2;if(CheckBlock(tmp)){dx=2;gotorotate;}
return;
rotate:
//旋转
DrawBlock(g_CurBlock,HIDE);
g_CurBlock.dir++;
g_CurBlock.x+=dx;
DrawBlock(g_CurBlock);
}
//左移方块
voidOnLeft()
{
BLOCKINFOtmp=g_CurBlock;
tmp.x--;
if(CheckBlock(tmp))
{
DrawBlock(g_CurBlock,HIDE);
g_CurBlock.x--;
DrawBlock(g_CurBlock);
}
}
//右移方块
voidOnRight()
{
BLOCKINFOtmp=g_CurBlock;
tmp.x++;
if(CheckBlock(tmp))
{
DrawBlock(g_CurBlock,HIDE);
g_CurBlock.x++;
DrawBlock(g_CurBlock);
}
}
//下移方块
voidOnDown()
{
BLOCKINFOtmp=g_CurBlock;
tmp.y--;
if(CheckBlock(tmp))
{
DrawBlock(g_CurBlock,HIDE);
g_CurBlock.y--;
DrawBlock(g_CurBlock);
}
else
OnSink();//不可下移时,执行“沉底方块”操作
}
//沉底方块
voidOnSink()
{
inti,x,y;
//连续下移方块
DrawBlock(g_CurBlock,HIDE);
BLOCKINFOtmp=g_CurBlock;
tmp.y--;
while(CheckBlock(tmp))
{
g_CurBlock.y--;
tmp.y--;
}
DrawBlock(g_CurBlock,FIX);
//固定方块在游戏区
WORDb=g_Blocks[g_CurBlock.id].dir[g_CurBlock.dir];
for(i=0;i<16;i++)
{
if(b&0x8000)
{
if(g_CurBlock.y-i/4>=HEIGHT)
{//如果方块的固定位置超出高度,结束游戏
GameOver();
return;
}
else
g_World[g_CurBlock.x+i%4][g_CurBlock.y-i/4]=1;
}
b<<=1;
}
//检查是否需要消掉行,并标记
introw[4]={0};
boolbRow=false;
for(y=g_CurBlock.y;y>=max(g_CurBlock.y-3,0);y--)
{
i=0;
for(x=0;xif(g_World[x][y]==1)
i++;
if(i==WIDTH)
{
bRow=true;
row[g_CurBlock.y-y]=1;
setfillcolor(WHITE);
setfillstyle(DIAGCROSS2_FILL);
bar(0,(HEIGHT-y-1)*SIZE+SIZE/2-2,WIDTH*SIZE-1,(HEIGHT-y-1)*SIZE+SIZE/2+2);
setfillstyle(SOLID_FILL);
}
}
if(bRow)
{
//延时200毫秒
Sleep(200);
//擦掉刚才标记的行
IMAGEimg;
for(i=0;i<4;i++)
{
if(row[i])
{
for(y=g_CurBlock.y-i+1;yfor(x=0;x{
g_World[x][y-1]=g_World[x][y];
g_World[x][y]=0;
}
getimage(&img,0,0,WIDTH*SIZE,(HEIGHT-(g_CurBlock.y-i+1))*SIZE);
putimage(0,SIZE,&img);
}
}
}
//产生新方块
NewBlock();
}