俄罗斯方块纯C语言

来源:互联网 发布:山西九鼎软件怎么样 编辑:程序博客网 时间:2024/05/21 06:47

程序预览:



源文件下载链接:http://blog.wunanhui.wang/?c=p_slog&a=shj&s=62


源代码:

#include <stdio.h>
#include <windows.h>
#include <time.h>

//常量定义区
#define M_X 100//定义地图的最大宽度
#define M_Y 100//定义地图的最大高度

//全局变量定义区
int i,j;//for循环专用变量
int m[M_X][M_Y];//定义最大地图数组
int X;//使用宽度
int Y;//使用高度
int Wx;//方块头实时位置
int Wy;//方块头实时位置
int Ox;//方块头实时上一次位置
int Oy;//方块头实时上一次位置
int R[4][2];//方块体实时位置
int T;//方块体实时颜色
int E,C;//方块体实时形状
int ch;//按键信息
int Z;//碰撞标志
int F;//得分
int J;//是否开启数据记录
clock_t s_t_1, s_t_2;
/*
0 = 黑色       8 = 灰色
1 = 蓝色       9 = 淡蓝色
2 = 绿色       10 = 淡绿色
3 = 浅绿色     11 = 淡浅绿色
4 = 红色       12 = 淡红色
5 = 紫色       13 = 淡紫色
6 = 黄色       14 = 淡黄色
7 = 白色       15 = 亮白色
*/
//设置字符前景色和底色,ForeColor:字色,BackColor:背景色,基本颜色0-7,8-15是亮度加强的基本色
void set_color(int ForeColor,int BackColor){
    HANDLE hConsole = GetStdHandle((STD_OUTPUT_HANDLE)) ;
    SetConsoleTextAttribute(hConsole,BackColor*16+ForeColor) ;
}
//设置光标,flg=1:显示光标 flg=0:隐藏光标
void set_cursor(int flg){
    HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO cursor_info={100,flg};
    SetConsoleCursorInfo(hOut,&cursor_info);
}
//设置字符显示位置
void set_cocate(int x,int y)
{
    x*=2;//增加
    HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
    COORD loc={x,y};
    SetConsoleCursorPosition(hOut,loc);
}
//执行系统命令
void command(int a){
/*
1 = 清屏
2 = 暂停
*/
switch(a){
    case 1:system("cls");break;
    case 2:set_cocate(0,Y);set_color(15,0);system("pause");break;
    default:break;
    }
}
//整形数据输入
int input_int(int i,int j){
    int a=-100,k=0;
    printf("请输入 %d~%d 的数值,并按回车确定; ",i,j);
    while(a>j||a<i){
        if(k!=0){
            printf("输入错误,请重新输入 %d~%d 的数值,并按回车确定; ",i,j);
        }
        scanf("%d",&a);
        k++;
    }
    return a;
}

//变量初始化
void f_bl(){
    X=0;//使用宽度
    Y=0;//使用高度
    Wx=0;//方块头实时位置
    Wy=0;//方块头实时位置
    T=0;//方块体实时颜色
    E=0;//方块体实时形状
    Ox=0;//方块头实时上一次位置
    Oy=0;//方块头实时上一次位置
    Z=0;//碰撞标志
    s_t_1=s_t_2=0;
    F=0;
    C=1;
    J=0;
}
//地图数组初始化
void f_sz_m(){
    for(i=0;i<M_X;i++){
        for(j=0;j<M_Y;j++){
            m[i][j]=0;
        }
    }
}
//初始化R数组
void f_R(){
    for(i=0;i<4;i++){
        for(j=0;j<2;j++){
            R[i][j]=0;
        }
    }    
}
//初始化data
void f_d(){
    FILE *fp;
    fp=fopen("data.txt","w");
    fclose(fp);
}

