本文实例为大家分享了Qt实现俄罗斯方块,供大家参考,具体内容如下
最近在学习Qt,用它来进行图形界面的开发还是很方便的,想着做一个小游戏来锻炼一下自己,就想到了小时候玩的俄罗斯方块。折腾了一段时间,虽然界面做的不美观,但是总算是实现了基本的功能。
首先我写了一个俄罗斯方块的类Tetris,通过这个类来进行这个游戏的数据的处理;然后游戏窗口是继承的QWidget类,用来显示游戏的方块;“下一个方块”窗口也是继承的QWidget类,用来显示下一个方块;控制提示和分数的显示用的QLabel。然后将将这些控件整合到继承自QMainWindow的mainWindow类。运行的结果如下:
Tetris类:一共有7中不同形状的方块(如下图),每个方块由四个方格组成,Block结构体用来存储方块的方格坐、中心方格坐标、ID等数据,移动中的方块和下移个方块都是通过这个结构体来操作的;已经落下的方块的方格存储在二维数组box[][]中,x坐标从左到右为正方向,y坐标从上到下为正方向(如下图)。
tetris.h
#ifndef TETRIS_H #define TETRIS_H //为了获得随机数 #include#include #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; i0; j--) { for (int i = 0; i = MAXX) { return false; } //y坐标在0 - MAXY之间就对box中的状态进行判定 //box中为1则返回false if (newY[i] >=0 && newY[i] = MAXY) { return false; } } newCenterX = block.centerX + dx; newCenterY = block.centerY + dy; //满足条件就将新的x和y坐标赋值给block for (int i = 0; i = MAXX) { return false; } //y坐标在0 - MAXY 之间就对box中的状态进行判定 //box中为1则返回false if (newY[i] >=0 && newY[i] = MAXY) { return false; } } newCenterX = block.centerX; newCenterY = block.centerY; //满足条件后进行block的赋值 for (int i = 0; i = 0) { box[x][y] = 1; } } } //获得第一个整行的行数,并返回 int Tetris::getFirstFullLine() { //这里j从1开始就好 for (int j = 0; j
tetrisbox.h
#ifndef TETRISBOX_H #define TETRISBOX_H #include#include #include #include #include #include #include //为了使用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
nexttetrisbox.h
#ifndef NEXTTETRISBOX_H #define NEXTTETRISBOX_H #include#include #include #include #include #include #include #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
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include#include #include #include #include #include #include #include #include #include #include #include #include #include #include #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" #includeint main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。