#include <time.h>
#include <QMessageBox>
#include <QDebug>
#include <QPainter>
#include <QKeyEvent>
#include "widget.h"
#include "ui_widget.h"
//定义图案代码和边界
//田字
int item1[4][4]=
{
{0,0,0,0},
{0,1,1,0},
{0,1,1,0},
{0,0,0,0}
};
//右L
int item2[4][4]=
{
{0,1,0,0},
{0,1,0,0},
{0,1,1,0},
{0,0,0,0}
};
//左L
int item3[4][4]=
{
{0,0,1,0},
{0,0,1,0},
{0,1,1,0},
{0,0,0,0}
};
//右S
int item4[4][4]=
{
{0,1,0,0},
{0,1,1,0},
{0,0,1,0},
{0,0,0,0}
};
//左S
int item5[4][4]=
{
{0,0,1,0},
{0,1,1,0},
{0,1,0,0},
{0,0,0,0}
};
//山形
int item6[4][4]=
{
{0,0,0,0},
{0,0,1,0},
{0,1,1,1},
{0,0,0,0}
};
//长条
int item7[4][4]=
{
{0,0,1,0},
{0,0,1,0},
{0,0,1,0},
{0,0,1,0}
};
//拷贝方块图案
inline void block_cpy(int dblock[4][4],int sblock[4][4])
{
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
dblock[i][j]=sblock[i][j];
}
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//调整窗口尺寸布局
resize(AREA_COL*BLOCK_SIZE+MARGIN*4+4*BLOCK_SIZE,AREA_ROW*BLOCK_SIZE+MARGIN*2);
//初始化游戏
InitGame();
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
//画游戏场景边框
painter.setBrush(QBrush(Qt::white,Qt::SolidPattern));
painter.drawRect(MARGIN,MARGIN,AREA_COL*BLOCK_SIZE,AREA_ROW*BLOCK_SIZE);
//画方块预告
painter.setBrush(QBrush(Qt::blue,Qt::SolidPattern));
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if(next_block[i][j]==1)
painter.drawRect(MARGIN*3+AREA_COL*BLOCK_SIZE+j*BLOCK_SIZE,MARGIN+i*BLOCK_SIZE,BLOCK_SIZE,BLOCK_SIZE);
//绘制得分
painter.setPen(Qt::black);
painter.setFont(QFont("Arial",14));
painter.drawText(QRect(MARGIN*3+AREA_COL*BLOCK_SIZE,MARGIN*2+4*BLOCK_SIZE,BLOCK_SIZE*4,BLOCK_SIZE*4),Qt::AlignCenter,"score: "+QString::number(score));
//绘制下落方块和稳定方块,注意方块边线的颜色是根据setPen来的,默认黑色
for(int i=0;i<AREA_ROW;i++)
for(int j=0;j<AREA_COL;j++)
{
//绘制活动方块
if(game_area[i][j]==1)
{
painter.setBrush(QBrush(Qt::red,Qt::SolidPattern));
painter.drawRect(j*BLOCK_SIZE+MARGIN,i*BLOCK_SIZE+MARGIN,BLOCK_SIZE,BLOCK_SIZE);
}
//绘制稳定方块
else if(game_area[i][j]==2)
{
painter.setBrush(QBrush(Qt::green,Qt::SolidPattern));
painter.drawRect(j*BLOCK_SIZE+MARGIN,i*BLOCK_SIZE+MARGIN,BLOCK_SIZE,BLOCK_SIZE);
}
}
}
void Widget::timerEvent(QTimerEvent *event)
{
//方块下落
if(event->timerId()==game_timer)
BlockMove(DOWN);
//刷新画面
if(event->timerId()==paint_timer)
update();
}
void Widget::keyPressEvent(QKeyEvent *event)
{
switch(event->key())
{
case Qt::Key_Up:
BlockMove(UP);
break;
case Qt::Key_Down:
BlockMove(DOWN);
break;
case Qt::Key_Left:
BlockMove(LEFT);
break;
case Qt::Key_Right:
BlockMove(RIGHT);
break;
case Qt::Key_Space:
BlockMove(SPACE);
break;
default:
break;
}
}
void Widget::CreateBlock(int block[4][4],int block_id)
{
switch (block_id)
{
case 0:
block_cpy(block,item1);
break;
case 1:
block_cpy(block,item2);
break;
case 2:
block_cpy(block,item3);
break;
case 3:
block_cpy(block,item4);
break;
case 4:
block_cpy(block,item5);
break;
case 5:
block_cpy(block,item6);
break;
case 6:
block_cpy(block,item7);
break;
default:
break;
}
}
void Widget::GetBorder(int block[4][4],Border &border)
{
//计算上下左右边界
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if(block[i][j]==1)
{
border.dbound=i;
break; //直到计算到最后一行有1
}
for(int i=3;i>=0;i--)
for(int j=0;j<4;j++)
if(block[i][j]==1)
{
border.ubound=i;
break;
}
for(int j=0;j<4;j++)
for(int i=0;i<4;i++)
if(block[i][j]==1)
{
border.rbound=j;
break;
}
for(int j=3;j>=0;j--)
for(int i=0;i<4;i++)
if(block[i][j]==1)
{
border.lbound=j;
break;
}
// qDebug()<<cur_border.ubound<<cur_border.dbound<<cur_border.lbound<<cur_border.rbound;
}
void Widget::InitGame()
{
for(int i=0;i<AREA_ROW;i++)
for(int j=0;j<AREA_COL;j++)
game_area[i][j]=0;
speed_ms=800;
refresh_ms=30;
//初始化随机数种子
srand(time(0));
//分数清0
score=0;
//开始游戏
StartGame();
}
void Widget::ResetBlock()
{
//产生当前方块
block_cpy(cur_block,next_block);
GetBorder(cur_block,cur_border);
//产生下一个方块
int block_id=rand()%7;
CreateBlock(next_block,block_id);
//设置初始方块坐标,以方块左上角为锚点
block_point start_point;
start_point.pos_x=AREA_COL/2-2;
start_point.pos_y=0;
block_pos=start_point;
}
void Widget::StartGame()
{
game_timer=startTimer(speed_ms); //开启游戏timer
paint_timer=startTimer(refresh_ms); //开启界面刷新timer
//产生初始下一个方块
int block_id=rand()%7;
CreateBlock(next_block,block_id);
ResetBlock(); //产生方块
}
void Widget::GameOver()
{
//游戏结束停止计时器
killTimer(game_timer);
killTimer(paint_timer);
QMessageBox::information(this,"failed","game over");
}
void Widget::BlockRotate(int block[4][4])
{
int temp_block[4][4];
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
temp_block[3-j][i]=block[i][j];
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
block[i][j]=temp_block[i][j];
}
void Widget::ConvertStable(int x,int y)
{
for(int i=cur_border.ubound;i<=cur_border.dbound;i++)
for(int j=cur_border.lbound;j<=cur_border.rbound;j++)
if(cur_block[i][j]==1)
game_area[y+i][x+j]=2; //x和y别搞反
}
bool Widget::IsCollide(int x,int y,Direction dir)
{
//用拷贝的临时方块做判断
int temp_block[4][4];
block_cpy(temp_block,cur_block);
Border temp_border;
GetBorder(temp_block,temp_border);
//先尝试按照某方向走一格
switch(dir)
{
case UP:
BlockRotate(temp_block);
GetBorder(temp_block,temp_border); //旋转后要重新计算边界
break;
case DOWN:
y+=1;
break;
case LEFT:
x-=1;
break;
case RIGHT:
x+=1;
break;
default:
break;
}
for(int i=temp_border.ubound;i<=temp_border.dbound;i++)
for(int j=temp_border.lbound;j<=temp_border.rbound;j++)
if(game_area[y+i][x+j]==2&&temp_block[i][j]==1||x+temp_border.lbound<0||x+temp_border.rbound>AREA_COL-1)
return true;
return false;
}
void Widget::BlockMove(Direction dir)
{
switch (dir) {
case UP:
if(IsCollide(block_pos.pos_x,block_pos.pos_y,UP))
break;
//逆时针旋转90度
BlockRotate(cur_block);
//防止旋转后bug,i和j从0到4重新设置方块
俄罗斯方块小游戏QT编程
版权申诉
5星 · 超过95%的资源 179 浏览量
2022-06-22
22:11:22
上传
评论 2
收藏 5KB ZIP 举报
.wei-upup
- 粉丝: 224
- 资源: 33
最新资源
- ModStartCMS v8.4.0 框架稳定性持续迭代,修复部分已知问题
- bleder 教室学校学生教育室办公室考试
- 人脸检测-使用OpenCV实现的动漫+漫画人脸检测算法-附项目源码-优质项目实战.zip
- 道路贴图,材质材料免费
- 人脸检测-基于OpenCV+Node.js+WebSockets实现的实时人脸检测应用-附项目源码-优质项目实战.zip
- 一些常见的MySQL死锁案例-mysql-deadlocks-master(源代码+案例+图解说明)
- UE4动画烘焙器-ue4.27
- 新建文件夹.zip
- 1103a2a791bbd96ea98021062e327495b1c422e32fb27e0c2d6404b1bd74b692.gif
- 同城相亲交友php小程序
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