使用(C++)QT实现经典小游戏(俄罗斯方块)

高高的博客 2024-07-11 09:35:03 阅读 88

一、简介

        学习QT有段时间了,但是也没用来做过啥,这两日就突然想到了这个游戏,于是就打算用QT写一个,也不是纯纯自己写的代码,在写之前我也是找了几个别人的项目看了一下,学习了框架的搭建,和某些类的使用。

首先我也是将整个程序分作了四块:

一、方块类:主要就是对每个方块的坐标的一个封装

二、游戏区域:根据实时的要求,根据坐标画出方块

三、下一块方块:刷新下一块方块

四、计分区域:根据得分显示关卡、分数等

二、代码实现

         在代码中都已经写了注释了,外面就不多累述了

1.ui界面

NextArea和GameArea都是由Qwidget提升上来的。

2.item方块类

2.1头文件

<code>/*

* 俄罗斯方块的方块类文件

*/

#ifndef ITEM_H

#define ITEM_H

#pragma once

#include <QObject>

#include <QWidget>

#include <QVector>

#include <QPoint>

#include <QPainter>

typedef QVector<QPoint> povector; //坐标容器

enum ItemType//7种方块,四种朝向

{

ItemType_I = 0,

ItemType_L1,

ItemType_L2,

ItemType_T,

ItemType_O,

ItemType_Z1,

ItemType_Z2,

ItemType_MAX,

};

class Item

{

public:

Item(){}

Item(ItemType type,int direction);//有参构造方块

~Item(){}

void NewItem(int random_number);//通过随机的一个数来创建一个新的方块

void initpoint(ItemType type,int direction);//根据方块的类型和朝向初始化四个小方块的坐标

ItemType type(); //返回方块的类型

int direction(); //返回方块的朝向

void ClearPoints();//清除坐标信息

void drawItem(QPainter &painter,int x,int y,int width,int height); //根据坐标和宽高画图形

void changedirection(int direction=1); //改变方块的朝向,我的朝向加1即为下一个朝向,顺时针旋转90°

void moveItem(int x,int y);//横向移动x格,竖向移动y格

void movetoItem(int x,int y);//移动到(x,y)位置

void AddPoints(povector& points); //添加方块格子坐标

void Deleterow(int y); //删除坐标为y的一行

void MoveDown(int nRow, int y);//删除行以后其它的方块下移

public:

ItemType mytype; //我的方块

int mydirection; //我的方块朝向

QPoint mypos; //我的方块位置坐标

povector myPoint; //我的方块四小块的坐标

};

#endif // ITEM_H

2.2源文件

#include "item.h"

//创建方块

void Item::NewItem(int random_number)

{

myPoint.clear();

qsrand(random_number);//获取随机数

ItemType type = (ItemType)(qrand()%ItemType_MAX); // 产生随机的方块类型

int direction = qrand()%4; 产生随机的方块的朝向

initpoint(type,direction);

mytype = type;

mydirection = direction;

}

//初始化方块位置信息

void Item::initpoint(ItemType type, int direction)

