Qt實(shí)現(xiàn)俄羅斯方塊
本文實(shí)例為大家分享了Qt實(shí)現(xiàn)俄羅斯方塊,供大家參考,具體內(nèi)容如下
最近在學(xué)習(xí)Qt,用它來進(jìn)行圖形界面的開發(fā)還是很方便的,想著做一個(gè)小游戲來鍛煉一下自己,就想到了小時(shí)候玩的俄羅斯方塊。折騰了一段時(shí)間,雖然界面做的不美觀,但是總算是實(shí)現(xiàn)了基本的功能。
首先我寫了一個(gè)俄羅斯方塊的類Tetris,通過這個(gè)類來進(jìn)行這個(gè)游戲的數(shù)據(jù)的處理;然后游戲窗口是繼承的QWidget類,用來顯示游戲的方塊;“下一個(gè)方塊”窗口也是繼承的QWidget類,用來顯示下一個(gè)方塊;控制提示和分?jǐn)?shù)的顯示用的QLabel。然后將將這些控件整合到繼承自QMainWindow的mainWindow類。運(yùn)行的結(jié)果如下:

Tetris類:一共有7中不同形狀的方塊(如下圖),每個(gè)方塊由四個(gè)方格組成,Block結(jié)構(gòu)體用來存儲(chǔ)方塊的方格坐、中心方格坐標(biāo)、ID等數(shù)據(jù),移動(dòng)中的方塊和下移個(gè)方塊都是通過這個(gè)結(jié)構(gòu)體來操作的;已經(jīng)落下的方塊的方格存儲(chǔ)在二維數(shù)組box[][]中,x坐標(biāo)從左到右為正方向,y坐標(biāo)從上到下為正方向(如下圖)。


