c俄罗斯方块源码思路(c++做俄罗斯方块代码)
本文目录一览:
怎样用c语言编写俄罗斯方块程序?
俄罗斯方块C源代码
#include stdio.h
#include windows.h
#include conio.h
#include time.h
#define ZL 4 //坐标增量, 不使游戏窗口靠边
#define WID 36 //游戏窗口的宽度
#define HEI 20 //游戏窗口的高度
int i,j,Ta,Tb,Tc; // Ta,Tb,Tc用于记住和转换方块变量的值
int a[60][60]={0}; //标记游戏屏幕各坐标点:0,1,2分别为空、方块、边框
int b[4]; //标记4个"口"方块:1有,0无,类似开关
int x,y, level,score,speed; //方块中心位置的x,y坐标,游戏等级、得分和游戏速度
int flag,next; //当前要操作的方块类型序号,下一个方块类型序号
void gtxy(int m, int n); //以下声明要用到的自编函数
void gflag( ); //获得下一方块序号
void csh( ); //初始化界面
void start( ); //开始部分
void prfk ( ); //打印方块
void clfk( ); //清除方块
void mkfk( ); //制作方块
void keyD( ); //按键操作
int ifmov( ); //判断方块能否移动或变体
void clHA( ); //清除满行的方块
void clNEXT( ); //清除边框外的NEXT方块
int main( )
{ csh( );
while(1)
{start( ); //开始部分
while(1)
{ prfk( );
Sleep(speed); //延时
clfk( );
Tb=x;Tc=flag; //临存当前x坐标和序号,以备撤销操作
keyD( );
y++; //方块向下移动
if (ifmov( )==0) { y--; prfk( ); dlHA( ); break;} //不可动放下,删行,跨出循环
for(i=y-2;iy+2;i++){ if (i==ZL) { j=0; } } //方块触到框顶
if (j==0) { system("cls");gtxy(10,10);printf("游戏结束!"); getch(); break; }
clNEXT( ); //清除框外的NEXT方块
return 0;
void gtxy(int m, int n) //控制光标移动
{COORD pos; //定义变量
pos.X = m; //横坐标
pos.Y = n; //纵坐标
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
void csh( ) //初始化界面
{gtxy(ZL+WID/2-5,ZL-2); printf("俄罗斯方块"); //打印游戏名称
gtxy(ZL+WID+3,ZL+7); printf("******* NEXT:"); //打印菜单信息
gtxy(ZL+WID+3,ZL+13); printf("**********");
gtxy(ZL+WID+3,ZL+15); printf("Esc :退出游戏");
gtxy(ZL+WID+3,ZL+17); printf("↑键:变体");
gtxy(ZL+WID+3,ZL+19); printf("空格:暂停游戏");
gtxy(ZL,ZL); printf("╔"); gtxy(ZL+WID-2,ZL); printf("╗"); //打印框角
gtxy(ZL,ZL+HEI); printf("╚"); gtxy(ZL+WID-2,ZL+HEI); printf("╝");
a[ZL][ZL+HEI]=2; a[ZL+WID-2][ZL+HEI]=2; //记住有图案
for(i=2;iWID-2;i+=2) {gtxy(ZL+i,ZL); printf("═"); } //打印上横框
for(i=2;iWID-2;i+=2) {gtxy(ZL+i,ZL+HEI); printf("═"); a[ZL+i][ZL+HEI]=2; } //下框
for(i=1;iHEI;i++) { gtxy(ZL,ZL+i); printf("║"); a[ZL][ZL+i]=2; } //左竖框记住有图案
for(i=1;iHEI;i++) {gtxy(ZL+WID-2,ZL+i); printf("║"); a[ZL+WID-2][ZL+i]=2; } //右框
CONSOLE_CURSOR_INFO cursor_info={1,0}; //以下是隐藏光标的设置
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),cursor_info);
level=1; score=0; speed=400;
gflag( ); flag=next; //获得一个当前方块序号
void gflag( ) //获得下一个方块的序号
{ srand((unsigned)time(NULL)); next = rand()%19+1; }
void start( ) //开始部分
{ gflag( ); Ta=flag; flag=next; //保存当前方块序号,将下一方块序号临时操作
x=ZL+WID+6; y=ZL+10; prfk( ); //给x,y赋值,在框外打印出下一方块
flag=Ta; x=ZL+WID/2; y=ZL-1; //取回当前方块序号,并给x,y赋值
void prfk ( ) //打印俄罗斯方块
{ for(i=0;i4;i++) {b[i]=1; } //数组b[4]每个元素的值都为1
mkfk ( ); //制作俄罗斯方块
for( i= x-2; i=x+4; i+=2 ) //打印方块
{ for(j=y-2;j= y+1;j++) { if( a[i][j]==1 jZL ){ gtxy(i,j); printf("□"); } } }
gtxy(ZL+WID+3,ZL+1); printf("level : %d",level); //以下打印菜单信息
gtxy(ZL+WID+3,ZL+3); printf("score : %d",score);
gtxy(ZL+WID+3,ZL+5); printf("speed : %d",speed);
void clfk( ) //清除俄罗斯方块
{ for(i=0;i4;i++) { b[i]=0; } //数组b[4]每个元素的值都为0
mkfk ( ); //制作俄罗斯方块
for( i=x-2; i=x+4; i+=2 ) //清除方块
{ for(j=y-2;j=y+1;j++){ if( a[i][j]==0 jZL ){ gtxy(i,j); printf(" "); } } }
void mkfk( ) //制作俄罗斯方块
{ a[x][ y]=b[0]; //方块中心位置状态: 1-有,0-无
switch(flag) //共6大类,19种小类型
{ case 1: { a[x][y-1]=b[1]; a[x+2][y-1]=b[2]; a[x+2][y]=b[3]; break; } //田字方块
case 2: { a[x-2][y]=b[1]; a[x+2][y]=b[2]; a[x+4][y]=b[3]; break; } //直线方块:----
case 3: { a[x][y-1]=b[1]; a[x][y-2]=b[2]; a[x][y+1]=b[3]; break; } //直线方块: |
case 4: { a[x-2][y]=b[1]; a[x+2][y]=b[2]; a[x][y+1]=b[3]; break; } //T字方块
case 5: { a[x][y-1]=b[1]; a[x][y+1]=b[2]; a[x-2][y]=b[3]; break; } //T字顺时针转90度
case 6: { a[x][y-1]=b[1]; a[x-2][y]=b[2]; a[x+2][y]=b[3]; break; } //T字顺转180度
case 7: { a[x][y-1]=b[1]; a[x][y+1]=b[2]; a[x+2][y]=b[3]; break; } //T字顺转270度
case 8: { a[x][y+1]=b[1]; a[x-2][y]=b[2]; a[x+2][y+1]=b[3]; break; } //Z字方块
case 9: { a[x][y-1]=b[1]; a[x-2][y]=b[2]; a[x-2][y+1]=b[3]; break; } //Z字顺转90度
case 10: { a[x][y-1]=b[1]; a[x-2][y-1]=b[2]; a[x+2][y]=b[3]; break; } //Z字顺转180度
case 11: { a[x][y+1]=b[1]; a[x+2][y-1]=b[2]; a[x+2][ y]=b[3]; break; } //Z字顺转270度
case 12: { a[x][y-1]=b[1]; a[x][y+1]=b[2]; a[x-2][y-1]=b[3]; break; } //7字方块
case 13: {a[x-2][y]=b[1]; a[x+2][y-1]=b[2]; a[x+2][y]=b[3]; break; } //7字顺转90度
case 14: { a[x][y-1]=b[1]; a[x][y+1]=b[2]; a[x+2][y+1]=b[3]; break; } //7字顺转180度
case 15: { a[x-2][y]=b[1]; a[x-2][y+1]=b[2]; a[x+2][y]=b[3]; break; } //7字顺转270度
case 16: { a[x][y+1]=b[1]; a[x][y-1]=b[2]; a[x+2][y-1]=b[3]; break; } //倒7字方块
case 17: { a[x-2][y]=b[1]; a[x+2][y+1]=b[2]; a[x+2][y]=b[3]; break; } //倒7字顺转90度
case 18: { a[x][y-1]=b[1]; a[x][y+1]=b[2]; a[x-2][y+1]=b[3]; break; } //倒7字顺转180度
case 19: { a[x-2][y]=b[1]; a[x-2][y-1]=b[2]; a[x+2][y]=b[3]; break; } //倒7字顺转270度
void keyD( ) //按键操作
{ if (kbhit( ))
{ int key;
key=getch();
if (key==224)
{ key=getch();
if (key==75) { x-=2; } //按下左方向键,中心横坐标减2
if (key==77) { x+=2; } //按下右方向键,中心横坐标加2
if (key==72) //按下向上方向键,方块变体
{ if (flag=2 flag=3 ) { flag++; flag%=2; flag+=2; }
if ( flag=4 flag=7 ) { flag++; flag%=4; flag+=4; }
if (flag=8 flag=11 ) { flag++; flag%=4; flag+=8; }
if (flag=12 flag=15 ) { flag++; flag%=4; flag+=12; }
if ( flag=16 flag=19 ) { flag++; flag%=4; flag+=16; } }
if (key==32) //按空格键,暂停
{ prfk( ); while(1) { if (getch( )==32) { clfk( );break;} } } //再按空格键,继续游戏
if (ifmov( )==0) { x=Tb; flag=Tc; } //如果不可动,撤销上面操作
else { prfk( ); Sleep(speed); clfk( ); Tb=x;Tc=flag;} //如果可动,执行操作
int ifmov( ) //判断能否移动
{ if (a[x][y]!=0) { return 0; } //方块中心处有图案返回0,不可移动
else{ if ( (flag==1 ( a[x][ y-1]==0 a[x+2][y-1]==0 a[x+2][y]==0 ) ) ||
(flag==2 ( a[x-2][y]==0 a[x+2][y]==0 a[x+4][y]==0 ) ) ||
(flag==3 ( a[x][y-1]==0 a[x][y-2]==0 a[x][y+1]==0 ) ) ||
(flag==4 ( a[x-2][y]==0 a[x+2][y]==0 a[x][y+1]==0 ) ) ||
(flag==5 ( a[x][y-1]==0 a[x][y+1]==0 a[x-2][y]==0 ) ) ||
(flag==6 ( a[x][ y-1]==0 a[x-2][y]==0 a[x+2][y]==0 ) ) ||
(flag==7 ( a[x][y-1]==0 a[x][y+1]==0 a[x+2][y]==0 ) ) ||
(flag==8 ( a[x][y+1]==0 a[x-2][y]==0 a[x+2][y+1]==0 ) ) ||
(flag==9 ( a[x][y-1]==0 a[x-2][y]==0 a[x-2][y+1]==0 ) ) ||
(flag==10 ( a[x][y-1]==0 a[x-2][y-1]==0 a[x+2][y]==0 ) ) ||
(flag==11 ( a[x][y+1]==0 a[x+2][y-1]==0 a[x+2][y]==0 ) ) ||
(flag==12 ( a[x][y-1]==0 a[x][y+1]==0 a[x-2][y-1]==0 ) ) ||
( flag==13 ( a[x-2][y]==0 a[x+2][y-1]==0 a[x+2][y]==0 ) ) ||
( flag==14 ( a[x][y-1]==0 a[x][y+1]==0 a[x+2][y+1]==0 ) ) ||
(flag==15 ( a[x-2][y]==0 a[x-2][y+1]==0 a[x+2][y]==0 ) ) ||
(flag==16 ( a[x][y+1]==0 a[x][y-1]==0 a[x+2][y-1]==0 ) ) ||
( flag==17 ( a[x-2][y]==0 a[x+2][y+1]==0 a[x+2][y]==0 ) ) ||
(flag==18 ( a[x][y-1]==0 a[x][y+1]==0 a[x-2][y+1]==0 ) ) ||
(flag==19 ( a[x-2][y]==0 a[x-2][y-1]==0
a[x+2][y]==0 ) ) ) { return 1; }
return 0; //其它情况返回0
void clNEXT( ) //清除框外的NEXT方块
{ flag = next; x=ZL+WID+6; y=ZL+10; clfk( ); }
void clHA( ) //清除满行的方块
{ int k, Hang=0; //k是某行方块个数, Hang是删除的方块行数
for(j=ZL+HEI-1;j=ZL+1;j--) //当某行有WID/2-2个方块时,则为满行
{ k=0; for(i=ZL+2;iZL+WID-2;i+=2)
{ if (a[i][j]==1) //竖坐标从下往上,横坐标由左至右依次判断是否满行
{ k++; //下面将操作删除行
if (k==WID/2-2) { for(k=ZL+2;kZL+WID-2;k+=2)
{ a[k][j]=0; gtxy(k,j); printf(" "); Sleep(1); }
for(k=j-1;kZL;k--)
{ for(i=ZL+2;iZL+WID-2;i+=2) //已删行数上面有方块,先清除再全部下移一行
{ if(a[i][k]==1) { a[i][k]=0; gtxy(i,k); printf(" ");a[i][k+1]=1;
gtxy(i,k+1); printf("□"); } }
j++; //方块下移后,重新判断删除行是否满行
Hang++; //记录删除方块的行数
score+=100*Hang; //每删除一行,得100分
if ( Hang0 (score%500==0 || score/500 level-1 ) ) //得分满500速度加快升一级
{ speed-=20; level++; if(speed200)speed+=20; }
C语言代码俄罗斯方块(yCodeBlocks)?
#include "mywindows.h"
HANDLE handle;
// 初始化句柄
void initHandle()
handle = GetStdHandle(STD_OUTPUT_HANDLE);
// 设置颜色
void setColor(int color)
SetConsoleTextAttribute(handle, color);
void setPos(int x, int y)
COORD coord = {x*2, y};
SetConsoleCursorPosition(handle, coord);
// 设置光标是否可见
void setCursorVisible(int flag)
CONSOLE_CURSOR_INFO info;
info.bVisible = flag; //光标是否可见
info.dwSize = 100; //光标宽度1-100
SetConsoleCursorInfo(handle, info);
// 关闭句柄
void closeHandle()
CloseHandle(handle);
求俄罗斯方块C语言设计思路
最基础就是二维数组做c俄罗斯方块源码思路,当某一行满的时候删除这一行c俄罗斯方块源码思路,固定形状从a[0][0]开始定义c俄罗斯方块源码思路,完了自己隔一秒变一次二维c俄罗斯方块源码思路,也就是
a[1][0],怎么变换也事先写好对应数组哪个位置,应该就是这样吧
用c语言编写俄罗斯方块程序 求详解
在写一个程序之前得先有思路,本题中得思路是:
随机给出不同的形状(长条形、Z字形、反Z形、田字形、7字形、反7形、T字型)下落填充给定的区域,若填满一条便消掉,记分,当达到一定的分数时,过关,每关方块下落的速度不同,若在游戏中各形状填满了给定区域,为输者。
有了思路再动手,如果不会可以参考一下别人开源的项目!
因为项目复杂性,我给出了一个俄罗斯方块程序的项目地址在最后,祝您好运!
项目地址:俄罗斯方块游戏
谁能大致描述一下C语言做俄罗斯方块的思想
#include stdlib.h /*标准库*/
#include graphics.h /*绘图库*/
#include bios.h /*BIOS库c俄罗斯方块源码思路,输入输出c俄罗斯方块源码思路,BIOS时间等*/
#define mDRAW 5 /*各种消息的宏定义*/
#define mLINE 6
#define mADOWN 7
#define mGEN 8
#define mLEFT 75
#define mRIGHT 77
#define mSPACE 57
#define mDOWN 80
#define mESC 1
#define TIMEINT 2 //下落间隔时间c俄罗斯方块源码思路,即下落速度
#define MAXX 9 /*行列数,9×30的区域*/
#define MAXY 30
#define BACKCOLOR BLACK /*背景色*/
#define WINX 50 //游戏box所在的位置,单位为像素,下同
#define WINY 470
#define GAP 6 //间隙宽度
#define AREAX (WINX+GAP)
#define AREAY (WINY-GAP)
#define BOXW 15 //每一小格的宽度
int oldarea[MAXY+1][MAXX]; //为和当前游戏区域进行比较而保存的上一游戏区域信息
int area[MAXY+1][MAXX]; //游戏区域的方块信息,有方块计1,否则计0.
int actW,actH,actX,actY; //方块可活动的X、Y、宽、高信息
int curX,curY,curColor,curW,curH; //方块当前的X、Y、宽、高、颜色信息
int newX,newY,newColor,newW,newH; //方块新的(或称为接受控制消息后计算出的下一状态的)X、Y、宽、高、颜色信息
int active; //游戏是否处于active状态
int box[4][4]; /*方块的二维数组,定义当前方块*/
int FORCOLOR; /*前景色*/
int MESSAGE; //方块位置控制消息
int BOX[7][4][4]={ /*7个不同的方块定义成4×4的数组,可以看成产生方块的模板*/
{1,1,1,1}, /*直棍*/
{0,0,0,0},
{0,0,0,0},
{0,0,0,0}
{1,1,1,0},/*右弯*/
{1,0,0,0},
{0,0,0,0},
{0,0,0,0}
{1,1,1,0}, /*左弯*/
{0,0,1,0},
{0,0,0,0},
{0,0,0,0}
{1,1,1,0}, /*T型*/
{0,1,0,0},
{0,0,0,0},
{0,0,0,0}
{1,1,0,0}, /*左Z*/
{0,1,1,0},
{0,0,0,0},
{0,0,0,0}
{0,1,1,0}, /*右Z*/
{1,1,0,0},
{0,0,0,0},
{0,0,0,0}
{1,1,0,0}, /*方块*/
{1,1,0,0},
{0,0,0,0},
{0,0,0,0}
//子函数下面详细说明
void init(); //初始化
void draw(); //绘图
int genBox();
int getKey();
void lineFull();
int moveLeft();
int moveRight();
int moveDown();
int rotate();
int getW();
int getH();
void clearOldBox();
void putNewBox();
int collisionRotate(int box[][4]);
void getMessage();
void dispatchMessage();
int timeCome();
void fallDown();
int gameOver();
/*------------主函数----------------*/
main()
int i;
init();
do //循环
getMessage(); //获得方块位置控制消息
dispatchMessage(); //根据不同的消息做出不同的动作
while(!gameOver()); //直到游戏结束
getch(); //使用getch()让程序停在这里,按下任意键后
closegraph(); //就可关闭图形,结束游戏
/*------------子函数--------------*/
void getMessage()
if(MESSAGE) return; //除接受键盘消息外,方块的动作函数也会产生一些消息如果有一个消息尚未处理,则直接返回处理它
if(timeCome()) //计时时间到
MESSAGE=mADOWN; //控制消息=mADOWN,自动落下一格
return;
if(bioskey(1)) //查询是否有键盘消息
MESSAGE=bioskey(0)8;/*bioskey(0)返回键盘按键低8位数的ASCII码,因此右移8位,生成消息*/
return;
void dispatchMessage() //根据不同的消息做出不同的动作
switch(MESSAGE)
case mLEFT: moveLeft();break; //以下分别代表左、右、
case mRIGHT: moveRight();break;//下、旋转、落下、绘图、行满、生成方块等动作
case mADOWN: moveDown();break;
case mSPACE: rotate();break;
case mDOWN: fallDown(); break;
case mDRAW: draw();break;
case mLINE: lineFull();break;
case mGEN: genBox();break;
case mESC: closegraph(); exit(0);//退出
default: MESSAGE=0;
void fallDown()
while(active)//如果游戏active
moveDown(); draw(); //向下落,绘图
MESSAGE=mLINE;
int timeCome() //计时函数
static long tm, old; //两个时间,一个从BIOS中取得的新时间,一个上一次获得的时间
tm=biostime(0,tm);
if(tm-oldTIMEINT) return 0; //判断间隔
else
old=tm; return 1;
void init()
int i,j,x1,y1,x2,y2;
int driver=DETECT, mode=0; // 定义图形驱动模式为自检模式
randomize(); //初始化随机数生成器
registerbgidriver(EGAVGA_driver);//建立独立图形运行程序
initgraph(driver,mode,""); //直接进行的图形初始化程序
cleardevice(); //清除图形屏幕
setfillstyle(SOLID_FILL,BLUE);//设置填充模式,蓝色实心
bar(0,0,639,479);// 在(0,0)到(639,479)区域绘制蓝色矩形,这是一个总区域
x1=AREAX;
y1=AREAY-BOXW*MAXY;
x2=AREAX+MAXX*BOXW;
y2=AREAY;
rectangle(--x1,--y1,++x2,++y2); //在上述范围绘制一个矩形
setfillstyle(SOLID_FILL,BLACK);
bar(++x1,++y1,--x2,--y2); //在上述区域一个像素绘制一个黑色实心矩形,这是游戏区域
y1=AREAY-MAXY*BOXW; y2=AREAY;
setcolor(DARKGRAY);
for(i=0;iMAXX;i++)//绘制每一格子之间的网格线,深灰色
x1=AREAX+i*BOXW;
line(x1,y1,x1,y2);
x1=AREAX; x2=x1+MAXX*BOXW;
for(j=0;jMAXY;j++)
y1=AREAY-j*BOXW;
line(x1,y1,x2,y1);
for(j=0;jMAXY;j++) //将所有方格都清0,即初始的游戏区域是空的
for(i=0;iMAXX;i++)
area[j][i]=oldarea[j][i]=0; //全部清空
actX=0; actY=0; actW=MAXX-1; actH=MAXY-1;
draw();
MESSAGE=mGEN; //消息,产生一个方块
int genBox() //动作函数,产生一个方块
int i,j,boxidx;
boxidx=random(7); FORCOLOR=random(7)+1; //随机数
for(j=0;j4;j++)
for(i=0;i4;i++)
box[j][i]=BOX[boxidx][j][i];//从模板中生成一个方块
curW=getW(); curH=getH();//获得当前这个方块的宽度和高度
curX=(MAXX+curW)/2;//方块当前的X位置,开始总是从中间落下
if(curX+curW=MAXX)curX=MAXX-1-curW;//如果当前方块的宽度+方块的位置大于最大值,调整位置。我认为这种情况是不会发生的,唯一的可能是直棍。
curY=MAXY-1-curH; //当前块Y位置,开始总是从最上端落下
newX=curX; newY=curY; actX=curX;actY=curY;
actW=newW=curW; actH=newH=curH;
active=1;//游戏actice
if(collision(box)) return 0;//如果方块一下来发生碰撞,返回0,游戏结束
putNewBox();//重构游戏区域
draw(); MESSAGE=0; //绘图,清空消息
return 1;//产生成功,返回1
void lineFull()//每次有方块落下后,都对方块那几行进行判断
int row,col, rowEnd,full,i,j;
rowEnd=newY+newH; //计算方块落在哪几行
if(rowEnd=MAXY-1) rowEnd=MAXY-2;
for(row=newY; row=rowEnd;) //仅判断方块所落的那几行是否需要消行
full=1;
for(col=0;colMAXX;col++) //从0到MAXX
if(!area[row][col]){full=0; break;} //如果区域内不全是1,即这一行不满,跳出for(col=0;colMAXX;col++)循环
if(!full){++row; continue;} //如果不满,行号+1,回到for(row=newY; row=rowEnd;)继续
for(j=row; jMAXY-1;j++) //如果full=1,有一行满c俄罗斯方块源码思路了,消行,从row行开始一直到MAXY-1行
for(i=0;iMAXX;i++) //逐一将上一行的信息复制到下一行
area[j][i]=area[j+1][i];
actX=0;actY=row; actW=MAXX-1; actH=MAXY-1-row;
draw(); rowEnd--;
MESSAGE=mGEN; //方块落下,自动产生一个方块生成的消息dispatchMessage() 接到这一消息会在上端产生一个新方块
void draw() //绘制游戏区域
int row,col,x1,y1,x2,y2;
for(row=actY;row=actY+actH;row++)
for(col=actX;col=actX+actW;col++)
if(area[row][col]!=oldarea[row][col])
if(area[row][col]==0)
setfillstyle(SOLID_FILL,BACKCOLOR);
else
setfillstyle(SOLID_FILL,FORCOLOR);
x1=AREAX+col*BOXW; x2=x1+BOXW;
y1=AREAY-(row+1)*BOXW; y2=y1+BOXW;
bar(++x1,++y1,--x2,--y2);
oldarea[row][col]=area[row][col];
MESSAGE=0;
int moveLeft() //向左移动
newX=curX-1; clearOldBox(); //X位置-1
if(collision(box)) //判断是否碰撞
newX=curX; //如果碰撞,不能左移,X位置不变
putNewBox(); //产生新的游戏区域
MESSAGE=0;
return 0;
putNewBox(); //未碰撞,产生新的游戏区域
actW=curW+1; actX=curX=newX;
MESSAGE=mDRAW; //产生绘制消息
return 1;
int moveRight() //向右移动 同上
newX=curX+1; clearOldBox();
if(collision(box))
newX=curX;
putNewBox();
MESSAGE=0;
return 0;
putNewBox();
actW=curW+1; actX=curX; curX=newX;
MESSAGE=mDRAW;
return 1;
int moveDown() //向下移动 同上
int i,j;
newY=curY-1;
clearOldBox();
if(collision(box)) //判断是否发生碰撞,即是否落到底部
newY=curY;
putNewBox();
active=0; //由于已经落到c俄罗斯方块源码思路了底部,因此active要停住,falldown函数就会停,不再计时了
MESSAGE=mLINE; //发出LINE消息,看是否需要清除一行
return 0;
putNewBox(); //未发生碰撞,就重构游戏区域
actH=curH+1; actY=newY; curY=newY;
MESSAGE=mDRAW;
return 1;
int rotate() //方块旋转
int newBox[4][4];
int i,j;
clearOldBox(); //清除旧的游戏区域的信息
for(j=0;j4;j++)
for(i=0;i4;i++)
newBox[j][i]=0; //新方块信息清零
for(j=0;j4;j++)//按旋转将box数组填入对应的newbox数组
for(i=0;i4;i++)
newBox[curW-i][j]=box[j][i];
newW=curH; newH=curW;
if(collisionRotate(newBox)) //判断旋转是否发生了碰撞
newW=curW; newH=curH; newX=curX; newY=curY;
putNewBox();
MESSAGE=0;
return 0;
for(j=0;j4;j++) //重构方块旋转后游戏区域的信息
for(i=0;i4;i++)
box[j][i]=newBox[j][i];
putNewBox();
actH=newHcurH? newH:curH;
actW=curX+actH-newX;
actX=newX; actY=newY; curX=newX;
curY=newY; curW=newW; curH=newH;
MESSAGE=mDRAW;
return 1;
int getW() //获得一个方块的宽度
int i,j;
for(i=3;i0;i--)
for(j=0;j4;j++)
if(box[j][i]) return i;
return 0;
int getH() //获得一个方块的高度
int i,j;
for(j=3;j0;j--)
for(i=0;i4;i++)
if(box[j][i]) return j;
return 0;
void clearOldBox() //清除旧的游戏区域的信息
int i,j;
for(j=0;j=curH; j++)
for(i=0;i=curW; i++)
if(box[j][i])
area[curY+j][curX+i]=0;//将area数组中原方块位置信息清0
void putNewBox() //重构新游戏区域的信息
int i,j;
for(j=0;j=newH;j++)
for(i=0;i=newW;i++)
if(box[j][i]) //将area数组中填入新的方块位置的位置
area[newY+j][newX+i]=FORCOLOR;
int collision(int cbox[][4]) //方块碰撞
int i,j;
if(newX0) return 1; //遇到左右边界,碰撞
if(newX+newW=MAXX) return 1;
if(newY0) return 1; //上界?
for(j=0;j=newH;j++) //双循环逐一判断
for(i=0;i=newW;i++)
if(area[newY+j][newX+i]cbox[j][i]) return 1; //方块的新(X,Y)位置到新(X+方块长,Y+方块宽)和方块自身进行与操作,如果存在1,就是碰撞
return 0; //否则就无碰撞
int collisionRotate(int cbox[][4]) //旋转方块时碰撞
int i,j;
if(newX+newW=MAXX) newX=MAXX-1-newW;
if(newY+newH=MAXY) newY=MAXY-1-newH;
if(collision(cbox)) return 1;
for(i=0;i=newW;i++)
for(j=0;j=newH;j++)
if(area[newY+j][newX+i])
newX-=newW-i+1; goto L;
L: return collision(cbox);
int gameOver()
if(!active (curY+curHMAXY-3)) return 1; //如果大于当前Y坐标+当前高度最大Y坐标-3,游戏结束
else return 0;
求C语言俄罗斯方块代码
俄罗斯方块C源代码
#include stdio.h
#include windows.h
#include conio.h
#include time.h
#define ZL 4 //坐标增量, 不使游戏窗口靠边
#define WID 36 //游戏窗口的宽度
#define HEI 20 //游戏窗口的高度
int i,j,Ta,Tb,Tc; // Ta,Tb,Tc用于记住和转换方块变量的值
int a[60][60]={0}; //标记游戏屏幕各坐标点:0,1,2分别为空、方块、边框
int b[4]; //标记4个"口"方块:1有c俄罗斯方块源码思路,0无c俄罗斯方块源码思路,类似开关
int x,y, level,score,speed; //方块中心位置的x,y坐标c俄罗斯方块源码思路,游戏等级、得分和游戏速度
int flag,next; //当前要操作的方块类型序号,下一个方块类型序号
void gtxy(int m, int n); //以下声明要用到的自编函数
void gflag( ); //获得下一方块序号
void csh( ); //初始化界面
void start( ); //开始部分
void prfk ( ); //打印方块
void clfk( ); //清除方块
void mkfk( ); //制作方块
void keyD( ); //按键操作
int ifmov( ); //判断方块能否移动或变体
void clHA( ); //清除满行的方块
void clNEXT( ); //清除边框外的NEXT方块
int main( )
{ csh( );
while(1)
{start( ); //开始部分
while(1)
{ prfk( );
Sleep(speed); //延时
clfk( );
Tb=x;Tc=flag; //临存当前x坐标和序号,以备撤销操作
keyD( );
y++; //方块向下移动
if (ifmov( )==0) { y--; prfk( ); dlHA( ); break;} //不可动放下,删行,跨出循环
for(i=y-2;iy+2;i++){ if (i==ZL) { j=0; } } //方块触到框顶
if (j==0) { system("cls");gtxy(10,10);printf("游戏结束!"); getch(); break; }
clNEXT( ); //清除框外的NEXT方块
return 0;
void gtxy(int m, int n) //控制光标移动
{COORD pos; //定义变量
pos.X = m; //横坐标
pos.Y = n; //纵坐标
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
void csh( ) //初始化界面
{gtxy(ZL+WID/2-5,ZL-2); printf("俄罗斯方块"); //打印游戏名称
gtxy(ZL+WID+3,ZL+7); printf("******* NEXT:"); //打印菜单信息
gtxy(ZL+WID+3,ZL+13); printf("**********");
gtxy(ZL+WID+3,ZL+15); printf("Esc :退出游戏");
gtxy(ZL+WID+3,ZL+17); printf("↑键:变体");
gtxy(ZL+WID+3,ZL+19); printf("空格:暂停游戏");
gtxy(ZL,ZL); printf("╔"); gtxy(ZL+WID-2,ZL); printf("╗"); //打印框角
gtxy(ZL,ZL+HEI); printf("╚"); gtxy(ZL+WID-2,ZL+HEI); printf("╝");
a[ZL][ZL+HEI]=2; a[ZL+WID-2][ZL+HEI]=2; //记住有图案
for(i=2;iWID-2;i+=2) {gtxy(ZL+i,ZL); printf("═"); } //打印上横框
for(i=2;iWID-2;i+=2) {gtxy(ZL+i,ZL+HEI); printf("═"); a[ZL+i][ZL+HEI]=2; } //下框
for(i=1;iHEI;i++) { gtxy(ZL,ZL+i); printf("║"); a[ZL][ZL+i]=2; } //左竖框记住有图案
for(i=1;iHEI;i++) {gtxy(ZL+WID-2,ZL+i); printf("║"); a[ZL+WID-2][ZL+i]=2; } //右框
CONSOLE_CURSOR_INFO cursor_info={1,0}; //以下是隐藏光标的设置
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),cursor_info);
level=1; score=0; speed=400;
gflag( ); flag=next; //获得一个当前方块序号
void gflag( ) //获得下一个方块的序号
{ srand((unsigned)time(NULL)); next = rand()%19+1; }
void start( ) //开始部分
{ gflag( ); Ta=flag; flag=next; //保存当前方块序号,将下一方块序号临时操作
x=ZL+WID+6; y=ZL+10; prfk( ); //给x,y赋值,在框外打印出下一方块
flag=Ta; x=ZL+WID/2; y=ZL-1; //取回当前方块序号,并给x,y赋值
void prfk ( ) //打印俄罗斯方块
{ for(i=0;i4;i++) {b[i]=1; } //数组b[4]每个元素的值都为1
mkfk ( ); //制作俄罗斯方块
for( i= x-2; i=x+4; i+=2 ) //打印方块
{ for(j=y-2;j= y+1;j++) { if( a[i][j]==1 jZL ){ gtxy(i,j); printf("□"); } } }
gtxy(ZL+WID+3,ZL+1); printf("level : %d",level); //以下打印菜单信息
gtxy(ZL+WID+3,ZL+3); printf("score : %d",score);
gtxy(ZL+WID+3,ZL+5); printf("speed : %d",speed);
void clfk( ) //清除俄罗斯方块
{ for(i=0;i4;i++) { b[i]=0; } //数组b[4]每个元素的值都为0
mkfk ( ); //制作俄罗斯方块
for( i=x-2; i=x+4; i+=2 ) //清除方块
{ for(j=y-2;j=y+1;j++){ if( a[i][j]==0 jZL ){ gtxy(i,j); printf(" "); } } }
void mkfk( ) //制作俄罗斯方块
{ a[x][ y]=b[0]; //方块中心位置状态: 1-有,0-无
switch(flag) //共6大类,19种小类型
{ case 1: { a[x][y-1]=b[1]; a[x+2][y-1]=b[2]; a[x+2][y]=b[3]; break; } //田字方块
case 2: { a[x-2][y]=b[1]; a[x+2][y]=b[2]; a[x+4][y]=b[3]; break; } //直线方块:----
case 3: { a[x][y-1]=b[1]; a[x][y-2]=b[2]; a[x][y+1]=b[3]; break; } //直线方块: |
case 4: { a[x-2][y]=b[1]; a[x+2][y]=b[2]; a[x][y+1]=b[3]; break; } //T字方块
case 5: { a[x][y-1]=b[1]; a[x][y+1]=b[2]; a[x-2][y]=b[3]; break; } //T字顺时针转90度
case 6: { a[x][y-1]=b[1]; a[x-2][y]=b[2]; a[x+2][y]=b[3]; break; } //T字顺转180度
case 7: { a[x][y-1]=b[1]; a[x][y+1]=b[2]; a[x+2][y]=b[3]; break; } //T字顺转270度
case 8: { a[x][y+1]=b[1]; a[x-2][y]=b[2]; a[x+2][y+1]=b[3]; break; } //Z字方块
case 9: { a[x][y-1]=b[1]; a[x-2][y]=b[2]; a[x-2][y+1]=b[3]; break; } //Z字顺转90度
case 10: { a[x][y-1]=b[1]; a[x-2][y-1]=b[2]; a[x+2][y]=b[3]; break; } //Z字顺转180度
case 11: { a[x][y+1]=b[1]; a[x+2][y-1]=b[2]; a[x+2][ y]=b[3]; break; } //Z字顺转270度
case 12: { a[x][y-1]=b[1]; a[x][y+1]=b[2]; a[x-2][y-1]=b[3]; break; } //7字方块
case 13: {a[x-2][y]=b[1]; a[x+2][y-1]=b[2]; a[x+2][y]=b[3]; break; } //7字顺转90度
case 14: { a[x][y-1]=b[1]; a[x][y+1]=b[2]; a[x+2][y+1]=b[3]; break; } //7字顺转180度
case 15: { a[x-2][y]=b[1]; a[x-2][y+1]=b[2]; a[x+2][y]=b[3]; break; } //7字顺转270度
case 16: { a[x][y+1]=b[1]; a[x][y-1]=b[2]; a[x+2][y-1]=b[3]; break; } //倒7字方块
case 17: { a[x-2][y]=b[1]; a[x+2][y+1]=b[2]; a[x+2][y]=b[3]; break; } //倒7字顺转90度
case 18: { a[x][y-1]=b[1]; a[x][y+1]=b[2]; a[x-2][y+1]=b[3]; break; } //倒7字顺转180度
case 19: { a[x-2][y]=b[1]; a[x-2][y-1]=b[2]; a[x+2][y]=b[3]; break; } //倒7字顺转270度
void keyD( ) //按键操作
{ if (kbhit( ))
{ int key;
key=getch();
if (key==224)
{ key=getch();
if (key==75) { x-=2; } //按下左方向键,中心横坐标减2
if (key==77) { x+=2; } //按下右方向键,中心横坐标加2
if (key==72) //按下向上方向键,方块变体
{ if (flag=2 flag=3 ) { flag++; flag%=2; flag+=2; }
if ( flag=4 flag=7 ) { flag++; flag%=4; flag+=4; }
if (flag=8 flag=11 ) { flag++; flag%=4; flag+=8; }
if (flag=12 flag=15 ) { flag++; flag%=4; flag+=12; }
if ( flag=16 flag=19 ) { flag++; flag%=4; flag+=16; } }
if (key==32) //按空格键,暂停
{ prfk( ); while(1) { if (getch( )==32) { clfk( );break;} } } //再按空格键,继续游戏
if (ifmov( )==0) { x=Tb; flag=Tc; } //如果不可动,撤销上面操作
else { prfk( ); Sleep(speed); clfk( ); Tb=x;Tc=flag;} //如果可动,执行操作
int ifmov( ) //判断能否移动
{ if (a[x][y]!=0) { return 0; } //方块中心处有图案返回0,不可移动
else{ if ( (flag==1 ( a[x][ y-1]==0 a[x+2][y-1]==0 a[x+2][y]==0 ) ) ||
(flag==2 ( a[x-2][y]==0 a[x+2][y]==0 a[x+4][y]==0 ) ) ||
(flag==3 ( a[x][y-1]==0 a[x][y-2]==0 a[x][y+1]==0 ) ) ||
(flag==4 ( a[x-2][y]==0 a[x+2][y]==0 a[x][y+1]==0 ) ) ||
(flag==5 ( a[x][y-1]==0 a[x][y+1]==0 a[x-2][y]==0 ) ) ||
(flag==6 ( a[x][ y-1]==0 a[x-2][y]==0 a[x+2][y]==0 ) ) ||
(flag==7 ( a[x][y-1]==0 a[x][y+1]==0 a[x+2][y]==0 ) ) ||
(flag==8 ( a[x][y+1]==0 a[x-2][y]==0 a[x+2][y+1]==0 ) ) ||
(flag==9 ( a[x][y-1]==0 a[x-2][y]==0 a[x-2][y+1]==0 ) ) ||
(flag==10 ( a[x][y-1]==0 a[x-2][y-1]==0 a[x+2][y]==0 ) ) ||
(flag==11 ( a[x][y+1]==0 a[x+2][y-1]==0 a[x+2][y]==0 ) ) ||
(flag==12 ( a[x][y-1]==0 a[x][y+1]==0 a[x-2][y-1]==0 ) ) ||
( flag==13 ( a[x-2][y]==0 a[x+2][y-1]==0 a[x+2][y]==0 ) ) ||
( flag==14 ( a[x][y-1]==0 a[x][y+1]==0 a[x+2][y+1]==0 ) ) ||
(flag==15 ( a[x-2][y]==0 a[x-2][y+1]==0 a[x+2][y]==0 ) ) ||
(flag==16 ( a[x][y+1]==0 a[x][y-1]==0 a[x+2][y-1]==0 ) ) ||
( flag==17 ( a[x-2][y]==0 a[x+2][y+1]==0 a[x+2][y]==0 ) ) ||
(flag==18 ( a[x][y-1]==0 a[x][y+1]==0 a[x-2][y+1]==0 ) ) ||
(flag==19 ( a[x-2][y]==0 a[x-2][y-1]==0
a[x+2][y]==0 ) ) ) { return 1; }
return 0; //其它情况返回0
void clNEXT( ) //清除框外的NEXT方块
{ flag = next; x=ZL+WID+6; y=ZL+10; clfk( ); }
void clHA( ) //清除满行的方块
{ int k, Hang=0; //k是某行方块个数, Hang是删除的方块行数
for(j=ZL+HEI-1;j=ZL+1;j--) //当某行有WID/2-2个方块时,则为满行
{ k=0; for(i=ZL+2;iZL+WID-2;i+=2)
{ if (a[i][j]==1) //竖坐标从下往上,横坐标由左至右依次判断是否满行
{ k++; //下面将操作删除行
if (k==WID/2-2) { for(k=ZL+2;kZL+WID-2;k+=2)
{ a[k][j]=0; gtxy(k,j); printf(" "); Sleep(1); }
for(k=j-1;kZL;k--)
{ for(i=ZL+2;iZL+WID-2;i+=2) //已删行数上面有方块,先清除再全部下移一行
{ if(a[i][k]==1) { a[i][k]=0; gtxy(i,k); printf(" ");a[i][k+1]=1;
gtxy(i,k+1); printf("□"); } }
j++; //方块下移后,重新判断删除行是否满行
Hang++; //记录删除方块的行数
score+=100*Hang; //每删除一行,得100分
if ( Hang0 (score%500==0 || score/500 level-1 ) ) //得分满500速度加快升一级
{ speed-=20; level++; if(speed200)speed+=20; }