用c语言写俄罗斯方块

写了一个俄罗斯方块来检验自己所学,在这里个大家分享一下,程序还有一些不足之处,这里我分享下我个人的思路,第一次写这样的东西,可能的说的不是很清楚,

程序要求:
打印不同类型的方块,使方块自由下落,过程中需要通过按键来实现方块的左移,右移,旋转,加速下落,暂停等功能;另外还要实现当方块到达边界的时候,停止左移,右移,下落,防止方块越界。同时,还需要检测是否右满行,如果有,需要程序将满行消除,同时将其他非满行完整下移;根据消除的行数在右边界面显示实时的分数,以及随着游戏进行,速度的变化****加粗样式

说到这里,问题便是如何检测方块是否到达边界,是否满行等
这里的解决方法是通过一个数组来检测某行某列是否有方块存在,数组的行和列分别对应打印方块的Y,X坐标(行对应Y,列对应X)

另外需要注意的是一个方块在横坐标上等同于输出两个字符,(所以如果你的数组列数为16,去掉用来检测方块是否到达边界的两列,打印方块的区域的大小应该为142=28)纵坐标上与平常字符没有区别。*

接下来是具体实施方法,将数组第一行的第一列和最后一列赋给数值1,第一行和最后一行赋值1,通过检测方块的下一个左标时的数组值是否是1,来检测方块是否到达边界。
我个人的一个思路是先将方块的横纵坐标表示出来,例如:打印田字形方块时,每一个小方块的横坐标依次是{2,4,2,4}(从左往右,从上往下),纵坐标依次是{1,1,2,2};这样就可以在你想要的位置出打印方块

