作者在 2010-08-12 23:48:04 发布以下内容
/*
俄罗斯方块源码
编译环境:tc2.0
by:spygg
仿真环境:dosbox
若是移植到windows下需修改delay函数中的值为10000000000
游戏板大小为21行12列
*/
#include <graphics.h>
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
void draw_little_block(int ,int ,int );
void draw_block(int ,int ,int,int);
void change(int *i,int *j,int key);
int check_block(int x,int y,int style);
void kill_line(int y);
void gameover();
int style_next,style,score=0,speed=0; /*we use speed control the block's drop speed*/
int board[22][14]={0};
char str[100];
struct shape
{
int xy[8];
int gen_color;
int next;
};
#define STARTX 13 /* The first block's x potision */
#define STARTY 1 /* The first block's y potision */
#define STARTX1 15 /* The preview of the block */
#define STARTY1 6
#define LEFT 0x4b00 /*define of the key*/
#define RIGHT 0x4d00
#define DOWN 0x5000
#define UP 0x4800
#define ESC 0x011b
#define ENTER 0x1c0d
/*以左上角为(0,0) ,第九个是颜色,第十个是变形后的索引*/
struct shape shapes[19]=
{
/*set lefttop's potision is (0,0) ;after 8 x,y valule is color; and then next we call it style */
{1,1,1,2,1,3,2,3,1,1}, /* __ */
{2,2,0,3,1,3,2,3,1,2}, /* | | */
{1,1,2,1,2,2,2,3,1,3}, /* | | | _____ */
{0,2,1,2,2,2,0,3,1,0}, /* |__ _____| | | */
{1,1,2,1,1,2,1,3,2,5}, /* ------ */
{0,2,0,3,1,3,2,3,2,6}, /* | | */
{2,1,2,2,1,3,2,3,2,7}, /* | | | _____ */
{0,2,1,2,2,2,2,3,2,4}, /* | |_____ _ _| | */
{1,2,0,3,1,3,2,3,6,9}, /* */
{2,1,1,2,2,2,2,3,6,10}, /* | | */
{0,2,1,2,2,2,1,3,6,11}, /* | - --- | ------- |---- */
{1,1,1,2,2,2,1,3,6,8}, /* ----- | | | */
{1,2,2,2,0,3,1,3,4,13}, /* ---- |__ */
{1,1,1,2,2,2,2,3,4,12}, /* __| | */
{0,2,1,2,1,3,2,3,14,15}, /* ---- __| */
{2,1,1,2,2,2,1,3,14,14}, /* |__ | */
{1,0,1,1,1,2,1,3,3,17}, /* | */
{0,3,1,3,2,3,3,3,3,16}, /* | ____ */
/* ___ */
{1,2,2,2,1,3,2,3,61,18} /* |__| */
};
void draw_little_block(int x,int y,int color) /*DARK==0*/
{
setfillstyle(1,color); /*当color 值为0时候画的为黑色方块*/
bar(x*16+1,y*16+1,x*16+16-1,y*16+16-1); /*加1和减1是为了美观*/
}
/*style是方块的种类,way决定了方块是否为黑色*/
void draw_block(int x,int y,int style,int way) /*style is the shape of the block 0~18, way decide the block is dark or not*/
{
int i,j;
for(i=0;i<=6;i+=2)
{
if(way==1) /*由大方块左上角的x值加上STARTX得到相对于起始位置的坐标因为方块总是从游戏板中间下落,加STATRX只是为了方便没有什么特别的意义*/
draw_little_block(x+STARTX+shapes[style].xy[i], y+STARTY+shapes[style].xy[i+1], shapes[style].gen_color);/*画出方块并着色*/
else
draw_little_block(x+STARTX+shapes[style].xy[i], y+STARTY+shapes[style].xy[i+1], 0); /*把方块涂黑*/
}
}
int check_block(int x,int y,int style)
{
int i;
for(i=0;i<=6;i+=2)
if((board[y+shapes[style].xy[i+1]-4][x+shapes[style].xy[i]+5]!=0)) /*如果方块此位置非空则返回*/
return 0;
return 1;
}
void change(int *n,int *m,int key)
{
speed=0;
if(key==UP&&(check_block(*n,*m,shapes[style].next)==1))
{
draw_block(*n,*m,style,0);
style=shapes[style].next; /*变形为同类的下一个见图形 */
draw_block(*n,*m,style,1);
}
else if((key==LEFT)&&(check_block(*n-1,*m,style)==1)&&(*m>1))
{
draw_block(*n,*m,style,0);
(*n)--;
draw_block(*n,*m,style,1);
}
else if((key==DOWN)&&(check_block(*n,*m+1,style)==1))
{
draw_block(*n,*m,style,0);
(*m)++;
draw_block(*n,*m,style,1);
speed=1;
}
else if((key==RIGHT)&&(check_block(*n+1,*m,style)==1)&&(*m>1))
{
draw_block(*n,*m,style,0);
(*n)++;
draw_block(*n,*m,style,1);
}
else if(key==ENTER)
{
while(1) /*等待下一次ENTER按下*/
{
if(bioskey(1))
if((key=bioskey(0))==ENTER)
break;
}
}
else if(key==ESC)
exit(0);
}
/*
此是游戏的难点,消行首先要判断时候有满行,判断条件是游戏板中的某行所有值都为1则说明满行
只有方块下落时才可能消行,又因为方块高度最大为4,所以判断四行
有满行要把满的行全部涂黑,值清零,再将此行上方的图形顺次下移一行
*/
void kill_line(int y)
{
int i,j,k,flag=0;
for(i=0;i<4;i++) /*只需要判断四行*/
{
flag=0;
for(j=0;j<12;j++) /*每一行是否全满*/
{
flag=0;
if(board[y+i-4][j+1]==0)
{
flag=1;
break;
}
}
if(flag==0) /*若是有某行全满*/
{
score++;
for(j=0;j<12;j++) /*把此行的值赋值0 并涂黑*/
{
board[y+i-4][j+1]=0;
draw_little_block(j+9,y+4-1,0);
}
for(k=0;k<y-4+i;k++) /*从此行开始到最顶端所有的行*/
{
for(j=0;j<12;j++)
{
draw_little_block(j+9,y+i-k+STARTY,0); /*首先把消去行的涂黑,以便于下落*/
board[y+i-4-k][j+1]=board[y+i-1-4-k][j+1]; /*循环把上一行的值赋给下一行*/
if(board[y+i-4-k][j+1]!=0) /*如果有值则画出该小方块,没有的话不处理*/
draw_little_block(j+9,y+i-k+STARTY,board[y+i-4-k][j+1]);
}
}
delay(100);
}
}
delay(100);
}
void gameover(int *n,int *m,int style)
{
int k,flag=0;
for(k=4;k<8;k++) /*判断最顶端的中间位置是否有方块*/
if(board[1][k+1]!=0)
flag=1;
if((flag==1)&&(check_block(*n-1,*m,style)==0)&&(check_block(*n+1,*m,style)==0)) /*若是有方块并且不能左右移动则说明游戏结束*/
{
settextstyle(0,0,3);
outtextxy(150,200,"Game Over!");
exit(0);
}
}
int main(void)
{
int graph_driver,graph_mode;
int m,n,key,i,k;
graph_driver=DETECT;
initgraph(&graph_driver,&graph_mode," "); /*初始化图形模式*/
randomize(); /*初始化随机函数*/
for(i=0;i<22;i++) /*给方块增加三排卫兵*/
{
board[i][0]=1;
board[i][13]=1;
}
for(i=1;i<13;i++)
board[21][i]=1;
settextstyle(0,0,3); /*设置文字格式*/
outtextxy(20,200,"press any key to start!"); /*输出等待提示用户开始*/
getch(); /*等待用户任意键进入游戏*/
cleardevice(); /*清屏*/
line(142,80,142,418);
line(338,80,338,418);
line(142,418,338,418); /*勾画游戏区域*/
while(1)
{
settextstyle(0,0,1);
setcolor(LIGHTRED); /* 画计分板*/
setlinestyle(0,0,1);
setfillstyle(1,BLUE);
rectangle(450,50,500,70);
floodfill(455,55,LIGHTRED);
setcolor(14);
itoa(score,str,10);
outtextxy(460,55,str);
style_next=random(19); /*随机化方块*/
draw_block(STARTX1,STARTY1,style_next,1); /*画出预览*/
m=0;
n=0;
while(1) /*方块的调整*/
{
if(check_block(n,m+1,style)==0)
break;
if(bioskey(1)) /*等待按键按下*/
{
key=bioskey(0);
change(&n,&m,key);
}
if(check_block(n,m+1,style)==0)
break;
draw_block(n,m,style,0);
m++;
draw_block(n,m,style,1);
if(speed!=1) /*说明没有按下下落键*/
{
for(k=0;k<=4;k++) /*为了循环检测按键*/
{
if(bioskey(1))
{
key=bioskey(0);
change(&n,&m,key);
}
else
delay(100);
}
}
else
{
speed=0;
delay(10);
}
if(m>=21)
break;
}
for(i=0;i<=6;i+=2) /*对方块中的每一个方块在游戏版中的位置赋值*/
board[m+shapes[style].xy[i+1]-4][n+shapes[style].xy[i]+5]=shapes[style].gen_color;
kill_line(m);
draw_block(STARTX1,STARTY1,style_next,0);/*把预览涂黑*/
style=style_next; /*把预览的种类赋值给游戏版中要显示的种类*/
gameover(&n,&m,style); /*判断游戏是否结束*/
}
}
俄罗斯方块源码
编译环境:tc2.0
by:spygg
仿真环境:dosbox
若是移植到windows下需修改delay函数中的值为10000000000
游戏板大小为21行12列
*/
#include <graphics.h>
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
void draw_little_block(int ,int ,int );
void draw_block(int ,int ,int,int);
void change(int *i,int *j,int key);
int check_block(int x,int y,int style);
void kill_line(int y);
void gameover();
int style_next,style,score=0,speed=0; /*we use speed control the block's drop speed*/
int board[22][14]={0};
char str[100];
struct shape
{
int xy[8];
int gen_color;
int next;
};
#define STARTX 13 /* The first block's x potision */
#define STARTY 1 /* The first block's y potision */
#define STARTX1 15 /* The preview of the block */
#define STARTY1 6
#define LEFT 0x4b00 /*define of the key*/
#define RIGHT 0x4d00
#define DOWN 0x5000
#define UP 0x4800
#define ESC 0x011b
#define ENTER 0x1c0d
/*以左上角为(0,0) ,第九个是颜色,第十个是变形后的索引*/
struct shape shapes[19]=
{
/*set lefttop's potision is (0,0) ;after 8 x,y valule is color; and then next we call it style */
{1,1,1,2,1,3,2,3,1,1}, /* __ */
{2,2,0,3,1,3,2,3,1,2}, /* | | */
{1,1,2,1,2,2,2,3,1,3}, /* | | | _____ */
{0,2,1,2,2,2,0,3,1,0}, /* |__ _____| | | */
{1,1,2,1,1,2,1,3,2,5}, /* ------ */
{0,2,0,3,1,3,2,3,2,6}, /* | | */
{2,1,2,2,1,3,2,3,2,7}, /* | | | _____ */
{0,2,1,2,2,2,2,3,2,4}, /* | |_____ _ _| | */
{1,2,0,3,1,3,2,3,6,9}, /* */
{2,1,1,2,2,2,2,3,6,10}, /* | | */
{0,2,1,2,2,2,1,3,6,11}, /* | - --- | ------- |---- */
{1,1,1,2,2,2,1,3,6,8}, /* ----- | | | */
{1,2,2,2,0,3,1,3,4,13}, /* ---- |__ */
{1,1,1,2,2,2,2,3,4,12}, /* __| | */
{0,2,1,2,1,3,2,3,14,15}, /* ---- __| */
{2,1,1,2,2,2,1,3,14,14}, /* |__ | */
{1,0,1,1,1,2,1,3,3,17}, /* | */
{0,3,1,3,2,3,3,3,3,16}, /* | ____ */
/* ___ */
{1,2,2,2,1,3,2,3,61,18} /* |__| */
};
void draw_little_block(int x,int y,int color) /*DARK==0*/
{
setfillstyle(1,color); /*当color 值为0时候画的为黑色方块*/
bar(x*16+1,y*16+1,x*16+16-1,y*16+16-1); /*加1和减1是为了美观*/
}
/*style是方块的种类,way决定了方块是否为黑色*/
void draw_block(int x,int y,int style,int way) /*style is the shape of the block 0~18, way decide the block is dark or not*/
{
int i,j;
for(i=0;i<=6;i+=2)
{
if(way==1) /*由大方块左上角的x值加上STARTX得到相对于起始位置的坐标因为方块总是从游戏板中间下落,加STATRX只是为了方便没有什么特别的意义*/
draw_little_block(x+STARTX+shapes[style].xy[i], y+STARTY+shapes[style].xy[i+1], shapes[style].gen_color);/*画出方块并着色*/
else
draw_little_block(x+STARTX+shapes[style].xy[i], y+STARTY+shapes[style].xy[i+1], 0); /*把方块涂黑*/
}
}
int check_block(int x,int y,int style)
{
int i;
for(i=0;i<=6;i+=2)
if((board[y+shapes[style].xy[i+1]-4][x+shapes[style].xy[i]+5]!=0)) /*如果方块此位置非空则返回*/
return 0;
return 1;
}
void change(int *n,int *m,int key)
{
speed=0;
if(key==UP&&(check_block(*n,*m,shapes[style].next)==1))
{
draw_block(*n,*m,style,0);
style=shapes[style].next; /*变形为同类的下一个见图形 */
draw_block(*n,*m,style,1);
}
else if((key==LEFT)&&(check_block(*n-1,*m,style)==1)&&(*m>1))
{
draw_block(*n,*m,style,0);
(*n)--;
draw_block(*n,*m,style,1);
}
else if((key==DOWN)&&(check_block(*n,*m+1,style)==1))
{
draw_block(*n,*m,style,0);
(*m)++;
draw_block(*n,*m,style,1);
speed=1;
}
else if((key==RIGHT)&&(check_block(*n+1,*m,style)==1)&&(*m>1))
{
draw_block(*n,*m,style,0);
(*n)++;
draw_block(*n,*m,style,1);
}
else if(key==ENTER)
{
while(1) /*等待下一次ENTER按下*/
{
if(bioskey(1))
if((key=bioskey(0))==ENTER)
break;
}
}
else if(key==ESC)
exit(0);
}
/*
此是游戏的难点,消行首先要判断时候有满行,判断条件是游戏板中的某行所有值都为1则说明满行
只有方块下落时才可能消行,又因为方块高度最大为4,所以判断四行
有满行要把满的行全部涂黑,值清零,再将此行上方的图形顺次下移一行
*/
void kill_line(int y)
{
int i,j,k,flag=0;
for(i=0;i<4;i++) /*只需要判断四行*/
{
flag=0;
for(j=0;j<12;j++) /*每一行是否全满*/
{
flag=0;
if(board[y+i-4][j+1]==0)
{
flag=1;
break;
}
}
if(flag==0) /*若是有某行全满*/
{
score++;
for(j=0;j<12;j++) /*把此行的值赋值0 并涂黑*/
{
board[y+i-4][j+1]=0;
draw_little_block(j+9,y+4-1,0);
}
for(k=0;k<y-4+i;k++) /*从此行开始到最顶端所有的行*/
{
for(j=0;j<12;j++)
{
draw_little_block(j+9,y+i-k+STARTY,0); /*首先把消去行的涂黑,以便于下落*/
board[y+i-4-k][j+1]=board[y+i-1-4-k][j+1]; /*循环把上一行的值赋给下一行*/
if(board[y+i-4-k][j+1]!=0) /*如果有值则画出该小方块,没有的话不处理*/
draw_little_block(j+9,y+i-k+STARTY,board[y+i-4-k][j+1]);
}
}
delay(100);
}
}
delay(100);
}
void gameover(int *n,int *m,int style)
{
int k,flag=0;
for(k=4;k<8;k++) /*判断最顶端的中间位置是否有方块*/
if(board[1][k+1]!=0)
flag=1;
if((flag==1)&&(check_block(*n-1,*m,style)==0)&&(check_block(*n+1,*m,style)==0)) /*若是有方块并且不能左右移动则说明游戏结束*/
{
settextstyle(0,0,3);
outtextxy(150,200,"Game Over!");
exit(0);
}
}
int main(void)
{
int graph_driver,graph_mode;
int m,n,key,i,k;
graph_driver=DETECT;
initgraph(&graph_driver,&graph_mode," "); /*初始化图形模式*/
randomize(); /*初始化随机函数*/
for(i=0;i<22;i++) /*给方块增加三排卫兵*/
{
board[i][0]=1;
board[i][13]=1;
}
for(i=1;i<13;i++)
board[21][i]=1;
settextstyle(0,0,3); /*设置文字格式*/
outtextxy(20,200,"press any key to start!"); /*输出等待提示用户开始*/
getch(); /*等待用户任意键进入游戏*/
cleardevice(); /*清屏*/
line(142,80,142,418);
line(338,80,338,418);
line(142,418,338,418); /*勾画游戏区域*/
while(1)
{
settextstyle(0,0,1);
setcolor(LIGHTRED); /* 画计分板*/
setlinestyle(0,0,1);
setfillstyle(1,BLUE);
rectangle(450,50,500,70);
floodfill(455,55,LIGHTRED);
setcolor(14);
itoa(score,str,10);
outtextxy(460,55,str);
style_next=random(19); /*随机化方块*/
draw_block(STARTX1,STARTY1,style_next,1); /*画出预览*/
m=0;
n=0;
while(1) /*方块的调整*/
{
if(check_block(n,m+1,style)==0)
break;
if(bioskey(1)) /*等待按键按下*/
{
key=bioskey(0);
change(&n,&m,key);
}
if(check_block(n,m+1,style)==0)
break;
draw_block(n,m,style,0);
m++;
draw_block(n,m,style,1);
if(speed!=1) /*说明没有按下下落键*/
{
for(k=0;k<=4;k++) /*为了循环检测按键*/
{
if(bioskey(1))
{
key=bioskey(0);
change(&n,&m,key);
}
else
delay(100);
}
}
else
{
speed=0;
delay(10);
}
if(m>=21)
break;
}
for(i=0;i<=6;i+=2) /*对方块中的每一个方块在游戏版中的位置赋值*/
board[m+shapes[style].xy[i+1]-4][n+shapes[style].xy[i]+5]=shapes[style].gen_color;
kill_line(m);
draw_block(STARTX1,STARTY1,style_next,0);/*把预览涂黑*/
style=style_next; /*把预览的种类赋值给游戏版中要显示的种类*/
gameover(&n,&m,style); /*判断游戏是否结束*/
}
}