{

direction = 0;

switch (type)

{

case ItemType_I://长条形

{

if(0==direction%2)//朝向0 2都是横长条

{

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

{

myPoint.append(mypos + QPoint( i,0));

}

}

else//朝向1 3都是竖长条

{

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

{

myPoint.append(mypos + QPoint(0,i-3));

}

}

break;

}

case ItemType_L1://右枪形

{

if(0==direction)//朝向0

{

myPoint.append(mypos + QPoint( 0,0));// 1 0 0

myPoint.append(mypos + QPoint( 0,1));// 1 0 0

myPoint.append(mypos + QPoint( 0,2));// 1 1 0

myPoint.append(mypos + QPoint( 1,2));// 0 0 0

}

else if(1==direction)//朝向1

{

myPoint.append(mypos + QPoint( 0,1));// 0 0 0

myPoint.append(mypos + QPoint( 1,1));// 1 1 1

myPoint.append(mypos + QPoint( 2,1));// 1 0 0

myPoint.append(mypos + QPoint( 0,2));// 0 0 0

}

else if(2==direction)//朝向2

{

myPoint.append(mypos + QPoint( 0,0));

myPoint.append(mypos + QPoint( 1,0));// 1 1 0

myPoint.append(mypos + QPoint( 1,1));// 0 1 0

myPoint.append(mypos + QPoint( 1,2));// 0 1 0

}

else//朝向3

{

myPoint.append(mypos + QPoint( 0,2));//0 0 0

myPoint.append(mypos + QPoint( 1,2));//0 0 1

myPoint.append(mypos + QPoint( 2,2));//1 1 1

myPoint.append(mypos + QPoint( 2,1));//

}

break;

}

case ItemType_L2://左枪形

{

if(0==direction)//朝向0

{

myPoint.append(mypos + QPoint( 1,0));//0 1 0 0

myPoint.append(mypos + QPoint( 1,1));//0 1 0 0

myPoint.append(mypos + QPoint( 1,2));//1 1 0 0

myPoint.append(mypos + QPoint( 0,2));//0 0 0 0

}

else if(1==direction)//朝向1

{

myPoint.append(mypos + QPoint( 0,1));// 0 0 0

myPoint.append(mypos + QPoint( 0,2));// 1 0 0

myPoint.append(mypos + QPoint( 1,2));// 1 1 1

myPoint.append(mypos + QPoint( 2,2));// 0 0 0

}

else if(2==direction)//朝向2

{

myPoint.append(mypos + QPoint( 0,0));//

myPoint.append(mypos + QPoint( 1,0));// 1 1 0

myPoint.append(mypos + QPoint( 0,1));// 1 0 0

myPoint.append(mypos + QPoint( 0,2));// 1 0 0

}

else//朝向3

{

myPoint.append(mypos + QPoint( 0,1));//0 0 0 0

myPoint.append(mypos + QPoint( 1,1));//1 1 1 0

myPoint.append(mypos + QPoint( 2,1));//0 0 1 0

myPoint.append(mypos + QPoint( 2,2));//0 0 0 0

}

break;

}

case ItemType_T://T形

{

if(0==direction)//朝向0

{

myPoint.append(mypos + QPoint( 1,0));//0 1 0 0

myPoint.append(mypos + QPoint( 1,1));//1 1 1 0

myPoint.append(mypos + QPoint( 0,1));//0 0 0 0

myPoint.append(mypos + QPoint( 2,1));//0 0 0 0

}

else if(1==direction)//朝向1

{

myPoint.append(mypos + QPoint( 0,0));// 1 0 0

myPoint.append(mypos + QPoint( 0,1));// 1 1 0

myPoint.append(mypos + QPoint( 0,2));// 1 0 0

myPoint.append(mypos + QPoint( 1,1));// 0 0 0

}

else if(2==direction)//朝向2

{

myPoint.append(mypos + QPoint( 0,0));

myPoint.append(mypos + QPoint( 1,0));//1 1 1 0

myPoint.append(mypos + QPoint( 2,0));//0 1 0 0

myPoint.append(mypos + QPoint( 1,1));//0 0 0 0

}

else//朝向3

{

myPoint.append(mypos + QPoint( 1,0));//0 1 0 0

myPoint.append(mypos + QPoint( 0,1));//1 1 0 0

myPoint.append(mypos + QPoint( 1,1));//0 1 0 0

myPoint.append(mypos + QPoint( 1,2));//0 0 0 0

}

break;

}

case ItemType_O://正方形

{

myPoint.append(mypos + QPoint( 0,0));//1 1 0 0

myPoint.append(mypos + QPoint( 0,1));//1 1 0 0

myPoint.append(mypos + QPoint( 1,0));//0 0 0 0

myPoint.append(mypos + QPoint( 1,1));//0 0 0 0

break;

}

case ItemType_Z1://右Z形

{

if(0==direction%2)//朝向0/2

{

myPoint.append(mypos + QPoint( 0,0));// 1 0 0

myPoint.append(mypos + QPoint( 0,1));// 1 1 0

myPoint.append(mypos + QPoint( 1,1));// 0 1 0

myPoint.append(mypos + QPoint( 1,2));// 0 0 0

}

else//朝向1/3

{

myPoint.append(mypos + QPoint( 0,1));//

myPoint.append(mypos + QPoint( 1,0));//0 1 1 0

myPoint.append(mypos + QPoint( 1,1));//1 1 0 0

myPoint.append(mypos + QPoint( 2,0));//0 0 0 0

}

break;

}

case ItemType_Z2://左Z形

{

if(0==direction%2)//朝向0/2

{

myPoint.append(mypos + QPoint( 1,0));// 0 1 0

myPoint.append(mypos + QPoint( 0,1));// 1 1 0

myPoint.append(mypos + QPoint( 1,1));// 1 0 0

myPoint.append(mypos + QPoint( 0,2));// 0 0 0

}

else//朝向1/3

{

myPoint.append(mypos + QPoint( 0,0));

myPoint.append(mypos + QPoint( 1,0));//1 1 0 0

myPoint.append(mypos + QPoint( 1,1));//0 1 1 0

myPoint.append(mypos + QPoint( 2,1));//0 0 0 0

}

break;

}

default:

break;

}

}

