【C++】游戏之俄罗斯方块

相应键盘并根据键盘输入做出相应变化(做出变化之前要检验这种变幻是否符合游戏规则)
显示图像
图像旋转
检测一行是否被占满
统计分数并按照分数情况调整方块的下落速度

实现这些俄罗斯方块就差不多成型了

#include <iostream>
#include <cstdlib>
#include <windows.h>
#include <cstdio>
#include <ctime>
using namespace std;

const int x_max=20,y_max=25,x_base=3,y_base=2;
int score=0;
bool is_show[y_max-2][x_max-2];

class Basic   //basic中的函数很简单就不解释很多了
{
public:
    void gotoxy(int x,int y)
    {
        COORD c;
        c.X=x;c.Y=y;
        SetConsoleCursorPosition (GetStdHandle(STD_OUTPUT_HANDLE),c);
    }
    void turn(int p[4][4],int size_)   //旋转
    {
        int temp[4][4];
        memset(temp,0,sizeof(temp));
        for (int i=0;i<size_;++i)
            for (int j=0;j<size_;++j)
                temp[i][j]=p[size_-1-j][i];
        for (int i=0;i<4;++i)
            for (int j=0;j<4;++j)
                p[i][j]=temp[i][j];
    }
    void HideCursor()
    {
        HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        CONSOLE_CURSOR_INFO cci;
        GetConsoleCursorInfo(hOut, &cci);
        cci.bVisible = FALSE;
        SetConsoleCursorInfo(hOut, &cci);
    }
    void cprintf(char* str, WORD color, ...)
    {
        WORD colorOld;
        HANDLE handle = ::GetStdHandle(STD_OUTPUT_HANDLE);
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        GetConsoleScreenBufferInfo(handle, &csbi);
        colorOld = csbi.wAttributes;
        SetConsoleTextAttribute(handle, color);
        cout << str;
        SetConsoleTextAttribute(handle, colorOld);
    }
    void show(int x,int y,int show_type)
    {
        gotoxy(x,y);
        if (show_type==0)
            cout<<" ";
        if (show_type==1)
        {
            cprintf("O",100);
        }
        if (show_type==2)
        {
            //cout<<"#";
            cprintf(" ",78);
        }
    }
    void set_ground()
    {
        for (int i=0;i<y_max;++i)
        {
            for (int j=0;j<x_max;++j)
            {
                if (j==0||j==x_max-1)
                    show(j+x_base,i+y_base,2);
                else if (i==0||i==y_max-1)
                    show(j+x_base,i+y_base,2);
            }
        }
    }
};