//将地图记录进data
void r_d(){
    if(J){
        FILE *fp;
        int i,j;
        fp=fopen("data.txt","a");
        for(i=0;i<X;i++){
            fprintf(fp,"|");
            for(j=0;j<Y;j++){
                fprintf(fp,"%3d|",m[i][j]);
            }
            fprintf(fp," ");
        }    
        fprintf(fp," ");
        fclose(fp);
    }
}
//设置是否开启数据记录
void s_j(){
    printf("是否开启数据记录 0=否 1=是 ");
    J=input_int(0,1);
}
//设置使用高度和宽度
void s_gk(){
    printf("宽度设置,建议20 ");
    X=input_int(10,100);
    printf("高度设置,建议20 ");
    Y=input_int(15,100);
}
//将高度和宽度写入地图
void r_gk(){
    for(i=0;i<X;i++){
        for(j=0;j<Y;j++){
            if(i==0||i==X-1||j==Y-1){
                m[i][j]=20;
            }
        }
    }
}
//打印地图
void d_m(){
    command(1);
    set_color(15,0);
    for(i=0;i<X;i++){
        for(j=0;j<Y;j++){
            if(m[i][j]==20){
                set_cocate(i,j);
                printf("#");
            }
        }
    }
}
//设置R数组
void s_R(int a,int b,int c,int d,int e,int f,int g,int h){
    R[0][0]=a;R[0][1]=b;
    R[1][0]=c;R[1][1]=d;
    R[2][0]=e;R[2][1]=f;
    R[3][0]=g;R[3][1]=h;
}
//设置W
void s_W(int a,int b){
    Ox=Wx;Oy=Wy;
    if(a<1){a=1;}
    if(E==1){if(a>X-5){a=X-5;}}
    if(E==2){if(a>X-2){a=X-2;}}
    if(E==3||E==5||E==7||E==9||E==11||E==13||E==15||E==17){if(a>X-4){a=X-4;}}
    if(E==4||E==6||E==8||E==10||E==12||E==14||E==16||E==18||E==19){if(a>X-3){a=X-3;}}
    Wx=a;Wy=b;
}
//方块设置
void s_fk(int a){
    switch(a){
        case 1 :s_R(Wx,Wy,  Wx+1,Wy,  Wx+2,Wy,  Wx+3,Wy  );break;
        case 2 :s_R(Wx,Wy,  Wx,Wy+1,  Wx,Wy+2,  Wx,Wy+3  );break;
        case 3 :s_R(Wx,Wy,  Wx,Wy+1,  Wx+1,Wy+1,Wx+2,Wy+1);break;
        case 4 :s_R(Wx,Wy,  Wx+1,Wy,  Wx,Wy+1,  Wx,Wy+2  );break;
        case 5 :s_R(Wx,Wy,  Wx+1,Wy,  Wx+2,Wy,  Wx+2,Wy+1);break;
        case 6 :s_R(Wx+1,Wy,Wx+1,Wy+1,Wx,Wy+2,  Wx+1,Wy+2);break;
        case 7 :s_R(Wx+2,Wy,Wx,Wy+1,  Wx+1,Wy+1,Wx+2,Wy+1);break;
        case 8 :s_R(Wx,Wy,  Wx,Wy+1,  Wx,Wy+2,  Wx+1,Wy+2);break;
        case 9 :s_R(Wx,Wy,  Wx+1,Wy,  Wx+2,Wy,  Wx,Wy+1  );break;
        case 10:s_R(Wx,Wy,  Wx+1,Wy,  Wx+1,Wy+1,Wx+1,Wy+2);break;
        case 11:s_R(Wx+1,Wy,Wx,Wy+1,  Wx+1,Wy+1,Wx+2,Wy+1);break;
        case 12:s_R(Wx,Wy,  Wx,Wy+1,  Wx+1,Wy+1,Wx,Wy+2  );break;
        case 13:s_R(Wx,Wy,  Wx+1,Wy,  Wx+2,Wy,  Wx+1,Wy+1);break;
        case 14:s_R(Wx+1,Wy,Wx,Wy+1,  Wx+1,Wy+1,Wx+1,Wy+2);break;
        case 15:s_R(Wx,Wy,  Wx+1,Wy,  Wx+1,Wy+1,Wx+2,Wy+1);break;
        case 16:s_R(Wx+1,Wy,Wx,Wy+1,  Wx+1,Wy+1,Wx,Wy+2  );break;
        case 17:s_R(Wx+1,Wy,Wx+2,Wy,  Wx,Wy+1,  Wx+1,Wy+1);break;
        case 18:s_R(Wx,Wy,  Wx,Wy+1,  Wx+1,Wy+1,Wx+1,Wy+2);break;
        case 19:s_R(Wx,Wy,  Wx+1,Wy,  Wx,Wy+1,  Wx+1,Wy+1);break;
        default:break;
    }
}
//将方块位置记录进地图
void r_fk_t_m(int a){
    for(i=0;i<4;i++){
        if(a){m[R[i][0]][R[i][1]]=E;}
        else{m[R[i][0]][R[i][1]]=0;}
    }     
}
//显示方块 1=显示 0清除
void d_fk(int a){
    if(a){
        if(E==1||E==2){set_color(8,0);}
        if(E==3||E==4||E==5||E==6){set_color(9,0);}
        if(E==7||E==8||E==9||E==10){set_color(10,0);}
        if(E==11||E==12||E==13||E==14){set_color(11,0);}
        if(E==15||E==16){set_color(12,0);}
        if(E==17||E==18){set_color(13,0);}
        if(E==19){set_color(14,0);}
    }
    else{
        set_color(0,0);
    }
    r_fk_t_m(a);//将方块位置记录进地图
    for(i=0;i<4;i++){
        set_cocate(R[i][0],R[i][1]);
        printf("#");
    }
}
//方块起始开始
int f_d_fx(){
    Z=0;
    E=C;//方块形状设置
    Wx=X+1;Wy=5; //设置位置
    s_fk(C);//方块设置
    d_fk(0);//显示方块
    C=0;
    while(!C){C=rand()%20;}//方块形状设置
    Wx=X+1;Wy=5; //设置位置
    s_fk(C);//方块设置
    if(C==1||C==2){set_color(8,0);}
    if(C==3||C==4||C==5||C==6){set_color(9,0);}
    if(C==7||C==8||C==9||C==10){set_color(10,0);}
    if(C==11||C==12||C==13||C==14){set_color(11,0);}
    if(C==15||C==16){set_color(12,0);}
    if(C==17||C==18){set_color(13,0);}
    if(C==19){set_color(14,0);}
    for(i=0;i<4;i++){
        set_cocate(R[i][0],R[i][1]);
        printf("#");
    }
    set_cocate(X+1,4);
    set_color(15,0);
    printf("下一个方块");
    s_W(X/2-2,0);//设置起始位置
    s_fk(E);//方块设置
    if(c_pz()){return 1;}
    d_fk(1);//显示方块
    r_d();//将地图记录进data
    usleep(100000);
    d_fk(0);//显示方块
    return 0;
}
//碰撞检测
int c_pz(){
    for(i=0;i<4;i++){
        if(m[R[i][0]][R[i][1]]!=0){return 1;}
    }
    return 0;
}
//方块旋转
void chang1(){
    switch(E){
        case 1 :E=2;break;
        case 2 :E=1;break;
        case 3 :E=4;break;
        case 4 :E=5;break;
        case 5 :E=6;break;
        case 6 :E=3;break;
        case 7 :E=8;break;
        case 8 :E=9;break;
        case 9 :E=10;break;
        case 10:E=7;break;
        case 11:E=12;break;
        case 12:E=13;break;
        case 13:E=14;break;
        case 14:E=11;break;
        case 15:E=16;break;
        case 16:E=15;break;
        case 17:E=18;break;
        case 18:E=17;break;
        case 19:E=19;break;
        default:break;
    }
}
//方块旋转
void chang2(){
    switch(E){
        case 2 :E=1;break;
        case 1 :E=2;break;
        case 4 :E=2;break;
        case 5 :E=4;break;
        case 6 :E=5;break;
        case 3 :E=6;break;
        case 8 :E=7;break;
        case 9 :E=8;break;
        case 10:E=9;break;
        case 7:E=10;break;
        case 12:E=11;break;
        case 13:E=12;break;
        case 14:E=13;break;
        case 11:E=14;break;
        case 16:E=15;break;
        case 15:E=16;break;
        case 18:E=17;break;
        case 17:E=18;break;
        case 19:E=19;break;
        default:break;
    }
}
//更改
void change(int a){
    d_fk(0);//显示方块
    switch(a){
        case 1 :chang1();break;
        case 2 :s_W(Wx,Wy+1);break;
        case 3 :s_W(Wx-1,Wy);break;
        case 4 :s_W(Wx+1,Wy);break;
        default:break;
    }
    s_fk(E);//方块设置
    if(c_pz()){//碰撞检测
        if(a==2){
            Z=1;//碰撞标志
        }
        if(a==1){
            chang2();
            s_W(Wx,Wy);//设置位置
            s_fk(E);//方块设置
        }
        else{
            s_W(Ox,Oy);//设置位置
            s_fk(E);//方块设置
        }
    }
    d_fk(1);//显示方块
    r_d();//将地图记录进data
}
//检测是否成行
void c_h(){
    int a;
    int k;
    for(j=1;j<Y-1;j++){
        a=0;
        for(i=1;i<X-1;i++){
            if(m[i][j]!=0){
                a++;
            }
        }
        if(a==X-2){
            for(k=j;k>1;k--){
                for(i=1;i<X-1;i++){
                    m[i][k]=0;
                    m[i][k]=m[i][k-1];
                    if(m[i][k]==1||m[i][k]==2){set_color(8,0);}
                    if(m[i][k]==3||m[i][k]==4||m[i][k]==5||m[i][k]==6){set_color(9,0);}
                    if(m[i][k]==7||m[i][k]==8||m[i][k]==9||m[i][k]==10){set_color(10,0);}
                    if(m[i][k]==11||m[i][k]==12||m[i][k]==13||m[i][k]==14){set_color(11,0);}
                    if(m[i][k]==15||m[i][k]==16){set_color(12,0);}
                    if(m[i][k]==17||m[i][k]==18){set_color(13,0);}
                    if(m[i][k]==19){set_color(14,0);}
                    if(m[i][k]==0){set_color(0,0);}
                    set_cocate(i,k);
                    printf("#");
                }
            }
            F+=X-2;
            set_cocate(X+1,2);
            set_color(12,0);
            printf("分数:%4d",F);
            set_cocate(X+1,3);
            set_color(14,0);
            printf("速度:%4d",1000-F/2);
        }
    }
}
//介绍
void hollo(){
    set_color(12,0);
    printf("######################################## ");
    printf("#Created At:20170906                   # ");
    printf("#Algorithm Gossip:tetris               # ");
    printf("#Developer:wunanhui                    # ");
    printf("#Referenced By:http://www.wunanhui.wang# ");
    printf("######################################## ");
    set_color(15,0);
    printf("游戏规则 ");
    printf("由小方块组成的不同形状的板块陆续从屏幕上 ");
    printf("方落下来,玩家通过调整板块的位置和方向, ");
    printf("使它们在屏幕底部拼出完整的一条或几条。这 ");
    printf("些完整的横条会随即消失,给新落下来的板块 ");
    printf("腾出空间,与此同时,玩家得到分数奖励。没 ");
    printf("有被消除掉的方块不断堆积起来,一旦堆到屏 ");
    printf("幕顶端,玩家便告输,游戏结束。 ");
    printf(" ");
}
//游戏说明
void s_m(){
    set_color(15,0);
    set_cocate(X+1,0);
    printf("Designer:wnh");
    set_cocate(X+1,9);
    printf("游戏说明");
    set_cocate(X+1,10);
    printf("↑:旋转");
    set_cocate(X+1,11);
    printf("←:左移");
    set_cocate(X+1,12);
    printf("→:右移");
    set_cocate(X+1,13);
    printf("↓:下移");
    set_cocate(X+1,14);
    printf("空格:暂停");
    set_cocate(X+1,2);
    set_color(12,0);
    printf("分数:%4d",F);
    set_cocate(X+1,3);
    set_color(14,0);
    printf("速度:%4d",1000-F/2);
}