//方块类型

ItemType Item::type()

{

return mytype;

}

//方块朝向

int Item::direction()

{

return mydirection;

}

//清除方块位置信息

void Item::ClearPoints()

{

myPoint.clear();

}

//画方块

void Item::drawItem(QPainter &painter,int x,int y,int width, int height)

{

for (int i = 0; i < myPoint.size(); i++)

{

QPoint pt = myPoint[i];

if(pt.y()>=1)

{

painter.drawRect(QRect(x+pt.x() * width,y+pt.y() * height, width, height));

}

}

}

//改变方块朝向

void Item::changedirection(int direction)

{

mydirection = (mydirection+direction)%4;

initpoint(mytype,mydirection);

}

//移动方块

void Item::moveItem(int x, int y)

{

for (int i = 0; i < myPoint.size(); i++)

{

int x1 = myPoint[i].x() + x;

int y1 = myPoint[i].y() + y;

myPoint[i].setX(x1);

myPoint[i].setY(y1);

}

mypos += QPoint(x, y);

}

//将方块移动到指定位置

void Item::movetoItem(int x, int y)

{

for (int i = 0; i < myPoint.size(); i++)

{

int x1 = myPoint[i].x()-mypos.x() + x;

int y1 = myPoint[i].y()-mypos.y() + y;

myPoint[i].setX(x1);

myPoint[i].setY(y1);

}

mypos = QPoint(x, y);

}

//添加方块坐标

void Item::AddPoints(povector &points)

{

for(int i=0;i<points.size();i++) // 遍历Point

{

if(!myPoint.contains(points[i])) //如果myPoint中没有

myPoint.append(points[i]); //添加进myPoint

}

}

//第nRow行以上的部分下移y行,用在消格之后

void Item::MoveDown(int nRow, int y)

{

for(int i=0;i<myPoint.size();i++) //遍历myPoint ( 方块类形坐标容噐)

{

if(myPoint[i].y()<nRow) //行坐标小于nRow 的

myPoint[i].setY(myPoint[i].y()+y); //行标加y,后回写

}

}

//删除第y行

void Item::Deleterow(int y)

{

QVector<QPoint> newPoints; //新建一个新的容器

for(int i=0;i<myPoint.size();i++) //遍历mPoints ( 方块类形坐标容噐)

{

if(myPoint[i].y()!=y) //如果行坐标不等于y,

newPoints.append(myPoint[i]); //添加到新的点容器

}

myPoint=newPoints; //新的容器回写到mPoints,等于y的方块便不再绘画

}

3.GameArea游戏窗口

3.1头文件

/*

* 俄罗斯方块的游戏区域文件

*/

#ifndef GAMEAREA_H

#define GAMEAREA_H

#include <QWidget>

#include "item.h"

#include <QTimerEvent>

#include <QMessageBox>

#include <QKeyEvent>

#include <QTime>

class GameArea : public QWidget

{

Q_OBJECT

public:

explicit GameArea(QWidget *parent = nullptr);

void DrawBKRects(); //画游戏区域

void DrawFixedRects(); //画下落后已固定不动的方块

void DrawCurItem(); //画当前下落中的方块

void NewGame(); //创建新游戏界面

void KeyPressed(int key); //收到按键值处理

bool HitSide(); //判断当前下落方块是否超左右边界

bool HitBottom(); //判断当前下落方块是否达到底部

bool HitTop(); //判断当前下落方块是否达到顶部

void AddToFixedRects(); //把当前方块加入到 固定方块

void Deleterow(); //删除完整的行

int GetLevelTime(int level); //获取不同等级关卡对应的定时器时间,关卡越高,时间越快(短)。比如1关=1s,2关=900ms,3关=800ms

signals:

void sigUpdateNextItem(ItemType type, int direction); //下一个方块刷新信号

void sigUpdateScore(int nScore); //刷新分数

void sigUpdateLevel(int nSpeed); //刷新等级

void sigPause(bool bPaused); //暂停信号

protected:

void paintEvent(QPaintEvent *e); //绘图事件

void timerEvent(QTimerEvent *e); //定时器事件

private:

Item myFixItems; //已落下、固定住了的方块们

Item myCurItem; //当前移动中的方块

Item myNextItem; //下一个方块

int myTimerID; //定时器ID

int myScore; //得分

int myLevel; //关卡

bool myStop; //是否暂停

};

