Qt实现俄罗斯方块

本文实例为大家分享了Qt实现俄罗斯方块,供大家参考,具体内容如下

最近在学习Qt,用它来进行图形界面的开发还是很方便的,想着做一个小游戏来锻炼一下自己,就想到了小时候玩的俄罗斯方块。折腾了一段时间,虽然界面做的不美观,但是总算是实现了基本的功能。

首先我写了一个俄罗斯方块的类Tetris,通过这个类来进行这个游戏的数据的处理;然后游戏窗口是继承的QWidget类,用来显示游戏的方块;“下一个方块”窗口也是继承的QWidget类,用来显示下一个方块;控制提示和分数的显示用的QLabel。然后将将这些控件整合到继承自QMainWindow的mainWindow类。运行的结果如下:

Tetris类:一共有7中不同形状的方块(如下图),每个方块由四个方格组成,Block结构体用来存储方块的方格坐、中心方格坐标、ID等数据,移动中的方块和下移个方块都是通过这个结构体来操作的;已经落下的方块的方格存储在二维数组box[][]中,x坐标从左到右为正方向,y坐标从上到下为正方向(如下图)。

项目源文件

  • tetris.h
  • tetris.cpp
  • tetrisbox.h
  • tetrisbox.cpp
  • nexttetris.h
  • nexttetris.cpp
  • mainwindow.h
  • mainwindow.cpp

tetris.h

#ifndef TETRIS_H

#define TETRIS_H

//为了获得随机数

#include <cstdlib>

#include <ctime>

#define MAXX 10 //显示窗口的横向格数

#define MAXY 20 //显示窗口的竖向格数

#define NEXTMAXX 6 //“下一个”显示窗口的横向格数

#define NEXTMAXY 6 //“下一个”显示窗口的竖向格数

#define WIDTH 30 //单格的宽度

#define HEIGHT 30 //单格的高度

#define INTERVAL 4 //单格之间的间隔

#define COUNT 4 //每个方块的格数

//Block结构体:一个方块

struct Block

{

int x[COUNT]; //方块单格的x坐标

int y[COUNT]; //方块单格的y坐标

int centerX; //方块的中心x坐标

int centerY; //方块的中心y坐标

int ID; //方块的ID

};

class Tetris

{

public:

Tetris();

void createBlock(); //创建当前方块

Block getNextBlock(); //获得下一个方块

Block getBlock(); //获得当前方块

int getScore(); //获得分数

int getBox(int x, int y); //获得相应坐标的状态

bool rotate(); //旋转

bool moveToLeft(); //向左移动

bool moveToRight(); //向右移动

bool moveToBottom(); //向下移动

bool isEnd(); //判断是否结束

void killLines(); //消去整行

void clear(); //重新初始化

static int getWidth(); //获得窗口的宽度

static int getHeight(); //获得窗口的高度

static int getNextWidth(); //获得“下一个”窗口的宽度

static int getNextHeight(); //获得“下一个”窗口的高度

private:

void createNextBlock(); //创建下一个方块

bool move(int dx, int dy); //是否可以移动

void blockToBox(); //将block中的数据转移到box中

bool isRotatable(); //是否可以旋转

int getFirstFullLine(); //获得第一个整行

private:

int score; //分数

Block block; //当前方块

Block nextBlock; //下一个方块

int box[MAXX][MAXY];//方格的坐标系 1表示右方格,0表示没有方格

};

#endif // TETRIS_H

Tetris.cpp

#include "tetris.h"

Tetris::Tetris()

{

//初始化随机数发生器

srand(unsigned(time(NULL)));

//初始化成员变量

score = 0;

for (int i = 0; i < MAXX; i++)

{

for (int j = 0; j < MAXY; j++)

{

box[i][j] = 0;

}

}

for (int i = 0; i < COUNT; i++)

{

block.x[i] = -1;

block.y[i] = -1;

}

block.centerX = -1;

block.centerY = -1;

block.ID = 0;

//创建下一个方块

createNextBlock();

}

//创建当前方块

//将上一次生成的下一个方块nextBlock复制给block

//并创建下一个nextBlock

void Tetris::createBlock()

