C++ QT QWidget 开发简易版俄罗斯方块

主体实现思路

使用了两个类,一个块类 一个主体widget类

块类功能以及代码

block.h
#ifndef BLOCK_H
#define BLOCK_H
#include <vector>
#include <string>

using namespace  std;
class block
{
public:
    block(vector<vector<vector<int>>> baseData,int color);
    vector<vector<int>> getNextChangeBlock();
    int getDownMove();
    int getLeftMove();
    int getRightMove();
    void downMove();
    void leftMove();
    void rightMove();
    void change();
    int getX();
    int getY();
    vector<vector<int>> nowChange;
    int color;
private:
    vector<vector<vector<int>>> allChange;
    int nowChangeIndex;
    int x ;
    int y ;
    int size;
};

#endif // BLOCK_H

block.cpp

#include "block.h"

using namespace std;
block::block(vector<vector<vector<int>>> baseData,int color)
{
    this->allChange=baseData;

    this->size = this->allChange.size();
    this->color=color;
    this->x=4;
    this->y=0;
    this->nowChangeIndex=0;
    this->nowChange=this->allChange[this->nowChangeIndex];
}
void block::change(){
    //改变形态
     int num = this->nowChangeIndex+1;
     if(num>=this->size){
         num= 0;
     }
     this->nowChangeIndex=num;
     vector<vector<int>> nextChange =this->allChange[num];
     for (int i=0 ;i<4;i++) {
         for (int j=0 ;j<4;j++) {

             this->nowChange[i][j]=nextChange[i][j];
         }
     }

}
void block::rightMove(){
    //右移
    ++this->x;
}
void block::leftMove(){
    //左移;
    --this->x;

}
void block::downMove(){
    //下落
     ++this->y;
}

vector<vector<int>> block:: getNextChangeBlock(){
    //获取下一次改变的形态
    int num = this->nowChangeIndex+1;
    if(num>=this->size){
        num= 0;
    }


    return this->allChange[num];
}


int block::getLeftMove(){
    int num = this->x-1;
    return  num;

}
int block::getRightMove(){
    int num = this->x+1;
    return  num;
}
int block::getDownMove(){
    int num = this->y+1;
    return  num;
}
int block::getX(){
    return this->x;
}
int block::getY(){
    return this->y;
}

主体widget类

wiget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <vector>
#include <string>
#include <QKeyEvent>
#include <QPainter>
#include <QColor>
#include <QRectF>
#include <QTime>
#include <QTimer>
#include <QPen>
#include <QDebug>
#include "block.h"
using namespace std ;
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
    QTimer* mytimer; // 定时器
private:

    block *myblock; // 方块
    vector<vector<int>> map;
    vector<vector<vector<int>>> ll; // 左口L容器    颜色0
    vector<vector<vector<int>>> rl; // 右口L容器    颜色1
    vector<vector<vector<int>>> lz; // 左口Z容器    颜色2
    vector<vector<vector<int>>> rz; // 右口Z容器    颜色3
    vector<vector<vector<int>>> zf; // 正方形容器   颜色4
    vector<vector<vector<int>>> tt; // T形容器      颜色5
    vector<vector<vector<int>>> li; // 棍子容器     颜色6
    vector<vector<int>> color;  // 颜色容器
    void init ();//初始化游戏
    void initMap(); // 初始化地图
    void initBlock(); // 初始化方块
    void initBaseBlock() ; //初始化基础方块
    void initColor(); // 初始化颜色
    void draw(QPainter &p);// 画函数
    bool blockRight(); // 判断是否允许右移
    bool blockLeft(); // 判断是否允许左移
    bool blockDown(); // 判断是否允许下落
    bool blockChange(); // 判断是否允许改变形态
    void setMap();// 当不允许下落的时候需要去刷新一下地图
    void clearMap();//当不允许下落的时候刷新完地图后需要清除地图
    bool isFull(int index);// 判断容器当前行是否已经存放满了
    QPen * mPen;// 画笔对象
    void paintEvent(QPaintEvent *event);//画图事件更新函数
    void keyPressEvent(QKeyEvent *);//键盘判定
    void initrl();
    void initlz();
    void initrz();
    void initzf();
    void inittt();
    void initli();
    void initll();

};

#endif // WIDGET_H

widget.cpp
#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    this->setMinimumSize(1000,1000);
    this->setMaximumSize(1000,1000);
    this->init();



}