#endif // GAMEAREA_H

3.2源文件

#include "gamearea.h"

#include <QDebug>

//默认游戏区域为15*20的单元格,每个单元格尺寸40*40像素

#define MAX_COLUME15

#define MAX_ROW20

#define RECT_WIDTH40

#define RECT_HEIGHT40

//GameArea类初始化

GameArea::GameArea(QWidget *parent) : QWidget(parent)

{

myScore = 0;

myLevel = 1;

myStop = false;

setMinimumSize(MAX_COLUME*RECT_WIDTH, MAX_ROW*RECT_HEIGHT);

}

//画游戏区域的背景

void GameArea::DrawBKRects()

{

//画背景边框

QPainter painter(this);

painter.setBrush(QColor("#696969"));

painter.setPen(Qt::NoPen);

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

{

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

{

if (i == 0 || i == MAX_COLUME - 1 || j == 0 || j == MAX_ROW - 1)

{

painter.drawRect(i*RECT_WIDTH, j*RECT_HEIGHT, RECT_WIDTH, RECT_HEIGHT);

}

}

}

}

//画已经下落到底部固定的方块

void GameArea::DrawFixedRects()

{

QPainter painter(this);

painter.setBrush(QColor("#D3D3D3"));

painter.setPen(QPen(QColor(Qt::black), 1));

myFixItems.drawItem(painter,0,0,RECT_WIDTH,RECT_HEIGHT);

}

//画当前正在下落中的方块

void GameArea::DrawCurItem()

{

QPainter painter(this);

painter.setBrush(QColor("#FFDEAD"));

painter.setPen(QPen(QColor(Qt::black), 1));

myCurItem.drawItem(painter,0,0,RECT_WIDTH,RECT_HEIGHT);

}

//创建一个新的游戏界面

void GameArea::NewGame()

{

myFixItems.ClearPoints();

myCurItem.NewItem(QTime::currentTime().msec());//创建新的方块,当前的和下一个应不一样,所以随机数应不同

myCurItem.movetoItem(MAX_COLUME/2-1,1); //当前下落方块移动到中心位置

myNextItem.NewItem(QTime::currentTime().second());

emit sigUpdateNextItem(myNextItem.type(),myNextItem.direction());//发送信号刷新下一块区域

myScore=0;

myLevel=1;

myTimerID = startTimer(GetLevelTime(myLevel)); //开启定时器

}

//收到了按键信息

void GameArea::KeyPressed(int key)

{

int x=0,y=0;

switch (key) {

case Qt::Key_Up:

{

myCurItem.changedirection(1);

if (HitSide()||HitBottom())//左右下到了边界

{

myCurItem.changedirection(-1);

}

return;

}

case Qt::Key_Right:

{

x=1;

break;

}

case Qt::Key_Down:

{

y=1;

break;

}

case Qt::Key_Left:

{

x=-1;

break;

}

case Qt::Key_Space:

{

while (1)

{

myCurItem.moveItem(0,1);

if(HitBottom())

{

myCurItem.moveItem(0,-1);

break;

}

}

return;

}

case Qt::Key_Return:

{

if(myCurItem.myPoint.size()!=0)

{

if(myStop == true)

myStop = false;

else

myStop = true;

break;

}

}

}

myCurItem.moveItem(x,y);

if (HitSide()||HitBottom())//左右下到了边界

{

myCurItem.moveItem(-x, -y);

}

}

//如果碰到了左右边界

bool GameArea::HitSide()

{

for (int i=0;i<myCurItem.myPoint.size();i++)

{

QPoint pt=myCurItem.myPoint[i];

if(pt.x()<=0||pt.x()>=MAX_COLUME-1) //如果x座标小于等于1或大于等于MAX_COLUME-1,则表示撞上左右边界了

return true;

}

return false;

}

//如果到了底部

bool GameArea::HitBottom()

{

for (int i=0;i<myCurItem.myPoint.size();i++)

{

QPoint pt=myCurItem.myPoint[i];

if(pt.y()>=MAX_ROW-1) //如果y座标大于等于RECT_ROWS-1,则表示撞上下边界了

return true;

if(myFixItems.myPoint.contains(pt))// 如果固定不动的方块的座标包含当前下落方块的座标,则表示下到底了

return true;

}

return false;

}

//如果碰到了顶部

bool GameArea::HitTop()