{

//nextBlock复制给block

for (int i = 0; i < COUNT; i++)

{

block.x[i] = nextBlock.x[i];

block.y[i] = nextBlock.y[i];

}

block.centerX = nextBlock.centerX;

block.centerY = nextBlock.centerY;

block.ID = nextBlock.ID;

//创建下一个nextblock

createNextBlock();

}

//返回下一个方块

Block Tetris::getNextBlock()

{

return nextBlock;

}

//返回当前方块

Block Tetris::getBlock()

{

return block;

}

//返回当前分数

int Tetris::getScore()

{

return score;

}

//返回坐标(x,y)的值,以判断是否右方格

int Tetris::getBox(int x, int y)

{

return box[x][y];

}

//旋转当前方块

//旋转成功返回true,否则返回false

bool Tetris::rotate()

{

if (isRotatable())

{

return true;

}

else

{

return false;

}

}

//将当前方块向左移动一格

//成功返回true,否则返回false

bool Tetris::moveToLeft()

{

if (move(-1, 0))

{

return true;

}

else

{

return false;

}

}

//将当前方块向右移动一格

//成功返回true,否则返回false

bool Tetris::moveToRight()

{

if (move(1, 0))

{

return true;

}

else

{

return false;

}

}

//将方块向下移动一格

//成功返回true, 游戏结束返回false

bool Tetris::moveToBottom()

{

if (!move(0, 1))

{

//移动不成功

blockToBox(); //将当前方块复制到box中

killLines(); //消行

//判断是否结束

//否则创建新的方块

if(isEnd())

{

return false;

}

else

{

createBlock();

}

}

return true;

}

//判断游戏是否结束

//结束条件为第一行有方格

bool Tetris::isEnd()

{

int j = 0;

for (int i = 0; i < MAXX; i++)

{

if (box[i][j] == 1)

{

return true;

}

}

return false;

}

//消掉整行并进行分数奖励

void Tetris::killLines()

{

int count = 0; //一次消掉的行数

//通过getFirstFullLine()函数获得从上到下第一个整行

//并将其上的行向下平移一行,达到消行的效果

int temp = 0;

while ((temp = getFirstFullLine()) != -1)

{

for (int j = temp; j >0; j--)

{

for (int i = 0; i < MAXX; i++)

{

box[i][j] = box[i][j-1];

}

}

count++;

}

//消行的分数奖励

score += count * count * 10;

}

//对成员变量进行初始化,重新开始游戏

void Tetris::clear()

{

//初始化

score = 0;

srand(unsigned(time(NULL)));

for (int i = 0; i < MAXX; i++)

{

for (int j = 0; j < MAXY; j++)

{

box[i][j] = 0;

}

}

for (int i = 0; i < COUNT; i++)

{

block.x[i] = -1;

block.y[i] = -1;

}

block.centerX = -1;

block.centerY = -1;

block.ID = 0;

//创建下一个方块

createNextBlock();

}

//获得游戏窗口的宽度

int Tetris::getWidth()

{

return MAXX * WIDTH + (MAXX - 1) * INTERVAL;

}

//获得游戏窗口的高度

int Tetris::getHeight()

{

return MAXY * HEIGHT + (MAXY - 1) * INTERVAL;

}

//获得“下一个”窗口的宽度

int Tetris::getNextWidth()

{

return NEXTMAXX * WIDTH + (NEXTMAXX - 1) * INTERVAL;

}

//获得“下一个”窗口的高度

int Tetris::getNextHeight()

{

return NEXTMAXY * WIDTH + (NEXTMAXY - 1) * INTERVAL;

}

//创建“下一个”方块

void Tetris::createNextBlock()

