// 程序名称:俄罗斯方块
// 编译环境:Visual C++ 6.0
// 程序编写:龙航四海
#include <graphics.h>
#include<windows.h>
#include<stdlib.h>
#include<time.h>
#include<conio.h>
#include<math.h>
#include<stdio.h>
#define box_k 10
#define box_g 18
#define BEGIN 10
#define WIDTH 24
struct board
{
int hang;
int lie;
int live;
}board_box[box_k*box_g+1];
char direction,str1[100],grade_temp[3];
int box_num,board_num,delay=800,box1[4],box3[4],shape[4],grade_num=0;
//box1[]数组保存的是移动的方块是底板中的第多少个,
//box3[]则存放的是新产生的方块的位置
int box[28][4]={{0xf0,0,0,0},{0x20,0x20,0x20,0x20},{0xf0,0,0,0},{0x20,0x20,0x20,0x20},
{0x60,0x60,0,0},{0xc0,0xc0,0,0},{0xc0,0xc0,0,0},{0xc0,0xc0,0,0},
{0x60,0x30,0,0},{0x40,0xc0,0x80,0},{0xc0,0x60,0,0},{0x40,0xc0,0x80,0},
{0x30,0x60,0,0},{0x80,0xc0,0x40,0},{0x60,0xc0,0,0},{0x80,0xc0,0x40,0},
{0x20,0x70,0,0},{0x40,0x60,0x40,0},{0xe0,0x40,0,0},{0x40,0xc0,0x40,0},
{0x70,0x10,0,0},{0x40,0x40,0xc0,0},{0x80,0xe0,0,0},{0xc0,0x80,0x80,0},
{0x70,0x40,0,0},{0xc0,0x40,0x40,0},{0x20,0xe0,0,0},{0x80,0x80,0xc0,0}
};
void drawline(int left, int top, int right, int bottom,COLORREF col1,COLORREF col2)
{
int i;
setcolor(col1);
for(i=1;i<WIDTH;i++)
{
line(left+i,top,left+i,bottom);
}
setcolor(col2);
line(left,top,left,bottom);
line(left,bottom,right,bottom);
line(left,top,right,top);
line(right,top,right,bottom);
}
void move(); //方块移动函数声明
void creat_box() //随机产生新方块并保存新方块的位置
{
int i,j,num2=0,temp;
srand(time(0));
box_num=rand()%28;
for(i=0;i<4;i++)
{
shape[i]=0xf0&box[box_num][i];
}
for(i=0;i<4;i++)
{
if(shape[i]>127)
{
drawline(BEGIN+box_k*WIDTH/2-WIDTH,
i*WIDTH+BEGIN,
BEGIN+box_k*WIDTH/2,
WIDTH+i*WIDTH+BEGIN,WHITE,BLACK);
box1[num2]=(i+1)*box_k+box_k/2-1;
num2++;
}
else
{
board_box[(i+1)*box_k+box_k/2].live=0;
}
for(j=0;j<3;j++)
{
shape[i]=shape[i]<<1;
temp=shape[i]&0x80;
if(temp!=0)
{
drawline(BEGIN+box_k*WIDTH/2+j*WIDTH,
i*WIDTH+BEGIN,
BEGIN+box_k*WIDTH/2+WIDTH+j*WIDTH,
WIDTH+i*WIDTH+BEGIN,WHITE,BLACK);
box1[num2]=(i+1)*box_k+box_k/2+j;
num2++;
}
}
}
for(i=0;i<4;i++)
{
box3[i]=box1[i];
box1[i]=box1[i]-box_k;
board_box[box1[i]].live=2;
}
Sleep(delay);
}
int leapchange()
{
int i,j,flag3=1;
for(i=0;i<4;i++)
{
if((box1[i])%box_k!=0)
continue;
for(j=0;j<4;j++)
{
if((box1[j])%box_k==box_k-1)
flag3=2;
}
}
for(i=0;i<4;i++)
{
if(box1[i]/box_k==box_g-1)
{
flag3=2;
return flag3;
}
}
return flag3;
}
void bianxing() //当'w'键按下时,方块变形
{
int i,j,num4=0,temp,num5,box2[4],flag2=0,flag3=0;
num5=box1[0];
for(i=0;i<4;i++)
{
box2[i]=box1[i];
}
for(i=0;i<4;i++)
{
drawline(board_box[box1[i]].hang,
board_box[box1[i]].lie,
board_box[box1[i]].hang+WIDTH,
board_box[box1[i]].lie+WIDTH,BLACK,WHITE);
board_box[box1[i]].live=0;
}
if(box_num%4==3)
box_num=box_num-3;
else
box_num++;
for(i=0;i<4;i++)
{
shape[i]=0xf0&box[box_num][i];
if(shape[i]>127)
{
if(board_box[num5+i*box_k].live==1)
flag2++;
box1[num4]=num5+i*box_k;
num4++;
}
for(j=0;j<3;j++)
{
shape[i]=shape[i]<<1;
temp=shape[i]&0x80;
if(temp!=0)
{
if(board_box[num5+i*box_k+j+1].live==1)
flag2++;
box1[num4]=num5+i*box_k+j+1;
num4++;
}
}
}
flag3=leapchange();
if(flag2!=0||flag3==2) //当flag2不等于0时表示变形失败,此时恢复原来的形状
{
if(box_num%4==0)
box_num=box_num+3;
else
box_num--;
for(i=0;i<4;i++)
{
box1[i]=box2[i];
drawline(board_box[box1[i]].hang,
board_box[box1[i]].lie,
board_box[box1[i]].hang+WIDTH,
board_box[box1[i]].lie+WIDTH,WHITE,BLACK);
board_box[box1[i]].live=2;
}
}
else //变形成功
{
for(i=0;i<4;i++)
{
drawline(board_box[box1[i]].hang,
board_box[box1[i]].lie,
board_box[box1[i]].hang+WIDTH,
board_box[box1[i]].lie+WIDTH,WHITE,BLACK);
board_box[box1[i]].live=2;
}
Sleep(delay);
}
}
void print()
{
int gdriver=DETECT,gmode;
int i,j;
initgraph(&gdriver,&gmode,"c:\\tc");
cleardevice();
setbkcolor(GREEN);
for(j = BEGIN;j <=BEGIN+ box_g*WIDTH;j +=WIDTH)
for(i= BEGIN;i<=BEGIN+box_k*WIDTH;i++)
{
if(j==BEGIN||j==BEGIN+box_g*WIDTH||i==BEGIN||i==BEGIN+box_k*WIDTH)
putpixel(i,j,BLUE);
else
putpixel(i,j,WHITE);
}
for(i = BEGIN;i <= BEGIN+box_k*WIDTH;i+=WIDTH)
for(j = BEGIN;j <= BEGIN+box_g*WIDTH;j++)
{
if(j==BEGIN||j==BEGIN+box_g*WIDTH||i==BEGIN||i==BEGIN+box_k*WIDTH)
putpixel(i,j,BLUE);
else
putpixel(i,j,WHITE);
}
for(board_num=0;board_num<box_k*box_g;board_num++)
{
board_box[board_num].lie=BEGIN+(board_num/box_k)*WIDTH;
board_box[board_num].hang=(board_num%box_k)*WIDTH+BEGIN;
board_box[board_num].live=0;
}
}
int leap() //判断方块形状
{
int num3,shu; //num3存储方块周围的空白数
shu=box1[3]-box1[0];
if(shu<box_k)
num3=1;
else if(shu<box_k+3)
num3=2;
else if(shu<2*box_k+3)
num3=3;
else
num3=4;
return num3;
}
void move() //方块移动及变换,并且更新方块的存储位置
{
int i,flag=0,flag1=0,num;//扫描变量行和列;
num=leap(); //num为当前方块想要移动所需的移动方向的空格数
if(direction=='d')
{
for(i=3;i>=0;i--)
{
if(board_box[box1[i]+1].live==0)
flag++; //flag为当前方块移动方向的空白方格数
if((box1[i]%box_k)<box_k-1)
flag1++;
}
if(flag==num&&flag1==4) //两者相等时,表示可以移动
{
flag=0;
flag1=0;
for(i=3;i>=0;i--)
{
board_box[box1[i]].live=0;
board_box[box1[i]+1].live=2;
drawline(board_box[box1[i]].hang, //消除移动前的方块
board_box[box1[i]].lie,
board_box[box1[i]].hang+WIDTH,
board_box[box1[i]].lie+WIDTH,BLACK,WHITE);
drawline(board_box[box1[i]+1].hang, //产生移动后的方块
board_box[box1[i]].lie,
board_box[box1[i]+1].hang+WIDTH,
board_box[box1[i]].lie+WIDTH,WHITE,BLACK);
box1[i]++;
}
Sleep(delay);
}
}
if(direction=='a')
{
for(i=0;i<4;i++)
{
if(board_box[box1[i]-1].live==0)
flag++; //flag为当前方块移动方向的空白方格数
if((box1[i]%box_k)>0)
flag1++;
}
if(flag==num&&flag1==4) //两者相等时,表示可以移动
{
flag=0;
flag1=0;
for(i=0;i<4;i++)
{
board_box[box1[i]-1].live=2;
board_box[box1[i]].live=0;
drawline(board_box[box1[i]].hang, //消除移动前的方块
board_box[box1[i]].lie,
board_box[box1[i]].hang+WIDTH,
board_box[box1[i]].lie+WIDTH,BLACK,WHITE);
drawline(board_box[box1[i]-1].hang, //产生移动后的方块
board_box[box1[i]].lie,
board_box[box1[i]-1].hang+WIDTH,
board_box[box1[i]].lie+WIDTH,WHITE,BLACK);
box1[i]--;
}
Sleep(delay);
}
}
if(direction=='s')
{
for(i=3;i>=0;i--)
{
if(board_box[box1[i]+box_k].live==0||board_box[box1[i]+box_k].live==2)
flag++;
if(box1[i]/box_k<box_g-1)
flag1++;
}
if(flag==4&&flag1==4)
{
flag1=0;
flag=0;
for(i=3;i>=0;i--)
{
board_box[box1[i]+box_k].live=2;
board_box[box1[i]].live=0;
drawline(board_box[box1[i]].hang, //消除移动前的方块
board_box[box1[i]].lie,
board_box[box1[i]].hang+WIDTH,
board_box[box1[i]].lie+WIDTH,BLACK,WHITE);
drawline(board_box[box1[i]].hang, //产生移动后的方块
board_box[box1[i]].lie+WIDTH,
board_box[box1[i]].hang+WIDTH,
board_box[box1[i]].lie+2*WIDTH,WHITE,BLACK);
box1[i]=box1[i]+box_k;
}
Sleep(delay);
}
}
if(direction=='w')
{
bianxing();
}
if(direction==' ')
system("pause");
if(direction=='q')
{
getch();
exit(0);
}
}
void check() //满行检测
{
int i,j,k,num6;
for(i=box_g-1;i>1;i--)
{
num6=0;
for(j=0;j<box_k;j++)
{
if(board_box[i*box_k+j].live==1)
num6++;
}
if(num6==box_k)
{
for(k=0;k<box_k;k++)
{
drawline(board_box[i*box_k+k].hang,
board_box[i*box_k+k].lie,
board_box[i*box_k+k].hang+WIDTH,
board_box[i*box_k+k].lie+WIDTH,BLACK,WHITE);
board_box[i*box_k+k].live=0;
}
for(k=i*box_k-1;k>=0;k--)
{
if((board_box[k].live==1)&&(board_box[k+box_k].live==0))
{
drawline(board_box[k].hang,
board_box[k].lie,
board_box[k].hang+WIDTH,
board_box[k].lie+WIDTH,BLACK,WHITE);
board_box[k].live=0;
drawline(board_box[k].hang,
board_box[k+box_k].lie,
board_box[k].hang+WIDTH,
board_box[k+box_k].lie+WIDTH,WHITE,BLACK);
board_box[k+box_k].live=1;
}
}
grade_num++;
itoa(grade_num,grade_temp,10);
outtextxy(box_k*WIDTH+2*BEGIN+3*WIDTH,50+3*WIDTH,grade_temp);
delay=delay-100;
if(delay==100)
{
outtextxy(box_k*WIDTH+2*BEGIN+3*WIDTH,50+4*WIDTH,"你好棒!");
getch();
exit(0);
}
}
}
}
void life() //判断游戏是否结束
{
int i,flag4=0;
for(i=0;i<4;i++)
{
if(board_box[box3[i]+box_k].live==1)
flag4++;
}
if(flag4!=0) //表示新产生的方块下面有方块,游戏结束
{
flag4=0;
outtextxy(box_k*WIDTH+2*BEGIN+3*WIDTH,50+5*WIDTH,"game over!");
getch();
exit(1);
}
}
void state() //方块的状态,是否变成底板
{
int i,flag3=0;//num6=0;//num6默认为0,表示方块可以下移
for(i=0;i<4;i++)
{
if(board_box[box1[i]+box_k].live==1||box1[i]/box_k==box_g-1)
flag3++;
}
if(flag3!=0) //表示方块不可以下移
{
flag3=0;
for(i=0;i<4;i++)
{
board_box[box1[i]].live=1;
}
check();
creat_box();
life();
}
}
void init() //初始化
{
outtextxy(box_k*WIDTH+2*BEGIN,50,"游戏规则");
outtextxy(box_k*WIDTH+2*BEGIN,50+WIDTH,"任意键开始,空格键暂停,'q'退出");
outtextxy(box_k*WIDTH+2*BEGIN,50+2*WIDTH,"'a'键向左移,'d'键向右移,'w'键变形");
outtextxy(box_k*WIDTH+2*BEGIN,50+3*WIDTH,"当前得分:");
itoa(grade_num,grade_temp,10);
outtextxy(box_k*WIDTH+2*BEGIN+3*WIDTH,50+3*WIDTH,grade_temp);
creat_box();
}
void main()
{
print();
// char keyhit;
init();
while(1)
{
if(!kbhit())
direction='s';
else
direction=getch();
move();
state();
}
getch();
}