{

for (int i=0;i<myCurItem.myPoint.size();i++)

{

QPoint pt=myCurItem.myPoint[i];

if(pt.y()<=1) //如果y座标大于等于RECT_ROWS-1,则表示撞上下边界了

return true;

}

return false;

}

//将当前的坐标给固定的方块

void GameArea::AddToFixedRects()

{

myFixItems.AddPoints(myCurItem.myPoint);

}

//删除完整的行

void GameArea::Deleterow()

{

int nRowsDeleted = 0; //记录消的行数

for (int i = 1; i<MAX_ROW-1; i++) //遍历游戏区座标

{

int nCount = 0;

for (int j = 1; j<MAX_COLUME-1; j++)

{

if (myFixItems.myPoint.contains(QPoint(j,i))) //判定每行有多少位置有方块

{

nCount++; // 每行方块的个数

}

}

if (nCount == MAX_COLUME-2)// 如果每行的个数等于MAX_COLUME-2, 则代表是满的

{

myFixItems.Deleterow(i); //将这一行删除

myFixItems.MoveDown(i,1); //消除行之上的内容下移一个单位

nRowsDeleted++;

}

}

//一次元素落下,最多可能消4行

//一次消除的越多,得分越多

if (nRowsDeleted == 1)

{

myScore += 20;

}

else if (nRowsDeleted == 2)

{

myScore += 60;

}

else if (nRowsDeleted == 3)

{

myScore += 120;

}

else if (nRowsDeleted == 4)

{

myScore += 200;

}

emit sigUpdateScore(myScore); //更新MainWindow界面得分

//粗略使用每1000分一关

if(myScore >= 1000 * myLevel)

{

myLevel++;

//随关卡增加下落速度,即把定时器加快

killTimer(myTimerID);

myTimerID = startTimer( GetLevelTime(myLevel));

emit sigUpdateLevel(myLevel); //更新MainWindow界面关卡

}

}

//当前等级的速度

int GameArea::GetLevelTime(int level)

{

if(level>10)

{

return 400;

}

else

{

return (19-level)*50;

}

}

//绘画事件重写

void GameArea::paintEvent(QPaintEvent *)

{

DrawBKRects();

DrawFixedRects();

DrawCurItem();

if(myStop)//暂停中

{

QFont font;

font.setPixelSize(100);

QPainter painter(this);

painter.setBrush(Qt::NoBrush);

painter.setFont(font);

painter.setPen(QPen(QColor("red"),1));

painter.drawText(rect(), Qt::AlignCenter, "暂停");

}

update();

}

//定时器重写

void GameArea::timerEvent(QTimerEvent *e)

{

if(myStop)

{

return;

}

else

{

if(myTimerID==e->timerId())

{

myCurItem.moveItem(0,1);

if (HitBottom())//碰到底部

{

myCurItem.moveItem(0, -1); //移动到原位

AddToFixedRects(); //将方块的坐标给固定方块

Deleterow();//判断是否有完整的行,然后删除

if(HitTop())//碰到了顶部,游戏结束

{

killTimer(myTimerID);

QMessageBox::information(NULL, "GAME OVER", "GAME OVER", QMessageBox::Yes, QMessageBox::Yes);

myFixItems.ClearPoints();

myCurItem.ClearPoints();

return;

}

myCurItem = myNextItem; //下一个方块给当前方块赋值

myCurItem.movetoItem(MAX_COLUME/2-1, 1);//移动到中心位置

myNextItem.NewItem(QTime::currentTime().msec());//下一个方块继续创建

emit sigUpdateNextItem(myNextItem.type(), myNextItem.direction());//发送信号下一块区域刷新方块

}

}

}

}

4.NextArea刷新下一块窗口

4.1头文件

#ifndef NEXTAREA_H

#define NEXTAREA_H

#include <QObject>

#include <QWidget>

#include "item.h"

class NextArea:public QWidget

{

Q_OBJECT

public:

explicit NextArea(QWidget *parent = nullptr);

private:

void paintEvent(QPaintEvent *event);

public slots:

void UpdateNextItem(ItemType type, int direction);//刷新方块

private:

Item myItem;

};

#endif // NEXTAREA_H

4.2源文件

#include "nextarea.h"

NextArea::NextArea(QWidget *parent): QWidget(parent)

{

}

void NextArea::paintEvent(QPaintEvent *)