{

int centerX = (MAXX - 1) / 2; //中心x坐标

int ID = rand() % 7; //获得0 - 6的随机数

//根据不同的随机数创建方块

switch (ID)

{

case 0:

//##

//##

nextBlock.x[0] = centerX;

nextBlock.x[1] = centerX;

nextBlock.x[2] = centerX + 1;

nextBlock.x[3] = centerX + 1;

nextBlock.y[0] = -2;

nextBlock.y[1] = -1;

nextBlock.y[2] = -2;

nextBlock.y[3] = -1;

nextBlock.centerX = 0;

nextBlock.centerY = 0;

nextBlock.ID = 0;

break;

case 1:

//####

//

nextBlock.x[0] = centerX - 1;

nextBlock.x[1] = centerX;

nextBlock.x[2] = centerX + 1;

nextBlock.x[3] = centerX + 2;

nextBlock.y[0] = -1;

nextBlock.y[1] = -1;

nextBlock.y[2] = -1;

nextBlock.y[3] = -1;

nextBlock.centerX = centerX;

nextBlock.centerY = -1;

nextBlock.ID = 1;

break;

case 2:

//##

// ##

nextBlock.x[0] = centerX - 1;

nextBlock.x[1] = centerX;

nextBlock.x[2] = centerX;

nextBlock.x[3] = centerX + 1;

nextBlock.y[0] = -2;

nextBlock.y[1] = -2;

nextBlock.y[2] = -1;

nextBlock.y[3] = -1;

nextBlock.centerX = centerX;

nextBlock.centerY = -2;

nextBlock.ID = 2;

break;

case 3:

// ##

//##

nextBlock.x[0] = centerX;

nextBlock.x[1] = centerX + 1;

nextBlock.x[2] = centerX - 1;

nextBlock.x[3] = centerX;

nextBlock.y[0] = -2;

nextBlock.y[1] = -2;

nextBlock.y[2] = -1;

nextBlock.y[3] = -1;

nextBlock.centerX = centerX;

nextBlock.centerY = -2;

nextBlock.ID = 3;

break;

case 4:

//#

//###

nextBlock.x[0] = centerX - 1;

nextBlock.x[1] = centerX - 1;

nextBlock.x[2] = centerX;

nextBlock.x[3] = centerX + 1;

nextBlock.y[0] = -2;

nextBlock.y[1] = -1;

nextBlock.y[2] = -1;

nextBlock.y[3] = -1;

nextBlock.centerX = centerX;

nextBlock.centerY = -1;

nextBlock.ID = 4;

break;

case 5:

// #

//###

nextBlock.x[0] = centerX + 1;

nextBlock.x[1] = centerX - 1;

nextBlock.x[2] = centerX;

nextBlock.x[3] = centerX + 1;

nextBlock.y[0] = -2;

nextBlock.y[1] = -1;

nextBlock.y[2] = -1;

nextBlock.y[3] = -1;

nextBlock.centerX = centerX;

nextBlock.centerY = -1;

nextBlock.ID = 5;

break;

case 6:

// #

//###

nextBlock.x[0] = centerX;

nextBlock.x[1] = centerX - 1;

nextBlock.x[2] = centerX;

nextBlock.x[3] = centerX + 1;

nextBlock.y[0] = -2;

nextBlock.y[1] = -1;

nextBlock.y[2] = -1;

nextBlock.y[3] = -1;

nextBlock.centerX = centerX;

nextBlock.centerY = -1;

nextBlock.ID = 6;

break;

default:

break;

}

}

//可以移动就对block进行变换,返回true

//否则返回false

bool Tetris::move(int dx, int dy)

{

int newX[COUNT];

int newY[COUNT];

int newCenterX;

int newCenterY;

for (int i = 0; i < COUNT; i++)

{

newX[i] = block.x[i] + dx;

newY[i] = block.y[i] + dy;

//对变换后的坐标进行判定

//x坐标超出范围返回false

if (newX[i] < 0 || newX[i] >= MAXX)

{

return false;

}

//y坐标在0 - MAXY之间就对box中的状态进行判定

//box中为1则返回false

if (newY[i] >=0 && newY[i] < MAXY)

{

if (box[newX[i]][newY[i]] == 1)

{

return false;

}

}//y坐标超出最大值返回false

else if (newY[i] >= MAXY)

{

return false;

}

}

newCenterX = block.centerX + dx;

newCenterY = block.centerY + dy;

//满足条件就将新的x和y坐标赋值给block

for (int i = 0; i < COUNT; i++)

{

block.x[i] = newX[i];

block.y[i] = newY[i];

}

block.centerX = newCenterX;

block.centerY = newCenterY;

return true;

}

//可以旋转就对block进行变换,返回true

//否则返回false

bool Tetris::isRotatable()