項(xiàng)目源文件
- tetris.h
- tetris.cpp
- tetrisbox.h
- tetrisbox.cpp
- nexttetris.h
- nexttetris.cpp
- mainwindow.h
- mainwindow.cpp
tetris.h
#ifndef TETRIS_H
#define TETRIS_H
//為了獲得隨機(jī)數(shù)
#include <cstdlib>
#include <ctime>
#define MAXX 10 //顯示窗口的橫向格數(shù)
#define MAXY 20 //顯示窗口的豎向格數(shù)
#define NEXTMAXX 6 //“下一個(gè)”顯示窗口的橫向格數(shù)
#define NEXTMAXY 6 //“下一個(gè)”顯示窗口的豎向格數(shù)
#define WIDTH 30 //單格的寬度
#define HEIGHT 30 //單格的高度
#define INTERVAL 4 //單格之間的間隔
#define COUNT 4 //每個(gè)方塊的格數(shù)
//Block結(jié)構(gòu)體:一個(gè)方塊
struct Block
{
int x[COUNT]; //方塊單格的x坐標(biāo)
int y[COUNT]; //方塊單格的y坐標(biāo)
int centerX; //方塊的中心x坐標(biāo)
int centerY; //方塊的中心y坐標(biāo)
int ID; //方塊的ID
};
class Tetris
{
public:
Tetris();
void createBlock(); //創(chuàng)建當(dāng)前方塊
Block getNextBlock(); //獲得下一個(gè)方塊
Block getBlock(); //獲得當(dāng)前方塊
int getScore(); //獲得分?jǐn)?shù)
int getBox(int x, int y); //獲得相應(yīng)坐標(biāo)的狀態(tài)
bool rotate(); //旋轉(zhuǎn)
bool moveToLeft(); //向左移動(dòng)
bool moveToRight(); //向右移動(dòng)
bool moveToBottom(); //向下移動(dòng)
bool isEnd(); //判斷是否結(jié)束
void killLines(); //消去整行
void clear(); //重新初始化
static int getWidth(); //獲得窗口的寬度
static int getHeight(); //獲得窗口的高度
static int getNextWidth(); //獲得“下一個(gè)”窗口的寬度
static int getNextHeight(); //獲得“下一個(gè)”窗口的高度
private:
void createNextBlock(); //創(chuàng)建下一個(gè)方塊
bool move(int dx, int dy); //是否可以移動(dòng)
void blockToBox(); //將block中的數(shù)據(jù)轉(zhuǎn)移到box中
bool isRotatable(); //是否可以旋轉(zhuǎn)
int getFirstFullLine(); //獲得第一個(gè)整行
private:
int score; //分?jǐn)?shù)
Block block; //當(dāng)前方塊
Block nextBlock; //下一個(gè)方塊
int box[MAXX][MAXY];//方格的坐標(biāo)系 1表示右方格,0表示沒有方格
};
#endif // TETRIS_H
Tetris.cpp
#include "tetris.h"
Tetris::Tetris()
{
//初始化隨機(jī)數(shù)發(fā)生器
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;
//創(chuàng)建下一個(gè)方塊
createNextBlock();
}
//創(chuàng)建當(dāng)前方塊
//將上一次生成的下一個(gè)方塊nextBlock復(fù)制給block
//并創(chuàng)建下一個(gè)nextBlock
void Tetris::createBlock()
{
//nextBlock復(fù)制給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;
//創(chuàng)建下一個(gè)nextblock
createNextBlock();
}
//返回下一個(gè)方塊
Block Tetris::getNextBlock()
{
return nextBlock;
}
//返回當(dāng)前方塊
Block Tetris::getBlock()
{
return block;
}
//返回當(dāng)前分?jǐn)?shù)
int Tetris::getScore()
{
return score;
}
//返回坐標(biāo)(x,y)的值,以判斷是否右方格
int Tetris::getBox(int x, int y)
{
return box[x][y];
}
//旋轉(zhuǎn)當(dāng)前方塊
//旋轉(zhuǎn)成功返回true,否則返回false
bool Tetris::rotate()
{
if (isRotatable())
{
return true;
}
else
{
return false;
}
}
//將當(dāng)前方塊向左移動(dòng)一格
//成功返回true,否則返回false
bool Tetris::moveToLeft()
{
if (move(-1, 0))
{
return true;
}
else
{
return false;
}
}
//將當(dāng)前方塊向右移動(dòng)一格
//成功返回true,否則返回false
bool Tetris::moveToRight()
{
if (move(1, 0))
{
return true;
}
else
{
return false;
}
}
//將方塊向下移動(dòng)一格
//成功返回true, 游戲結(jié)束返回false
bool Tetris::moveToBottom()
{
if (!move(0, 1))
{
//移動(dòng)不成功
blockToBox(); //將當(dāng)前方塊復(fù)制到box中
killLines(); //消行
//判斷是否結(jié)束
//否則創(chuàng)建新的方塊
if(isEnd())
{
return false;
}
else
{
createBlock();
}
}
return true;
}
//判斷游戲是否結(jié)束
//結(jié)束條件為第一行有方格
bool Tetris::isEnd()
{
int j = 0;
for (int i = 0; i < MAXX; i++)
{
if (box[i][j] == 1)
{
return true;
}
}
return false;
}
//消掉整行并進(jìn)行分?jǐn)?shù)獎(jiǎng)勵(lì)
void Tetris::killLines()
{
int count = 0; //一次消掉的行數(shù)
//通過getFirstFullLine()函數(shù)獲得從上到下第一個(gè)整行
//并將其上的行向下平移一行,達(dá)到消行的效果
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++;
}
//消行的分?jǐn)?shù)獎(jiǎng)勵(lì)
score += count * count * 10;
}
//對(duì)成員變量進(jìn)行初始化,重新開始游戲
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;
//創(chuàng)建下一個(gè)方塊
createNextBlock();
}
//獲得游戲窗口的寬度
int Tetris::getWidth()
{
return MAXX * WIDTH + (MAXX - 1) * INTERVAL;
}
//獲得游戲窗口的高度
int Tetris::getHeight()
{
return MAXY * HEIGHT + (MAXY - 1) * INTERVAL;
}
//獲得“下一個(gè)”窗口的寬度
int Tetris::getNextWidth()
{
return NEXTMAXX * WIDTH + (NEXTMAXX - 1) * INTERVAL;
}
//獲得“下一個(gè)”窗口的高度
int Tetris::getNextHeight()
{
return NEXTMAXY * WIDTH + (NEXTMAXY - 1) * INTERVAL;
}
//創(chuàng)建“下一個(gè)”方塊
void Tetris::createNextBlock()
{
int centerX = (MAXX - 1) / 2; //中心x坐標(biāo)
int ID = rand() % 7; //獲得0 - 6的隨機(jī)數(shù)
//根據(jù)不同的隨機(jī)數(shù)創(chuàng)建方塊
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;
}
}
//可以移動(dòng)就對(duì)block進(jìn)行變換,返回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;
//對(duì)變換后的坐標(biāo)進(jìn)行判定
//x坐標(biāo)超出范圍返回false
if (newX[i] < 0 || newX[i] >= MAXX)
{
return false;
}
//y坐標(biāo)在0 - MAXY之間就對(duì)box中的狀態(tài)進(jìn)行判定
//box中為1則返回false
if (newY[i] >=0 && newY[i] < MAXY)
{
if (box[newX[i]][newY[i]] == 1)
{
return false;
}
}//y坐標(biāo)超出最大值返回false
else if (newY[i] >= MAXY)
{
return false;
}
}
newCenterX = block.centerX + dx;
newCenterY = block.centerY + dy;
//滿足條件就將新的x和y坐標(biāo)賦值給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;
}
//可以旋轉(zhuǎn)就對(duì)block進(jìn)行變換,返回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;
//對(duì)變換后的坐標(biāo)進(jìn)行判定
//x坐標(biāo)超出范圍返回false
if (newX[i] < 0 || newX[i] >= MAXX)
{
return false;
}
//y坐標(biāo)在0 - MAXY 之間就對(duì)box中的狀態(tài)進(jìn)行判定
//box中為1則返回false
if (newY[i] >=0 && newY[i] < MAXY)
{
if (box[newX[i]][newY[i]] == 1)
{
return false;
}
}//y坐標(biāo)超過最大值返回false
else if (newY[i] >= MAXY)
{
return false;
}
}
newCenterX = block.centerX;
newCenterY = block.centerY;
//滿足條件后進(jìn)行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中數(shù)據(jù)復(fù)制到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;
}
}
}
//獲得第一個(gè)整行的行數(shù),并返回
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); //更新數(shù)據(jù)和視圖
void paintEvent(QPaintEvent *event); //繪制視圖
signals:
public slots:
private:
Block block; //用來儲(chǔ)存Tetris中block的數(shù)據(jù)
int box[MAXX][MAXY]; //用來存儲(chǔ)Tetris中box的數(shù)據(jù)
};
#endif // TETRISBOX_H
tetrisbox.cpp
#include "tetrisbox.h"
TetrisBox::TetrisBox(QWidget *parent) : QWidget(parent)
{
//對(duì)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;
//對(duì)box初始化
for (int i = 0; i < MAXX; i++)
{
for (int j = 0; j < MAXY; j++)
{
box[i][j] = 0;
}
}
//設(shè)置本游戲窗口的寬度和高度
//并設(shè)置背景為黑色
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中的內(nèi)容
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中的內(nèi)容
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坐標(biāo)的轉(zhuǎn)換常數(shù)
#define RESTY 4 //方塊y坐標(biāo)的轉(zhuǎn)換常數(shù)
class NextTetrisBox : public QWidget
{
Q_OBJECT
public:
explicit NextTetrisBox(QWidget *parent = nullptr);
void updateNextTetris(Tetris tetris); //更新“下一個(gè)”的數(shù)據(jù)和視圖
void paintEvent(QPaintEvent *event); //繪制視圖
signals:
public slots:
private:
Block nextBlock; //“下一個(gè)”方塊
};
#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;
//設(shè)置本“下一個(gè)”窗口的寬度和高度
//并設(shè)置背景為黑色
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中的內(nèi)容
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"
//游戲的狀態(tài)
#define STATUS_ON 0 //游戲正常進(jìn)行
#define STATUS_PAUSE 1 //游戲暫停
#define STATUS_OFF 2 //游戲未開始
#define STATUS_END 3 //游戲結(jié)束
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
void keyPressEvent(QKeyEvent *event); //響應(yīng)鍵盤事件
void changeEvent(QEvent *event); //窗口最小化后暫停
void updateScore(); //更新分?jǐn)?shù)的數(shù)據(jù)和顯示
public slots:
void onTimer();
private:
int status; //游戲狀態(tài)
Tetris tetris; //俄羅斯方塊類對(duì)象
QTimer *timer; //計(jì)時(shí)器
TetrisBox *tetrisBox; //游戲窗口
NextTetrisBox *nextTetrisBox; //“下一個(gè)”窗口
QGridLayout *mainLayout; //mainLayout
QLabel *nextTetrisLabel; //“下一個(gè)”窗口的標(biāo)簽
QLabel *controlLabel; //“控制”標(biāo)簽
QLabel *w_controlLabel; //W鍵的標(biāo)簽
QLabel *s_controlLabel; //S鍵的標(biāo)簽
QLabel *a_controlLabel; //A鍵的標(biāo)簽
QLabel *d_controlLabel; //D鍵的標(biāo)簽
QLabel *h_controlLabel; //H鍵的標(biāo)簽
QLabel *j_controlLabel; //J鍵的標(biāo)簽
QLabel *c_controlLabel; //C鍵的標(biāo)簽
QLabel *m_controlLabel; //M鍵的標(biāo)簽
QLabel *scoreTitleLabel; //分?jǐn)?shù)標(biāo)題標(biāo)簽
QLabel *scoreLabel; //分?jǐn)?shù)標(biāo)簽(用來顯示分?jǐn)?shù))
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
//創(chuàng)建對(duì)象
tetrisBox = new TetrisBox;
nextTetrisBox = new NextTetrisBox;
nextTetrisLabel = new QLabel(tr("下一個(gè):"));
controlLabel = new QLabel(tr("控制:"));
w_controlLabel = new QLabel(tr("W-旋轉(zhuǎn)"));
s_controlLabel = new QLabel(tr("S-向下移動(dòng)"));
a_controlLabel = new QLabel(tr("A-向左移動(dòng)"));
d_controlLabel = new QLabel(tr("D-向右移動(dòng)"));
h_controlLabel = new QLabel(tr("H-開始"));
j_controlLabel = new QLabel(tr("J-暫停"));
c_controlLabel = new QLabel(tr("C-重新開始"));
m_controlLabel = new QLabel(tr("M-結(jié)束游戲"));
scoreTitleLabel = new QLabel(tr("得分:"));
scoreLabel = new QLabel(tr("0"));
mainLayout = new QGridLayout;
//設(shè)置mainLayout的水平和橫向的間隔為20
mainLayout->setHorizontalSpacing(20);
mainLayout->setVerticalSpacing(20);
//設(shè)置mainLayout居中
mainLayout->setAlignment(Qt::AlignCenter);
//添加各個(gè)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);
//因?yàn)閙ainWindow已有一個(gè)layout,所以不能直接將mainLayout
//設(shè)置到mainWindow中,需要先將mainLayout設(shè)置為一個(gè)widget的layout
//在將widget設(shè)置為mainLayout的centralWidget
QWidget *widget = new QWidget(this);
widget->setLayout(mainLayout);
setCentralWidget(widget);
//設(shè)置窗口背景為灰色
setPalette(Qt::gray);
//設(shè)置窗口在電腦屏幕上居中
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()
{
}
//相應(yīng)鍵盤事件
void MainWindow::keyPressEvent(QKeyEvent *event)
{
//W鍵-進(jìn)行旋轉(zhuǎn)并更新游戲窗口內(nèi)容
if (event->key() == Qt::Key_W)
{
if (tetris.rotate())
{
//需要游戲狀態(tài)為:正常進(jìn)行
if (status == STATUS_ON)
{
tetrisBox->updateTetris(tetris);
}
}
}
//A鍵-將方塊向左移動(dòng)并更新游戲窗口內(nèi)容
else if (event->key() == Qt::Key_A)
{
//需要游戲狀態(tài)為:正常進(jìn)行
if (status == STATUS_ON)
{
if (tetris.moveToLeft())
{
tetrisBox->updateTetris(tetris);
}
}
}
//S鍵-將方塊向下移動(dòng)并更新游戲窗口內(nèi)容
else if (event->key() == Qt::Key_S)
{
//需要游戲狀態(tài):正常進(jìn)行
if (status == STATUS_ON)
{
if (tetris.moveToBottom())
{
tetrisBox->updateTetris(tetris);
nextTetrisBox->updateNextTetris(tetris);
updateScore();
}
else //游戲結(jié)束
{
//計(jì)時(shí)器停止
timer->stop();
//輸出結(jié)束提示
QString str;
str += QString("Game Over!\nYour Score is: %1!").arg(tetris.getScore());
QMessageBox::information(this, tr("Game Over"), str);
//更改游戲狀態(tài)為:游戲結(jié)束
status = STATUS_END;
setWindowTitle(tr("Game_Tetris - END"));
}
}
}
//D鍵-將方塊向右移動(dòng)并更新游戲窗口內(nèi)容
else if (event->key() == Qt::Key_D)
{
//需要游戲狀態(tài)為:正常進(jìn)行
if (status == STATUS_ON)
{
if (tetris.moveToRight())
{
tetrisBox->updateTetris(tetris);
}
}
}
//H鍵-開始游戲
//不同狀態(tài)的相應(yīng):
//之前狀態(tài) 之后狀態(tài)
//游戲暫停 -> 正常進(jìn)行
//還未開始 -> 正常進(jìn)行
//游戲結(jié)束 -> 正常進(jìn)行
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)
{
//需要游戲狀態(tài)為:正常進(jìn)行
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鍵-關(guān)閉游戲
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);
}
//若窗口最小化就停止計(jì)時(shí)器
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();
}
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語言實(shí)現(xiàn)大數(shù)據(jù)文件的內(nèi)存映射機(jī)制
這篇文章主要介紹了C語言實(shí)現(xiàn)大數(shù)據(jù)文件的內(nèi)存映射機(jī)制的相關(guān)資料,需要的朋友可以參考下2017-01-01
C++LeetCode數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)詳解
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode數(shù)據(jù)結(jié)構(gòu),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
C++實(shí)現(xiàn)LeetCode(33.在旋轉(zhuǎn)有序數(shù)組中搜索)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(33.在旋轉(zhuǎn)有序數(shù)組中搜索),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
深入探討:main函數(shù)執(zhí)行完畢后,是否可能會(huì)再執(zhí)行一段代碼?
本篇文章是對(duì)main函數(shù)執(zhí)行完畢后,是否可能會(huì)再執(zhí)行一段代碼,進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
利用C++單例模式實(shí)現(xiàn)高性能配置管理器
這篇文章主要為大家詳細(xì)介紹了如何利用C++單例模式實(shí)現(xiàn)高性能配置管理器,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-04-04
利用Matlab仿真實(shí)現(xiàn)圖像煙霧識(shí)別(k-means聚類圖像分割+LBP+PCA+SVM)
本文主要介紹了利用k-means聚類實(shí)現(xiàn)圖像分割+LBP算法進(jìn)行特征提取+PCA算法進(jìn)行特征降維+SVM算法訓(xùn)練二分類模型從而實(shí)現(xiàn)煙霧識(shí)別。文中介紹很詳細(xì),感興趣的朋友可以了解一下2021-12-12

