主体实现思路
使用了两个类,一个块类 一个主体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()
{
}