{

int newX[COUNT];

int newY[COUNT];

int newCenterX;

int newCenterY;

if (block.ID == 0)

{

return false;

}

for (int i = 0; i < COUNT; i++)

{

int nx = block.x[i] - block.centerX;

int ny = block.y[i] - block.centerY;

newX[i] = nx * 0 + ny * (-1) + block.centerX;

newY[i] = nx * 1 + ny * 0 + block.centerY;

//对变换后的坐标进行判定

//x坐标超出范围返回false

if (newX[i] < 0 || newX[i] >= MAXX)

{

return false;

}

//y坐标在0 - MAXY 之间就对box中的状态进行判定

//box中为1则返回false

if (newY[i] >=0 && newY[i] < MAXY)

{

if (box[newX[i]][newY[i]] == 1)

{

return false;

}

}//y坐标超过最大值返回false

else if (newY[i] >= MAXY)

{

return false;

}

}

newCenterX = block.centerX;

newCenterY = block.centerY;

//满足条件后进行block的赋值

for (int i = 0; i < COUNT; i++)

{

block.x[i] = newX[i];

block.y[i] = newY[i];

}

block.centerX = newCenterX;

block.centerY = newCenterY;

return true;

}

//将block中数据复制到box中

void Tetris::blockToBox()

{

for (int i = 0; i < COUNT; i++)

{

int x = block.x[i];

int y = block.y[i];

if (y >= 0)

{

box[x][y] = 1;

}

}

}

//获得第一个整行的行数,并返回

int Tetris::getFirstFullLine()

{

//这里j从1开始就好

for (int j = 0; j < MAXY; j++)

{

bool judgement = true;

for (int i = 0; i < MAXX; i++)

{

if (box[i][j] == 0)

{

judgement = false;

break;

}

}

if (judgement)

{

return j;

}

}

return -1;

}

tetrisbox.h

#ifndef TETRISBOX_H

#define TETRISBOX_H

#include <QWidget>

#include <QPaintEvent>

#include <QPainter>

#include <QPalette>

#include <QPen>

#include <QBrush>

#include <QColor>

//为了使用Block

#include "tetris.h"

class TetrisBox : public QWidget

{

Q_OBJECT

public:

explicit TetrisBox(QWidget *parent = nullptr);

void updateTetris(Tetris tetris); //更新数据和视图

void paintEvent(QPaintEvent *event); //绘制视图

signals:

public slots:

private:

Block block; //用来储存Tetris中block的数据

int box[MAXX][MAXY]; //用来存储Tetris中box的数据

};

#endif // TETRISBOX_H

tetrisbox.cpp

#include "tetrisbox.h"

TetrisBox::TetrisBox(QWidget *parent) : QWidget(parent)

{

//对block初始化

for (int i = 0; i < COUNT; i++)

{

block.x[i] = -1;

block.y[i] = -1;

}

block.centerX = -1;

block.centerY = -1;

block.ID = -1;

//对box初始化

for (int i = 0; i < MAXX; i++)

{

for (int j = 0; j < MAXY; j++)

{

box[i][j] = 0;

}

}

//设置本游戏窗口的宽度和高度

//并设置背景为黑色

int w = Tetris::getWidth();

int h = Tetris::getHeight();

setFixedSize(w, h);

setPalette(QPalette(Qt::black));

setAutoFillBackground(true);

}

void TetrisBox::updateTetris(Tetris tetris)

{

//更新block

block = tetris.getBlock();

//更新box

for (int i = 0; i < MAXX; i++)

{

for (int j = 0; j < MAXY; j++)

{

box[i][j] = tetris.getBox(i, j);

}

}

repaint();

}

void TetrisBox::paintEvent(QPaintEvent *event)

{

QPainter painter(this);

QPen pen;

QBrush brush;

pen.setStyle(Qt::SolidLine);

pen.setColor(QColor(255, 255, 255));

brush.setStyle(Qt::SolidPattern);

brush.setColor(QColor(255, 255, 255));

painter.setPen(pen);

painter.setBrush(brush);

//绘制box中的内容

for (int i = 0; i < MAXX; i++)

{

for (int j = 0; j < MAXY; j++)

{

if (box[i][j] == 1)

{

int x = i * WIDTH + i * INTERVAL;

int y = j * HEIGHT + j * INTERVAL;

painter.drawRect(x, y, WIDTH, HEIGHT);

}

}

}

//绘制block中的内容

for (int i = 0; i < COUNT; i++)

{

int x = block.x[i];

int y = block.y[i];

int x1 = x * WIDTH + x * INTERVAL;

int y1 = y * HEIGHT + y * INTERVAL;

painter.drawRect(x1, y1, WIDTH, HEIGHT);

}

}

