一、说明
1. 本人大一,能力有限。实训除去教学和写文档只有8天,时间紧迫,边学边做。若觉得代码不行,不喜勿喷。
2.代码基本手搓,过程中使用AI简化优化代码或提供思路,俄罗斯方块基本功能可以实现,具体的见游戏帮助模块,那里详细说明了游戏规则。
3.代码边修边写,注释比较详细,本文不做过多解释,自行阅读代码理解,若对Qt知识不太了解可自行查阅相关资料。
4.本文代码只做基本功能,若想有所创新,可在“未来展望”部分寻找思路。
二、详细代码
Tetris.pro
QT += core gui
QT += core sql
QT += multimedia
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
block.cpp \
main.cpp \
mainwindow.cpp \
startwindow.cpp
HEADERS += \
block.h \
mainwindow.h \
startwindow.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
DISTFILES +=
block.h
#ifndef CLOCK_H
#define CLOCK_H
#include <QPainter>
#include <QPoint>
#include <QKeyEvent>
#include <QTimer>
#include <QObject>
#include <QRandomGenerator>
#include <QDateTime>
typedef QVector<QPoint> povector;
class Block: public QObject
{
Q_OBJECT;
public:
int type; //方块类型
povector myPoint; //点集
int fallSpeed; //下落速度
QTimer * fallTimer; //计时器
bool isBottom; //是否到底
QColor color; //添加颜色
povector allPoint1; //记录已经存在的点
public:
Block(){}
Block(int type, povector& allPoints,int score);
~Block()
{
delete fallTimer; // 释放定时器内存
}
//创建方块
void createBlock();
//画出方块
void drawBlock(QPainter &painter,int x,int y);
//旋转方块
void rotateBlock();
//自动下落
void autoFallBlock();
//左移
void moveLeft();
//右移
void moveRight();
//是否在底部
bool isAtBottom();
// 旋转碰撞检测
bool checkCollision4(povector& points);
//设置下落速度
int setSpeed(int score);
};
#endif
block.cpp
#include "block.h"
Block::Block(int type, povector& allPoints,int score)
{
//初始化方块类型
this->type = type;
//点集实时转移
allPoint1=allPoints;
//初始不在底部
isBottom=false;
// 初始化定时器
fallTimer = new QTimer(this);
QObject::connect(fallTimer, &QTimer::timeout, this, &Block::autoFallBlock);
fallSpeed = setSpeed(score); // 设置下落速度,单位为毫秒
fallTimer->start(fallSpeed); // 启动定时器
}
//创建不同类型的方块
void Block::createBlock()
{
switch(Block::type)
{
//T型
case 1 :
{
//这里的坐标顺序与后面操作有关
myPoint = {QPoint(0, 0), QPoint(1, 0), QPoint(2, 0), QPoint(1, 1)};
color = QColor(255, 128, 128); //浅红色
break;
}
//O型
case 2 :
{
myPoint = {QPoint(0, 0), QPoint(1, 0), QPoint(0, 1), QPoint(1, 1)};
color = QColor(255, 255, 150); //浅黄色
break;
}
//S型
case 3 :
{
myPoint = {QPoint(0, 1), QPoint(1, 0), QPoint(1, 1), QPoint(2, 0)};
color = QColor(173, 255, 195); //浅绿色
break;
}
//Z型
case 4 :
{
myPoint = {QPoint(0, 0), QPoint(1, 0), QPoint(1, 1), QPoint(2, 1)};
color = QColor(173, 216, 230); //浅蓝色
break;
}
//L型
case 5 :
{
myPoint = {QPoint(0, 0), QPoint(0, 1), QPoint(0, 2), QPoint(1, 2)};
color = QColor(175, 238, 238); //浅青色
break;
}
//J型
case 6 :
{
myPoint = {QPoint(1, 0), QPoint(1, 1), QPoint(1, 2), QPoint(0, 2)};
color = QColor(186, 147, 211); //浅紫色
break;
}
//I型
case 7 :
{
myPoint = {QPoint(0, 0), QPoint(0, 1), QPoint(0, 2), QPoint(0, 3)};
color = QColor(Qt::lightGray); //浅灰色
break;
}
default :
{
break;
}
}
}
//画出方块
void Block::drawBlock(QPainter &painter,int x,int y)
{
//历遍一个俄罗斯方块的所有点绘图
for (int i = 0; i < myPoint.size(); i++)
{
QPoint point = myPoint[i];
painter.drawRect(QRect(x+point.x()*30, y+point.y()*30, 30, 30));
}
}
//左移方块
void Block::moveLeft()
{
bool valid = true; //检测移动是否合法
for (QPoint &point : myPoint)
{
if (point.x() == -4) //为了使方块从中间下落,初始加了120像素,水平方向是12*30,这里从而是-4
{
valid = false;
break;
}
}
if (valid) //合法才能移动方块,下同
{
for (QPoint &point : myPoint)
{
point.setX(point.x() - 1);
}
}
}
//右移方块
void Block::moveRight()
{
bool valid = true;
for (QPoint &point : myPoint)
{
if (point.x() == 7) //为了使方块从中间下落,初始加了120像素,水平方向是12*30,这里从而调整
{
valid = false;
break;
}
}
if (valid)
{
for (QPoint &point : myPoint)
{
point.setX(point.x() + 1);
}
}
}
//旋转方块具体操作
void Block::rotateBlock()
{
int centerX,centerY,relativeX,relativeY,newX,newY;
bool valid; //检测是否可以旋转
// 保存当前方块的位置
povector originalPoints = myPoint;
// 保存旋转后的点集
povector rotatedPoints = myPoint;
if (type == 1|| type == 3 || type == 4 || type == 5 || type == 6) // L, J,