class Block: public Basic
{
private:
    int blocks[7][4][4];
    int pos_x,pos_y;
    bool active;
    int size_;
    int type;
public:
    Block()
    {
        srand(time(0));
        int temp1[4][4]={{0,0,0,0},{1,1,1,1},{0,0,0,0},{0,0,0,0}};//size=4
        memcpy(blocks[0],temp1,sizeof(blocks[0]));
        int temp2[4][4]={0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0};
        memcpy(blocks[1],temp2,sizeof(blocks[0]));
        int temp3[4][4]={1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}; //size=2
        memcpy(blocks[2],temp3,sizeof(blocks[0]));
        int temp4[4][4]={1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0};
        memcpy(blocks[3],temp4,sizeof(blocks[0]));
        int temp5[4][4]={1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0};
        memcpy(blocks[4],temp5,sizeof(blocks[0]));
        int temp6[4][4]={0,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0};
        memcpy(blocks[5],temp6,sizeof(blocks[0]));
        int temp7[4][4]={0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0};
        memcpy(blocks[6],temp7,sizeof(blocks[0]));        //对应七种方块的形状
        pos_x=x_max/2;
        pos_y=1;
        active=true;
        srand(time(0));
        type=rand()%7;
        if (type==0)
            size_=4;
        else if (type==2)
            size_=2;
        else
            size_=3;
    }
    int test()  //检验一行是否被填满,若填满,则将其消除
    {
        int i,j,j1,flag1,flag2,flag3=0;
        bool temp1;
        for (j=y_max-3;j>=0;--j)
        {
            flag1=0;
            flag2=0;
            for (i=0;i<=x_max-3;++i)
            {
                if (is_show[j][i]==true)
                    flag1=1;
                if (is_show[j][i]==false)
                    flag2=1;
            }
            if(flag2==0)
            {
                score+=1;
                flag3=1;
                for (i=0;i<=x_max-3;i++)
                    is_show[j][i]=false;
                for (j1=j;j1>0;j1--)
                {
                    for (i=0;i<=x_max-3;++i)
                    {
                        temp1=is_show[j1][i];
                        is_show[j1][i]=is_show[j1-1][i];
                        is_show[j1-1][i]=temp1;
                    }
                }
                j++;
            }
            if (flag1==0)
                break;
        }
        return flag3;
    }
    void print_block()   //打印方块
    {
        for (int i=0;i<y_max-2;++i)
        {
            for (int j=0;j<x_max-2;++j)
            {
                if (is_show[i][j]==true)
                {
                    show(x_base+j+1,y_base+i+1,1);
                }
                else
                {
                    show(x_base+j+1,y_base+i+1,0);
                }
            }
        }
    }
    bool test_base(int x,int y)  检测目前正在向下移动的方块是否与原先的方块有重合或者是否出界
    {
        x=x-1;
        y=y-1;
        for (int i=0;i<4;++i)
        {
            for (int j=0;j<4;++j)
            {
                if (blocks[type][i][j]==1)
                {
                    if(y+i>=y_max-2||x+j>=x_max-2||y+i<0||x+j<0)
                        return false;
                    else if (is_show[y+i][x+j]==true)
                        return false;
                }
                else continue;
            }
        }
        return true;
    }
    bool test(char dir)   //检测做出某种移动后是否与原先的方块有重合或者是否出界
    {
        switch(dir)
        {
        case 'w':
            turn(blocks[type],size_);
            if (test_base(pos_x,pos_y))
                return true;
            else{
                for (int i=0;i<3;++i)
                    turn(blocks[type],size_);
                return false;
            }
        case 's':
            if (test_base(pos_x,pos_y+1))
                return true;
            else
                return false;
        case 'a':
            if (test_base(pos_x-1,pos_y))
                return true;
            else
                return false;
        case 'd':
            if (test_base(pos_x+1,pos_y))
                return true;
            else
                return false;
        }
    }
    void print(int type_show)  打印出正在下落的方块
    {
        if (active)
        {
            for (int i=0;i<4;++i)
            {
                for(int j=0;j<4;++j)
                {
                    if (blocks[type][i][j]==1)
                    {
                        show(x_base+pos_x+j,y_base+pos_y+i,type_show);
                    }
                }
            }
        }
    }
    bool move_down(char dir) //响应键盘做出移动
    {
        if(active)
        {
            if (dir=='w'&&test('w'))
                dir='w';
            if ((dir=='s'||dir==0)&&test('s'))
                pos_y=pos_y+1;
            if (dir=='a'&&test('a'))
                pos_x=pos_x-1;
            if (dir=='d'&&test('d'))
                pos_x=pos_x+1;
        }
        if (test('s')==false)   //若检测到向下移动不行,那么下落结束
        {
            active=false;
            for (int i=0;i<4;++i)
            {
                for (int j=0;j<4;++j)
                {
                    if (blocks[type][i][j]==1)
                        is_show[pos_y+i-1][pos_x+j-1]=true;
                }
            }
            test();
            print_block();
            return false;
        }
        return true;
    }
    void reset()  //生成一个新的方块
    {
        if (active==false)
        {
            pos_x=x_max/2;
            pos_y=1;
            active=true;
            type=rand()%7;
            if (type==0)
                size_=4;
            else if (type==2)
                size_=2;
            else
                size_=3;
        }
    }
    int getx()
    {
        return pos_x;
    }
    int gety()
    {
        return pos_y;
    }
};

class Move
{
private:
    Block b;
    char c;
    int speed_const;
    int speed;
    int count_;
public:
    Move()
    {
        c=0;
        speed_const=1000;
        speed=1000;
        count_=0;
    }
    void key(clock_t& t,int tt)  //相应键盘
    {
        if(clock()-t>tt)
        {
            t=clock();
            if(GetAsyncKeyState(VK_ESCAPE)) exit(0);
			if(GetAsyncKeyState(VK_LEFT))c='a';
			if(GetAsyncKeyState(VK_RIGHT))c='d';
			if(GetAsyncKeyState(VK_UP))c='w';
			if(GetAsyncKeyState(VK_DOWN))c='s';
        }
    }
    void move__(clock_t& t) //做出移动
    {
        if (clock()-t>speed)
        {
            b.print(0);
            b.move_down(c);
            b.print(1);
            t=clock();
            if (c=='s')
            {
                speed=10;
                count_++;
                if (count_==5)
                {
                    count_=0;
                    c=0;
                    speed=speed_const;
                }
            }
            else
            {
                c=0;
                speed=speed_const;
            }
        }
    }
    void is_level_up()  //根据分数情况调整下落速度
    {
        if (score<5)
            speed_const=200;
        else if (score<10)
            speed_const=160;
        else if (score<15)
            speed_const=120;
        else if (score<20)
            speed_const=80;
    }
    void show_score()  //显示分数
    {
        b.gotoxy(30,1);
        cout<<"score:"<<score;
    }
    bool is_gameover()  //判断游戏是否结束
    {
        if (b.gety()==1&&b.test_base(b.getx(),b.gety())==false)
        {
            return true;
        }
        return false;
    }
    void show_rule()  //显示规则
    {
        b.gotoxy(26,6);
        cout<<"---------游戏规则---------"<<endl;
        cout<<"向上键:翻转图形"<<endl<<"向下键:快速下落"<<endl<<"向左键:向左移动"<<endl<<"向右键:向右移动";
    }
    void move_()  //相当于主函数
    {
        clock_t t1,t2;
        t1=clock();
        t2=clock();
        int tt1=60;
        b.set_ground();
        //show_rule();
        //system("color 20");
        while(true)
        {
            b.HideCursor();
            key(t1,tt1);
            move__(t2);
            b.reset();
            show_score();
            is_level_up();
            if (is_gameover())
                break;
        }
        system("cls");
        cout<<"the final score is:"<<score<<endl;
        getchar();
    }
};
int main()
{
    Move m;
    m.move_();
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值