nexttetrisbox.h

#ifndef NEXTTETRISBOX_H

#define NEXTTETRISBOX_H

#include <QWidget>

#include <QWidget>

#include <QPaintEvent>

#include <QPen>

#include <QBrush>

#include <QPainter>

#include <QColor>

#include "tetris.h"

#define RESTX (MAXX - NEXTMAXX) / 2 //方块x坐标的转换常数

#define RESTY 4 //方块y坐标的转换常数

class NextTetrisBox : public QWidget

{

Q_OBJECT

public:

explicit NextTetrisBox(QWidget *parent = nullptr);

void updateNextTetris(Tetris tetris); //更新“下一个”的数据和视图

void paintEvent(QPaintEvent *event); //绘制视图

signals:

public slots:

private:

Block nextBlock; //“下一个”方块

};

#endif // NEXTTETRISBOX_H

nexttetris.cpp

#include "nexttetrisbox.h"

NextTetrisBox::NextTetrisBox(QWidget *parent) : QWidget(parent)

{

//初始化nextBlock

for (int i = 0; i < COUNT; i++)

{

nextBlock.x[i] = -1;

nextBlock.y[i] = -1;

}

nextBlock.centerX = -1;

nextBlock.centerY = -1;

nextBlock.ID = 0;

//设置本“下一个”窗口的宽度和高度

//并设置背景为黑色

int w = Tetris::getNextWidth();

int h = Tetris::getNextHeight();

setFixedSize(w, h);

setPalette(QPalette(Qt::black));

setAutoFillBackground(true);

}

void NextTetrisBox::updateNextTetris(Tetris tetris)

{

nextBlock = tetris.getNextBlock();

for (int i = 0; i < COUNT; i++)

{

nextBlock.x[i] -= RESTX;

nextBlock.y[i] += RESTY;

}

//重新绘制

repaint();

}

void NextTetrisBox::paintEvent(QPaintEvent *event)

{

QPainter painter(this);

QPen pen;

QBrush brush;

pen.setStyle(Qt::SolidLine);

pen.setColor(QColor(255, 255, 255));

brush.setStyle(Qt::SolidPattern);

brush.setColor(QColor(255, 255, 255));

painter.setPen(pen);

painter.setBrush(brush);

//绘制nextBlock中的内容

for (int i = 0; i < COUNT; i++)

{

int x = nextBlock.x[i];

int y = nextBlock.y[i];

int x1 = x * WIDTH + x * INTERVAL;

int y1 = y * HEIGHT + y * INTERVAL;

painter.drawRect(x1, y1, WIDTH, HEIGHT);

}

}

mainwindow.h

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include <QMainWindow>

#include <QMainWindow>

#include <QPainter>

#include <QEvent>

#include <QPaintEvent>

#include <QPen>

#include <QBrush>

#include <QColor>

#include <QKeyEvent>

#include <QTimer>

#include <QGridLayout>

#include <QLabel>

#include <QMessageBox>

#include <QDesktopWidget>

#include <QApplication>

#include "tetris.h"

#include "tetrisbox.h"

#include "nexttetrisbox.h"

//游戏的状态

#define STATUS_ON 0 //游戏正常进行

#define STATUS_PAUSE 1 //游戏暂停

#define STATUS_OFF 2 //游戏未开始

#define STATUS_END 3 //游戏结束

class MainWindow : public QMainWindow