void Widget::init()
{
    this->initMap();
    this->initColor();
    this->initBaseBlock();
    this->initBlock();
     mytimer = new QTimer(this);

     connect(mytimer,&QTimer::timeout, this, [&]() mutable{


        if(this->blockDown()){
            this->myblock->downMove();
        }
        else {

         this->setMap();// 刷新地图
         this->clearMap(); // 清除地图
         this->initBlock(); // 重新初始化一个方块
        }
        this->update();

    });
    mytimer->start(1000);
}
void Widget::initMap(){
    // 初始化地图
    for (int i =0 ;i <10;i++) {
        vector <int> v;
        for (int j=0;j<10;j++) {
            v.push_back(0);
        }
        this->map.push_back(v);
    }

}
void Widget::initBlock(){
    // 生成一个随机数 并且对一个块进行初始化
    QTime randtime;
    randtime = QTime::currentTime();
    qsrand(randtime.msec()+randtime.second()*1000); //以当前时间ms为随机种子
    int num = qrand() % 6;
    switch (num) {
    case 0:
        // ll
        this->myblock=new block(this->ll,num);
        ;
        break;
    case 1:
        // rl
        this->myblock=new block(this->rl,num);
        break;
    case 2:
        // lz
        this->myblock=new block(this->lz,num);
        break;
    case 3:
        // rz
        this->myblock=new block(this->rz,num);
        break;
    case 4:
        // zf
        this->myblock=new block(this->zf,num);
        break;
    case 5:
        // tt
        this->myblock=new block(this->tt,num);
        break;
    case 6:
        // li
        this->myblock=new block(this->li,num);
        break;
    }

}
void Widget::initColor(){
    vector<int> c0 = {255,5,5};
    vector<int> c1 = {252,174,5};
    vector<int> c2=  {247,242,0};
    vector<int> c3 = {132,247,0};
    vector<int> c4 = {0,214,247};
    vector<int> c5 = {0,70,70};
    vector<int> c6 = {165,0,247};

    this->color.push_back(c0);
    this->color.push_back(c1);
    this->color.push_back(c2);
    this->color.push_back(c3);
    this->color.push_back(c4);
    this->color.push_back(c5);
    this->color.push_back(c6);
}
void Widget:: keyPressEvent(QKeyEvent *event){
    switch(event->key()){

    case Qt::Key_W :
        //上
        if(this->blockChange()){
            this->myblock->change();
        }

        break;
    case Qt::Key_Up :

        //上
        if(this->blockChange()){
            this->myblock->change();

        }

        break;
    case Qt::Key_S :
        //下

        if(this->blockDown()){
             this->mytimer->stop();
            this->myblock->downMove();
             this->mytimer->start(1000);
        }
        break;
    case Qt::Key_Down :
        //下

        if(this->blockDown()){
            this->mytimer->stop();
            this->myblock->downMove();
             this->mytimer->start(1000);
        }



        break;
    case Qt::Key_A:
        //左
        if(this->blockLeft()){
            this->myblock->leftMove();
        }

        break;
    case Qt::Key_Left:
        //左
        if(this->blockLeft()){
            this->myblock->leftMove();
        }
        break;
    case Qt::Key_D:
        //右
        if(this->blockRight()){
            this->myblock->rightMove();
        }

        break;
    case Qt::Key_Right:
        //右
        if(this->blockRight()){
            this->myblock->rightMove();
        }

        break;
    }
    this->update();
}
void Widget::draw(QPainter &p){
    // 先画地图
    // 地图两次循环
    this->mPen->setColor(QColor(255,38,38));
    p.setPen( *( this->mPen));
    for (int i =0 ;i <10;i++) {
        for (int j=0;j<10;j++) {
            // i 就是 y
            // j 就是 x
            if(this->map[i][j]!=0){
             int x = 100*j;
             int y = 100*i;
             p.drawRect(QRectF( x, y,100,100));
            }
        }
    }
    //再画方块

    int color =this->myblock->color;
    int r =this->color[color][0] ;
    int g =this->color[color][1] ;
    int b =this->color[color][2] ;
    this->mPen->setColor(QColor(r,g,b));
    p.setPen( *( this->mPen));
    int baseX  =  this->myblock->getX();
    int baseY  =  this->myblock->getY();
    for (int i =0 ;i<4;i++) {
       for (int j =0 ;j<4;j++) {
           if(this->myblock->nowChange[i][j]!=0){
               int x = (baseX+j)*100;
               int y = (baseY+i)*100;
               p.drawRect(QRectF( x, y,100,100));
           }
       }
   }


}
void Widget::paintEvent(QPaintEvent *event){
    QPainter p (this);
    this->mPen=new QPen();
    this->draw(p);
}
bool Widget:: blockRight(){
    // 判断是否允许右移
    int nextX = this->myblock->getRightMove();// 获取下一步右移的X坐标
    int nextY = this->myblock->getY(); // 获取左移的Y 也是当前的Y轴
    for (int i =0 ;i<4;i++) {
        for (int j =0 ;j<4;j++) {
            if(this->myblock->nowChange[i][j]!=0)
            {
                int x = nextX+j;
                int y = nextY+i;
                int size = this->map[y].size();
                if(x>size||this->map[y][x]!=0)
                {
                    return false;
                }
            }
        }
    }
    return true;
}
bool Widget:: blockLeft(){
    // 判断是否允许左移
    int nextX = this->myblock->getLeftMove();// 获取下一步左移的X坐标
    int nextY = this->myblock->getY(); // 获取左移的Y 也是当前的Y轴
    for (int i =0 ;i<4;i++) {
        for (int j =0 ;j<4;j++) {
            if(this->myblock->nowChange[i][j]!=0)
            {
                int x = nextX+j;
                int y = nextY+i;
                if( x<0||this->map[y][x]!=0)
                {
                    return false;
                }
            }
        }
    }
     return true;
}
bool Widget::blockDown(){
   // 判断是否允许下落
   int nextY = this->myblock->getDownMove(); // 获取下一步的Y
   int nextX = this->myblock->getX(); // 获取下一步的X 也是当前的X
   for (int i =0 ;i<4;i++) {
       for (int j =0 ;j<4;j++) {
           if(this->myblock->nowChange[i][j]!=0)
           {
               int x = nextX+j;
               int y = nextY+i;
               int size = this->map.size();
               if(y>=size||this->map[y][x]!=0 )
               {

                   return false;
               }
           }
       }
   }
   return true;
}
bool Widget::blockChange(){
   // 判断是否允许改变形态
    // 先获取下一个的形态
  vector<vector<int>> nextBlock= this->myblock->getNextChangeBlock();
  for (int i =0 ;i<4;i++) {
      for (int j =0 ;j<4;j++) {

          if(nextBlock[i][j]!=0){
              int x = this->myblock->getX()+j;
              int y = this->myblock->getY()+i;
              if(this->map[y][x]!=0){
                return false;
              }
          }
      }
  }
  return true;
}
void Widget::setMap(){
  //  当不允许下落的时候需要去刷新一下地图
  // this->myblock->y;从第几行开始
  //  this->myblock->x; 从第几列开始
  //  this->myblock->nowChange; 当前块的位置
    for (int i =0 ;i<4;i++) {
        for (int j =0 ;j<4;j++) {
            if(this->myblock->nowChange[i][j]!=0){
                int x = this->myblock->getX()+j;
                int y = this->myblock->getY()+i;
                this->map[y][x]=this->myblock->nowChange[i][j];
            }
        }
    }
}
bool Widget::isFull(int index){
    // 判断map容器当前行是否已经满了
    for (int i=0;i<10;i++) {
        if(this->map[index][i]==0){
            return false;
        }
    }
    return true;
}
void Widget::clearMap(){
    for (int i = 0; i<10; i++) {
        if(this->isFull(i)){
            vector<vector <int>>::iterator it_start = this->map.begin();// 迭代器
            this->map.erase(it_start+i); // 删除指定下标的值
            vector <int> insert ={0,0,0,0,0,0,0,0,0,0}; // 新增的元素
            this->map.insert(it_start,insert); // 从头插入

        }
    }
}
void Widget::initll(){
    //初始化左口L
    vector<vector<vector<int>>> ll;
    vector<vector<int>> ll1;
    vector<vector<int>> ll2;
    vector<vector<int>> ll3;
    vector<vector<int>> ll4;
    // 形态1
    vector<int> ll11= {0,1,0,0};
    vector<int> ll12= {0,1,0,0};
    vector<int> ll13= {1,1,0,0};
    vector<int> ll14= {0,0,0,0};
    ll1.push_back(ll11);
    ll1.push_back(ll12);
    ll1.push_back(ll13);
    ll1.push_back(ll14);
    // 形态2
    vector<int> ll21= {1,0,0,0};
    vector<int> ll22= {1,1,1,0};
    vector<int> ll23= {0,0,0,0};
    vector<int> ll24= {0,0,0,0};
    ll2.push_back(ll21);
    ll2.push_back(ll22);
    ll2.push_back(ll23);
    ll2.push_back(ll24);
    // 形态3
    vector<int> ll31= {0,1,1,0};
    vector<int> ll32= {0,1,0,0};
    vector<int> ll33= {0,1,0,0};
    vector<int> ll34= {0,0,0,0};
    ll3.push_back(ll31);
    ll3.push_back(ll32);
    ll3.push_back(ll33);
    ll3.push_back(ll34);
    // 形态4
    vector<int> ll41= {0,0,0,0};
    vector<int> ll42= {1,1,1,0};
    vector<int> ll43= {0,0,1,0};
    vector<int> ll44= {0,0,0,0};
    ll4.push_back(ll41);
    ll4.push_back(ll42);
    ll4.push_back(ll43);
    ll4.push_back(ll44);

    this->ll.push_back(ll1);
    this->ll.push_back(ll2);
    this->ll.push_back(ll3);
    this->ll.push_back(ll4);

}
void Widget::initrl(){
    //初始化右口L
    // 变量名定义失误 这个是可以复用的
    vector<vector<vector<int>>> ll;
    vector<vector<int>> ll1;
    vector<vector<int>> ll2;
    vector<vector<int>> ll3;
    vector<vector<int>> ll4;
    // 形态1
    vector<int> ll11= {0,1,0,0};
    vector<int> ll12= {0,1,0,0};
    vector<int> ll13= {0,1,1,0};
    vector<int> ll14= {0,0,0,0};
    ll1.push_back(ll11);
    ll1.push_back(ll12);
    ll1.push_back(ll13);
    ll1.push_back(ll14);
    // 形态2
    vector<int> ll21= {0,0,0,0};
    vector<int> ll22= {1,1,1,0};
    vector<int> ll23= {1,0,0,0};
    vector<int> ll24= {0,0,0,0};
    ll2.push_back(ll21);
    ll2.push_back(ll22);
    ll2.push_back(ll23);
    ll2.push_back(ll24);
    // 形态3
    vector<int> ll31= {1,1,0,0};
    vector<int> ll32= {0,1,0,0};
    vector<int> ll33= {0,1,0,0};
    vector<int> ll34= {0,0,0,0};
    ll3.push_back(ll31);
    ll3.push_back(ll32);
    ll3.push_back(ll33);
    ll3.push_back(ll34);
    // 形态4
    vector<int> ll41= {0,0,1,0};
    vector<int> ll42= {1,1,1,0};
    vector<int> ll43= {0,0,0,0};
    vector<int> ll44= {0,0,0,0};
    ll4.push_back(ll41);
    ll4.push_back(ll42);
    ll4.push_back(ll43);
    ll4.push_back(ll44);

    this->rl.push_back(ll1);
    this->rl.push_back(ll2);
    this->rl.push_back(ll3);
    this->rl.push_back(ll4);

}
void Widget::initlz(){
    //初始化左口z
    // 变量名定义失误 这个是可以复用的
    vector<vector<vector<int>>> ll;
    vector<vector<int>> ll1;
    vector<vector<int>> ll2;

    // 形态1
    vector<int> ll11= {0,0,1,0};
    vector<int> ll12= {0,1,1,0};
    vector<int> ll13= {0,1,0,0};
    vector<int> ll14= {0,0,0,0};
    ll1.push_back(ll11);
    ll1.push_back(ll12);
    ll1.push_back(ll13);
    ll1.push_back(ll14);
    // 形态2
    vector<int> ll21= {1,1,0,0};
    vector<int> ll22= {0,1,1,0};
    vector<int> ll23= {0,0,0,0};
    vector<int> ll24= {0,0,0,0};
    ll2.push_back(ll21);
    ll2.push_back(ll22);
    ll2.push_back(ll23);
    ll2.push_back(ll24);


    this->lz.push_back(ll1);
    this->lz.push_back(ll2);


}
void Widget::initrz(){
    //初始化左口z
    // 变量名定义失误 这个是可以复用的
    vector<vector<vector<int>>> ll;
    vector<vector<int>> ll1;
    vector<vector<int>> ll2;

    // 形态1
    vector<int> ll11= {0,1,0,0};
    vector<int> ll12= {0,1,1,0};
    vector<int> ll13= {0,0,1,0};
    vector<int> ll14= {0,0,0,0};
    ll1.push_back(ll11);
    ll1.push_back(ll12);
    ll1.push_back(ll13);
    ll1.push_back(ll14);
    // 形态2
    vector<int> ll21= {0,1,1,0};
    vector<int> ll22= {1,1,0,0};
    vector<int> ll23= {0,0,0,0};
    vector<int> ll24= {0,0,0,0};
    ll2.push_back(ll21);
    ll2.push_back(ll22);
    ll2.push_back(ll23);
    ll2.push_back(ll24);


    this->rz.push_back(ll1);
    this->rz.push_back(ll2);


}
void Widget::initzf(){
    //初始化左口z
    // 变量名定义失误 这个是可以复用的
    vector<vector<vector<int>>> ll;
    vector<vector<int>> ll1;


    // 形态1
    vector<int> ll11= {0,1,1,0};
    vector<int> ll12= {0,1,1,0};
    vector<int> ll13= {0,0,0,0};
    vector<int> ll14= {0,0,0,0};
    ll1.push_back(ll11);
    ll1.push_back(ll12);
    ll1.push_back(ll13);
    ll1.push_back(ll14);

    this->zf.push_back(ll1);


}
void Widget::inittt(){
    //初始化右口L
    // 变量名定义失误 这个是可以复用的
    vector<vector<vector<int>>> ll;
    vector<vector<int>> ll1;
    vector<vector<int>> ll2;
    vector<vector<int>> ll3;
    vector<vector<int>> ll4;
    // 形态1
    vector<int> ll11= {0,1,0,0};
    vector<int> ll12= {1,1,1,0};
    vector<int> ll13= {0,0,0,0};
    vector<int> ll14= {0,0,0,0};
    ll1.push_back(ll11);
    ll1.push_back(ll12);
    ll1.push_back(ll13);
    ll1.push_back(ll14);
    // 形态2
    vector<int> ll21= {0,1,0,0};
    vector<int> ll22= {0,1,1,0};
    vector<int> ll23= {0,1,0,0};
    vector<int> ll24= {0,0,0,0};
    ll2.push_back(ll21);
    ll2.push_back(ll22);
    ll2.push_back(ll23);
    ll2.push_back(ll24);
    // 形态3
    vector<int> ll31= {0,0,0,0};
    vector<int> ll32= {1,1,1,0};
    vector<int> ll33= {0,1,0,0};
    vector<int> ll34= {0,0,0,0};
    ll3.push_back(ll31);
    ll3.push_back(ll32);
    ll3.push_back(ll33);
    ll3.push_back(ll34);
    // 形态4
    vector<int> ll41= {0,1,0,0};
    vector<int> ll42= {1,1,0,0};
    vector<int> ll43= {0,1,0,0};
    vector<int> ll44= {0,0,0,0};
    ll4.push_back(ll41);
    ll4.push_back(ll42);
    ll4.push_back(ll43);
    ll4.push_back(ll44);

    this->tt.push_back(ll1);
    this->tt.push_back(ll2);
    this->tt.push_back(ll3);
    this->tt.push_back(ll4);

}
void Widget::initli(){
    //初始化右口L
    // 变量名定义失误 这个是可以复用的
    vector<vector<vector<int>>> ll;
    vector<vector<int>> ll1;
    vector<vector<int>> ll2;
    vector<vector<int>> ll3;
    vector<vector<int>> ll4;
    // 形态1
    vector<int> ll11= {0,1,0,0};
    vector<int> ll12= {0,1,0,0};
    vector<int> ll13= {0,1,0,0};
    vector<int> ll14= {0,1,0,0};
    ll1.push_back(ll11);
    ll1.push_back(ll12);
    ll1.push_back(ll13);
    ll1.push_back(ll14);
    // 形态2
    vector<int> ll21= {0,0,0,0};
    vector<int> ll22= {1,1,1,1};
    vector<int> ll23= {0,0,0,0};
    vector<int> ll24= {0,0,0,0};
    ll2.push_back(ll21);
    ll2.push_back(ll22);
    ll2.push_back(ll23);
    ll2.push_back(ll24);


    this->li.push_back(ll1);
    this->li.push_back(ll2);


}



void Widget::initBaseBlock(){
    // 初始化 ll  四种形态
    this->initll();
    this->initrl();
    this->initlz();
    this->initrz();
    this->initzf();
    this->inittt();
    this->initli();
}
Widget::~Widget()
{

}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值