{

QPainter painter(this);

painter.setBrush(QColor("#FFDEAD"));

painter.setPen(QPen(QColor(Qt::black),1));

int xStart = 0; //为了绘制在显示下一个方块区域的中部

int yStart = 80;

int w = 30;

int h = 30;

for(int i=0;i<myItem.myPoint.size();i++)

{

QPoint pt = myItem.myPoint[i];

int x = xStart + pt.x() * w;

int y = yStart + pt.y() * h;

painter.drawRect(x, y, w, h);

}

update();

}

void NextArea::UpdateNextItem(ItemType type, int direction)

{

myItem.initpoint(type,direction);

}

5.主窗口

5.1头文件

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include <QMainWindow>

#include <QMediaPlayer>

#include <QMediaPlaylist>

QT_BEGIN_NAMESPACE

namespace Ui { class MainWindow; }

QT_END_NAMESPACE

class MainWindow : public QMainWindow

{

Q_OBJECT

public:

explicit MainWindow(QWidget *parent = 0);

~MainWindow();

protected:

void keyPressEvent(QKeyEvent *e);//按键事件重写

private slots:

void UpdateLevel(int Level);//刷新等级

void UpdateScore(int Score);//刷新分数

void on_pbPuase_clicked();//开始按钮

void on_checkBox_stateChanged(int arg1);//音乐播放

private:

Ui::MainWindow *ui;

QMediaPlayer *player;

QMediaPlaylist *Playlist;

};

#endif // MAINWINDOW_H

5.2源文件

#include "mainwindow.h"

#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)

: QMainWindow(parent)

, ui(new Ui::MainWindow)

{

ui->setupUi(this);

setFixedSize(1000,800); //设置窗体为固定大小

setWindowTitle(tr("俄罗斯方块"));//设置窗体标题

connect(ui->widgetGameArea,&GameArea::sigUpdateLevel,this,&MainWindow::UpdateLevel);//等级

connect(ui->widgetGameArea,&GameArea::sigUpdateScore,this,&MainWindow::UpdateScore);//分数

connect(ui->widgetGameArea,&GameArea::sigUpdateNextItem,ui->widgetNextArea,&NextArea::UpdateNextItem);//下一块

Playlist =new QMediaPlaylist; //创建新的播放清单

player=new QMediaPlayer; //创建新的播放器

Playlist->addMedia(QUrl::fromLocalFile("F:/MyQT/Teris/media/1.mp3")); //往播放清单中添加音乐文件

Playlist->addMedia(QUrl::fromLocalFile("F:/MyQT/Teris/media/2.mp3"));

Playlist->addMedia(QUrl::fromLocalFile("F:/MyQT/Teris/media/3.mp3"));

Playlist->setCurrentIndex(0); //设置默认播放开始位置

Playlist->setPlaybackMode(QMediaPlaylist::Loop); //设置循环播放

player->setPlaylist(Playlist); //播放清单导入播放器

player->play(); //播放器开播

}

MainWindow::~MainWindow()

{

delete ui;

}

//按键由窗口接收,所以传递过去

void MainWindow::keyPressEvent(QKeyEvent *e)

{

ui->widgetGameArea->KeyPressed(e->key());

QMainWindow::keyPressEvent(e);

}

void MainWindow::UpdateLevel(int level)

{

ui->labelLevel->setText(QString::number(level));

}

void MainWindow::UpdateScore(int score)

{

ui->labelScore->setText(QString::number(score));

}

//开始游戏

void MainWindow::on_pbPuase_clicked()

{

ui->widgetGameArea->NewGame();

}

//音乐是否播放槽函数

void MainWindow::on_checkBox_stateChanged(int arg1)

{

if(arg1)

player->play();

else

player->stop();

}

三、概述

        对这个游戏来看,我自己的理解很直白的就是对数组的应用。在这个程序中,最核心的一点在于QVector<QPoint>这个坐标容器,在这个容器中,保存着所有需要画的方块的坐标,这个游戏的运行就是对这个容器里面的坐标增删改查的操作。

1.增

        具体表现就是在程序中落到底部的固定方块,方块到了底部以后,将坐标加入到这个容器中,也就实现了,方块的堆积。

2.删

        这个的直观表现就是完整行的消除,遍历整个游戏区域,每行是有方块限制的,当满了以后,便可以删除相关的坐标,便实现了消除。

3.改

        方块的形状改变便是更改的坐标,在设计中,每一个方块都是由各自的坐标的,当需要改变形状时,返回了当前形状的坐标。

4.查

        在下落的过程中,会一直遍历整个区域的坐标,当下落的方块中有存在了与固定方块相同的坐标时,便代表着该停止了,已经触碰了。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。