{

Q_OBJECT

public:

MainWindow(QWidget *parent = 0);

~MainWindow();

void keyPressEvent(QKeyEvent *event); //响应键盘事件

void changeEvent(QEvent *event); //窗口最小化后暂停

void updateScore(); //更新分数的数据和显示

public slots:

void onTimer();

private:

int status; //游戏状态

Tetris tetris; //俄罗斯方块类对象

QTimer *timer; //计时器

TetrisBox *tetrisBox; //游戏窗口

NextTetrisBox *nextTetrisBox; //“下一个”窗口

QGridLayout *mainLayout; //mainLayout

QLabel *nextTetrisLabel; //“下一个”窗口的标签

QLabel *controlLabel; //“控制”标签

QLabel *w_controlLabel; //W键的标签

QLabel *s_controlLabel; //S键的标签

QLabel *a_controlLabel; //A键的标签

QLabel *d_controlLabel; //D键的标签

QLabel *h_controlLabel; //H键的标签

QLabel *j_controlLabel; //J键的标签

QLabel *c_controlLabel; //C键的标签

QLabel *m_controlLabel; //M键的标签

QLabel *scoreTitleLabel; //分数标题标签

QLabel *scoreLabel; //分数标签(用来显示分数)

};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)

: QMainWindow(parent)

{

//创建对象

tetrisBox = new TetrisBox;

nextTetrisBox = new NextTetrisBox;

nextTetrisLabel = new QLabel(tr("下一个:"));

controlLabel = new QLabel(tr("控制:"));

w_controlLabel = new QLabel(tr("W-旋转"));

s_controlLabel = new QLabel(tr("S-向下移动"));

a_controlLabel = new QLabel(tr("A-向左移动"));

d_controlLabel = new QLabel(tr("D-向右移动"));

h_controlLabel = new QLabel(tr("H-开始"));

j_controlLabel = new QLabel(tr("J-暂停"));

c_controlLabel = new QLabel(tr("C-重新开始"));

m_controlLabel = new QLabel(tr("M-结束游戏"));

scoreTitleLabel = new QLabel(tr("得分:"));

scoreLabel = new QLabel(tr("0"));

mainLayout = new QGridLayout;

//设置mainLayout的水平和横向的间隔为20

mainLayout->setHorizontalSpacing(20);

mainLayout->setVerticalSpacing(20);

//设置mainLayout居中

mainLayout->setAlignment(Qt::AlignCenter);

//添加各个widget

mainLayout->addWidget(tetrisBox, 0, 0, 14, 1);

mainLayout->addWidget(nextTetrisLabel, 0, 1);

mainLayout->addWidget(nextTetrisBox, 1, 1, 1, 2);

mainLayout->addWidget(controlLabel, 5, 1);

mainLayout->addWidget(w_controlLabel, 6, 1);

mainLayout->addWidget(s_controlLabel, 6, 2);

mainLayout->addWidget(a_controlLabel, 7, 1);

mainLayout->addWidget(d_controlLabel, 7, 2);

mainLayout->addWidget(h_controlLabel, 8, 1);

mainLayout->addWidget(j_controlLabel, 8, 2);

mainLayout->addWidget(c_controlLabel, 9, 1);

mainLayout->addWidget(m_controlLabel, 9, 2);

mainLayout->addWidget(scoreTitleLabel, 12, 1);

mainLayout->addWidget(scoreLabel, 12, 2);

//因为mainWindow已有一个layout,所以不能直接将mainLayout

//设置到mainWindow中,需要先将mainLayout设置为一个widget的layout

//在将widget设置为mainLayout的centralWidget

QWidget *widget = new QWidget(this);

widget->setLayout(mainLayout);

setCentralWidget(widget);

//设置窗口背景为灰色

setPalette(Qt::gray);

//设置窗口在电脑屏幕上居中

QDesktopWidget *desktopWidget = QApplication::desktop();

int w = (desktopWidget->width() - this->width()) / 2;

int h = 5;

move(w, h);

//初始化

status = STATUS_OFF;

nextTetrisBox->updateNextTetris(tetris);

setWindowTitle(tr("Game_Tetris - OFF"));

timer = new QTimer(this);

connect(timer, SIGNAL(timeout()), this, SLOT(onTimer()));

}

MainWindow::~MainWindow()

{

}

//相应键盘事件

void MainWindow::keyPressEvent(QKeyEvent *event)