接下来上代码

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>
#include <time.h>
#define Lframewidth 32//边框的宽
#define Lframeheight 26//边框的高
#define SX 39//得分显示坐标
#define SY 10
#define SPX 39//速度显示坐标
#define SPY 12
int TYPEX[7][4][4]=//共有七种类型
{
    {
        {2,4,6,8},{2,2,2,2},{2,4,6,8},{2,2,2,2}
    },
    {
        {2,4,2,4},{2,4,2,4},{2,4,2,4},{2,4,2,4}
    },
    {
        {2,4,6,2},{2,4,4,4},{2,4,6,6},{2,2,2,4}
    },
    {
        {2,2,4,6},{2,4,2,2},{2,4,6,6},{2,4,4,4}
    },
    {
        {2,2,4,4},{2,4,4,6},{2,2,4,4},{2,4,4,6}
    },
    {
        {2,2,4,4},{2,4,4,6},{2,2,4,4},{2,4,4,6}
    },
    {
        {2,4,4,6},{2,2,2,4},{2,4,4,6},{2,4,4,4}
    }
};
int TYPEY[7][4][4]=
{
    {
        {1,1,1,1},{1,2,3,4},{1,1,1,1},{1,2,3,4}
    },
    {
        {1,1,2,2},{1,1,2,2},{1,1,2,2},{1,1,2,2}
    },
    {
        {1,1,1,2},{1,1,2,3},{2,2,2,1},{1,2,3,3}
    },
    {
        {1,2,2,2},{1,1,2,3},{1,1,1,2},{3,1,2,3}
    },
    {
        {1,2,2,3},{2,1,2,1},{1,2,2,3},{2,1,2,1}
    },
    {
        {2,3,1,2},{1,1,2,2},{2,3,1,2},{1,1,2,2}
    },
    {
        {2,1,2,2},{1,2,3,2},{1,1,2,1},{2,1,2,3}
    }
};
int array[27][17]={0};
int NextX=36;
int NextY=4;//打印下一个方块的坐标
int shape;
int type;//记录随机类型
int x=8;
int y=0;//确定初始打印方块的位置,在此基础上加上相应的横纵坐标
int m=0;
int speed=400;
int NextType;//下一个方块的属性
int NextShape;
int Score=0;
void HideCursor();//隐藏光标函数
void gotoXY(int x,int y);//光标位置移动函数
void InterInfo();//打印游戏边框
void PrintBricks();//随机生成方块,打印方块
void KeyValue();//通过按键控制左右移动 加速 旋转 暂停
void CleanRow();//消除满行
int main()
{


    int i,j;
    InterInfo();
    for(i=0;i<27;i++)
    {
        array[i][0]=1;
        array[i][16]=1;
    }
    for(i=0;i<18;i++)
    {
        array[0][i]=1;
        array[26][i]=1;
    }
        PrintBricks();
}
void HideCursor()
{
	CONSOLE_CURSOR_INFO cursor_info = {1, 0};
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void CleanRow()
{
    int i,j,countrow=0,countcol=0;
    for(i=25;i>0;i--)
    {
        for(j=2;j<32;j+=2)
        {
            if(array[i][j/2]==1)
                countcol++;
        }
        if(countcol==15)
        {
            countrow++;
        }
        countcol=0;
    }
    for(i=25;i>25-countrow;i--)
    {
        for(j=2;j<32;j+=2)
        {
            gotoXY(j,i);
            printf("  ");
            array[i][j/2]=0;
        }
    }
    for(i=25-countrow;i>0;i--)
    {
        for(j=2;j<32;j+=2)
        {
            if(array[i][j/2]==1)
            {
                gotoXY(j,i);
                printf("  ");
                array[i][j/2]=0;
                gotoXY(j,i+countrow);
                printf("■");
                array[i+countrow][j/2]=1;
            }

        }
    }
    Score=Score+countrow*10;
    gotoXY(SX,SY);
    if(countrow==1)
    {
        printf("%d",Score+10);
    }
    else if(countrow==2)
    {
        printf("%d",Score+20);
    }
    else if(countrow==3)
    {
        printf("%d",Score+30);
    }
    else if(countrow>3)
    {
        printf("%d",Score+60);
    }

}
void KeyValue()
{
    int i,j,k=1;
        int key;

        if(kbhit()!=0)
        {
            setbuf(stdin,NULL);//
            if(kbhit()!=0)
            key=getch();
            setbuf(stdin,NULL);
            
        }
        else
        {
              return;

        }
        switch(key)
        {
        case 97:
            for(i=0,j=0;i<4,j<4;i++,j++)
            {
                if(array[y+TYPEY[type][shape][j]+1][x/2+m/2+TYPEX[type][shape][i]/2-1]==1)
                    k=0;
            }
            if(k!=0)
               m-=2;
            break;
        case 100:
            for(i=0,j=0;i<4,j<4;i++,j++)
            {
                if(array[y+TYPEY[type][shape][j]+1][x/2+m/2+TYPEX[type][shape][i]/2+1]==1)
                  k=0;
            }
            if(k!=0)
                m+=2;
            break;
        case 115:
            speed-=300;
            Sleep(5);
            break;
        case 119:
            if(shape==0||shape==1||shape==2)
                shape++;
            else
                shape=shape-3;
            break;
        case 32:
            getch();
            setbuf(stdin,NULL);
            break;

        }

}

void PrintBricks()
{
    int i,j,k=1,count=0,n=1;
    srand((unsigned int)(time(NULL)));
    type=rand()%7;
    shape=rand()%4;//生成第一个方块
    srand((unsigned int)(time(NULL)));
    NextType=rand()%7;
    NextShape=rand()%4;//生成下一个方块
    for(i=0,j=0;i<4,j<4;i++,j++)
    {
        gotoXY(NextX+TYPEX[NextType][NextShape][i],NextY+TYPEY[NextType][NextShape][j]);
        printf("■");//在右边提示栏打印下一个方块
    }
    while(1)
    {


    x=10,y=0;
    m=0;
    while(k)//方块自由下落
    {

    KeyValue();
    for(i=0,j=0;i<4,j<4;i++,j++)
    {
    HideCursor();
    gotoXY(x+m+TYPEX[type][shape][i],y+TYPEY[type][shape][j]);
    printf("■");

    if(array[y+TYPEY[type][shape][j]+1][x/2+m/2+TYPEX[type][shape][i]/2]==1)
    {
       k=0;
    }

    }
     if(k==0)
     {
    for(i=0,j=0;i<4,j<4;i++,j++)
    {
    HideCursor();
    gotoXY(x+m+TYPEX[type][shape][i],y+TYPEY[type][shape][j]);
    printf("■");
    array[y+TYPEY[type][shape][j]][x/2+m/2+TYPEX[type][shape][i]/2]=1;

     }

     break;
     }
    Sleep(500);
    for(i=0,j=0;i<4,j<4;i++,j++)
    {
    HideCursor();
    gotoXY(x+m+TYPEX[type][shape][i],y+TYPEY[type][shape][j]);
    printf("  ");

    }
    Sleep(speed);
    //speed=speed-count;
    if(count==30)
    {
        speed-=count;
        count=0;
    }
    gotoXY(SPX,SPY);
    printf("%d",speed);
    y++;

    }
    CleanRow();
    k=1;
    for(i=0,j=0;i<4,j<4;i++,j++)
    {
        gotoXY(NextX+TYPEX[NextType][NextShape][i],NextY+TYPEY[NextType][NextShape][j]);
        printf("  ");
    }
    type=NextType;
    shape=NextShape;
    srand((unsigned int)(time(NULL)));
    NextType=rand()%7;
    NextShape=rand()%4;
    for(i=0,j=0;i<4,j<4;i++,j++)
    {
        gotoXY(NextX+TYPEX[NextType][NextShape][i],NextY+TYPEY[NextType][NextShape][j]);
        printf("■");
    }
    CleanRow();
    //count++;
    /*if(count==50)
    {
        speed-=50;
        count=0;
    }
    gotoXY(SPX,SPY);
    printf("%d",speed);*/
    for(i=1;i<16;i++)
    {
        if(array[1][i]==1)
        {
            n=0;
        }
    }
    if(n==0)
    {
        break;
    }
    }
    gotoXY(16,12);
    printf("游戏结束!!!");

}
void InterInfo()
{
    int i,j;
    gotoXY(0,0);
    printf("╔");
    gotoXY(Lframewidth,0);
    printf("╦");
    gotoXY(0,Lframeheight);
    printf("╚");
    gotoXY(Lframewidth,Lframeheight);
    printf("╩");
    for(i=1;i<Lframewidth;i++)
    {
        gotoXY(i,0);
        printf("═");
        gotoXY(i,Lframeheight);
        printf("═");
    }
    for(i=1;i<Lframeheight;i++)
    {
        gotoXY(0,i);
        printf("║");
        gotoXY(Lframewidth,i);
        printf("║");
    }

    gotoXY(Lframewidth+16,0);
    printf("╗");
    gotoXY(Lframewidth+16,Lframeheight);
    printf("╝");
    for(i=Lframewidth+1;i<Lframewidth+16;i++)
    {
        gotoXY(i,0);
        printf("═");
        gotoXY(i,Lframeheight);
        printf("═");
    }
    for(i=1;i<Lframeheight;i++)
    {
        gotoXY(Lframewidth+16,i);
        printf("║");
    }
    gotoXY(Lframewidth+1,1);
    printf("Game Name:Teris");
    for(i=Lframewidth+1;i<Lframewidth+16;i++)
    {
        gotoXY(i,2);
        printf("═");
        gotoXY(i,9);
        printf("═");
        gotoXY(i,4);
        printf("═");
    }
    gotoXY(Lframewidth+1,3);
    printf("Next Bricks:");
    gotoXY(Lframewidth+1,10);
    printf("Score:");
    gotoXY(Lframewidth+1,12);
    printf("Speed:");
    for(i=Lframewidth+1;i<Lframewidth+16;i++)
    {
        gotoXY(i,13);
        printf("═");
    }
    gotoXY(Lframewidth+2,14);
    printf("操作方法:");
    gotoXY(Lframewidth+2,15);
    printf("w 旋转");
    gotoXY(Lframewidth+2,16);
    printf("a 向左");
    gotoXY(Lframewidth+2,17);
    printf("d 向右");
    gotoXY(Lframewidth+2,18);
    printf("s 加速");
    gotoXY(Lframewidth+2,19);
    printf("空格 暂停");
}
void gotoXY(int x, int y)
{
    COORD pos = {x,y};
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
    SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}


此代码有不足,关键学习这些东西不能闭门造车,所以贴出来希望可以和大家交流,也希望有大神路过的给予指导,感激不尽

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值