//程序运行函数
int run(){
    set_cursor(0);//设置光标,flg=1:显示光标 flg=0:隐藏光标
    hollo();//介绍
    f_sz_m();//地图数组初始化
    f_R();//初始化R数组
    f_d();//初始化data
    f_bl();//变量初始化
    s_gk();//设置使用高度和宽度
    s_j();//设置是否开启数据记录
    r_gk();//将高度和宽度写入地图
    r_d();//将地图记录进data
    d_m();//打印地图
    s_m();//游戏说明
    int a=1;
    srand((unsigned)time(NULL ));// 设置随机种子
    while(1){
        if(f_d_fx()){return 1;}//方块起始开始
        while(1){
            change(2);//更改
            s_t_1=clock();//计时
            while(1){
                set_cocate(0,Y);
                set_color(15,0);
                printf("                                ");
                ch=0;
                if(kbhit()){
                    switch(ch=getch()){//获取用户按下的按键
                        case 0xE0:switch(ch=getch()){//分析按键
                            case 72:change(1);break;
                            case 80:change(2);break;
                            case 75:change(3);break;
                            case 77:change(4);break;
                            default:break;
                        }
                        break;
                        case 32:command(2);break;
                        default:break;
                    }
                }
                s_t_2=clock();//计时
                if(s_t_2-s_t_1>1000-F/2){change(2);s_t_1=clock();}
                if(Z){break;}
            }
            if(Z){break;}
        }
        c_h();//检测是否成行
    }
    return 0;
}

void main(){
    int a;
    while(1){
        if(run()){
            command(2);
            command(1);
            printf("游戏结束 ");
            printf("重新开始请按1,结束请按0 ");
            if(input_int(0,1)!=1){break;}
        }
    }
}