{

//W键-进行旋转并更新游戏窗口内容

if (event->key() == Qt::Key_W)

{

if (tetris.rotate())

{

//需要游戏状态为:正常进行

if (status == STATUS_ON)

{

tetrisBox->updateTetris(tetris);

}

}

}

//A键-将方块向左移动并更新游戏窗口内容

else if (event->key() == Qt::Key_A)

{

//需要游戏状态为:正常进行

if (status == STATUS_ON)

{

if (tetris.moveToLeft())

{

tetrisBox->updateTetris(tetris);

}

}

}

//S键-将方块向下移动并更新游戏窗口内容

else if (event->key() == Qt::Key_S)

{

//需要游戏状态:正常进行

if (status == STATUS_ON)

{

if (tetris.moveToBottom())

{

tetrisBox->updateTetris(tetris);

nextTetrisBox->updateNextTetris(tetris);

updateScore();

}

else //游戏结束

{

//计时器停止

timer->stop();

//输出结束提示

QString str;

str += QString("Game Over!\nYour Score is: %1!").arg(tetris.getScore());

QMessageBox::information(this, tr("Game Over"), str);

//更改游戏状态为:游戏结束

status = STATUS_END;

setWindowTitle(tr("Game_Tetris - END"));

}

}

}

//D键-将方块向右移动并更新游戏窗口内容

else if (event->key() == Qt::Key_D)

{

//需要游戏状态为:正常进行

if (status == STATUS_ON)

{

if (tetris.moveToRight())

{

tetrisBox->updateTetris(tetris);

}

}

}

//H键-开始游戏

//不同状态的相应:

//之前状态 之后状态

//游戏暂停 -> 正常进行

//还未开始 -> 正常进行

//游戏结束 -> 正常进行

else if (event->key() == Qt::Key_H)

{

if (status == STATUS_PAUSE)

{

timer->start(500);

status = STATUS_ON;

setWindowTitle(tr("Game_Tetris - ON"));

}

else if (status == STATUS_OFF)

{

//初始化窗口视图

tetris.createBlock();

tetrisBox->updateTetris(tetris);

nextTetrisBox->updateNextTetris(tetris);

updateScore();

status = STATUS_ON;

setWindowTitle(tr("Game_Tetris - ON"));

timer->start(500);

}

else if (status == STATUS_END)

{

//初始化tetris

tetris.clear();

tetris.createBlock();

tetrisBox->updateTetris(tetris);

nextTetrisBox->updateNextTetris(tetris);

updateScore();

status = STATUS_ON;

setWindowTitle(tr("Game_Tetris - ON"));

timer->start(500);

}

}

//J键-游戏暂停

else if (event->key() == Qt::Key_J)

{

//需要游戏状态为:正常进行

if (status == STATUS_ON)

{

timer->stop();

status = STATUS_PAUSE;

setWindowTitle(tr("Game_Tetris - PAUSE"));

}

}

//C键-重新开始游戏

else if (event->key() == Qt::Key_C)

{

timer->stop();

tetris.clear();

tetrisBox->updateTetris(tetris);

nextTetrisBox->updateNextTetris(tetris);

updateScore();

status = STATUS_OFF;

setWindowTitle(tr("Game_Tetris - OFF"));

}

//M键-关闭游戏

else if (event->key() == Qt::Key_M)

{

close();

}

}

void MainWindow::onTimer()

{

if(tetris.moveToBottom())

{

tetrisBox->updateTetris(tetris);

nextTetrisBox->updateNextTetris(tetris);

updateScore();

}

else

{

timer->stop();

QString str;

str += QString("Game Over!\nYour Score is: %1!").arg(tetris.getScore());

QMessageBox::information(this, tr("Game Over"), str);

status = STATUS_END;

setWindowTitle(tr("Game_Tetris - END"));

}

}

void MainWindow::updateScore()

{

QString str;

int score = tetris.getScore();

str += QString("%1").arg(score);

scoreLabel->setText(str);

}

//若窗口最小化就停止计时器

void MainWindow::changeEvent(QEvent *event)

{

if (event->type() != QEvent::WindowStateChange)

{

return;

}

if (windowState() == Qt::WindowMinimized)

{

timer->stop();

}

}

main.cpp

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

MainWindow w;

w.show();

return a.exec();

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是 Qt实现俄罗斯方块 的全部内容, 来源链接: utcz.com/p/246049.html

回到顶部