基于QT的俄罗斯方块设计Word文件下载.docx
《基于QT的俄罗斯方块设计Word文件下载.docx》由会员分享,可在线阅读,更多相关《基于QT的俄罗斯方块设计Word文件下载.docx(20页珍藏版)》请在冰点文库上搜索。
![基于QT的俄罗斯方块设计Word文件下载.docx](https://file1.bingdoc.com/fileroot1/2023-4/28/4f11e7cd-8a4b-47c1-9c66-420065062e0e/4f11e7cd-8a4b-47c1-9c66-420065062e0e1.gif)
在GUI编程中,当我们改变了一个组件,我们经常需要通知另外的一个组件。
更一般地,我们希望任何类型的对象都能够与另外的对象通讯。
例如,如果用户点击了关闭按钮,
我们希望窗口的close()函数被调用。
早期工具库对这种通讯使用回调实现。
回调是一个指向一个函数的指针,所以如果你希望某种事件发生的时候,处理函数获得通知,你就需要将指向另外函数的指针(也就是这个回调)传递给处理函数。
这样,处理函数就会在合适的时候调用回调函数。
回调有两个明显的缺点:
第一,它们不是类型安全的。
我们不能保证处理函数传递给回调函数的参数都是正确的。
第二,回调函数和处理函数紧密地耦合在一起,因为处理函数必须知道哪一个函数被回调。
在Qt中,我们有回调技术之外的选择:
信号槽。
当特定事件发出时,一个信号会被发出。
Qt组件有很多预定义的信号,同时,我们也可以通过继承这些组件,添加自定义的信号。
槽则能够响应特定信号的函数。
Qt组件有很多预定义的槽,但是更常见的是,通过继承组件添加你自己的槽,以便你能够按照自己的方式处理信号。
信号槽机制是类型安全的:
信号的签名必须同接受该信号的槽的签名一致(实际上,槽的参数个数可以比信号少,因为槽能够忽略信号定义的多出来的参数)。
既然签名都是兼容的,那么编译器就可以帮助我们找出不匹配的地方。
信号和槽是松耦合的:
发出信号的类不知道也不关心哪些槽连接到它的信号。
Qt的信号槽机制保证了,如果你把一个信号同一个槽连接,那么在正确的时间,槽能够接收到信号的参数并且被调用。
信号和槽都可以有任意类型的任意个数的参数。
它们全部都是类型安全的。
所有继承自QObject或者它的一个子类(例如QWidget)都可以包含信号槽。
信号在对象改变其状态,并且这个状态可能有别的对象关心时被发出。
这就是这个对象为和别的对
象交互所做的所有工作。
它并不知道也不关心有没有别的对象正在接收它发出的信号。
这是真正的信息封装,保证了这个对象能够成为一个组件。
槽能够被用于接收信号,也能够像普通函数一样使用。
正如一个对象并不知道究竟有没
有别的对象正在接收它的信号一样,一个槽也不知道有没有信号与它相连。
这保证了使用Qt
可以创建真正相互独立的组件。
你可以将任意多个信号连接到同一个槽上,也可能将一个信号连接任意多个槽。
同时,也能够直接将一个信号与另一个信号相连(这会使第一个信号发出时,马上发出第二个信号)。
总之,信号槽建立起一种非常强大的组件编程机制。
2.3.3事件
在Qt中,事件是作为对象处理的,所有事件对象继承自抽象类QEvent。
此类用来表示程序内部发生或者来自于外部但应用程序应该知道的动作。
事件能够能过被QObject的子类接受或者处理,但是通常用在与组件有关的应用中。
本文档主要阐述了在一个典型应用中的事件接收与处理。
当一个事件产生时,Qt通过实例化一个QEvent的合适的子类来表示它,然后通过调用event()函数发送给QObject的实例(或者它的子类)。
event()函数本身并不会处理事件,根据事件类型,它将调用相应的事件处理函数,并且返回事件被接受还是被忽略。
一些事件,比如QMouseEvent和QKeyEvent,来自窗口系统;
有的,比如QTimerEvent,来自于其他事件源;
另外一些则来自应用程序本身。
通常事件的处理需要调用一个虚函数。
比如,QPaintEvent事件的处理需要调用QWidget:
:
paintEvent()函数。
这个虚函数负责做出适当的响应,通常是用来重绘组件。
如果你在自己的函数中并不打算实现所有的处理,你可以调用基类的实现。
3系统设计
3.1需求分析
可随机生成7种基本方块单元不同的方块单元具备不同的颜色
基本方块单元在移动时支持两种操作:
旋转、移动具备计分及升级系统
支持虚拟按键
3.2框架设计
3.2.1俄罗斯方块基本规则
一个用于摆放小型正方形的平面虚拟场地,其标准大小:
行宽为10,列高为20,以每个小正方形为单位
一组由4个小型正方形组成的规则图形,英文称为Tetromino,中文通称为方块共有7
种,分别以S、Z、L、J、I、O、T这7个字母的形状来命名
随机发生器不断地输出单个方块到场地顶部,以一定的规则进行移动、旋转、下落和摆放,锁定并填充到场地中。
每次摆放如果将场地的一行或多行完全填满,则组成这些行的所有小正方形将被消除,并且以此来换取一定的积分或者其他形式的奖励。
而未被消除的方块会一直累积,并对后来的方块摆放造成各种影响
如果未被消除的方块堆放的高度超过场地所规定的最大高度(并不一定是20或者玩家
所能见到的高度),则游戏结束
3.2.2系统模块
如上图所示,系统可由以下几个模块组成:
虚拟显示屏:
为系统核心模块,负责游戏元素的显示、游戏逻辑的执行、以及游戏状态的维护、接收操作模块的操作信息、为辅助显示模块提供必要的信息
辅助显示模块:
显示下一个方块单元的类型、当前分数、当前等级
操作区模块:
为用户提供操作按键
3.3系统实现
系统源文件布局如下:
HTetris.pro:
系统工程文件HTetrisWindow.h:
HTetrisWindow类声明头文件
HTetrisPiece.h:
HTetrisPiece类声明头文件HTetrisBoard.h:
HTetrisBoard类声明头文件tetris.qrc:
系统资源文件,存放了表示方向的图像数据HTetrisWindow.cpp:
HTetrisWindow类的实现HTetrisPiece.cpp:
HTetrisPiece类的实现HTetrisBoard.cpp:
HTetrisBoard类的实现
main.cpp:
程序入口
main.cpp中初始化一个HTetrisWindow实例,并使其显示。
HTetrisWindow对应程序窗口,它包含一个游戏显示区(HTetrisBoard)、辅助显示区、及一些按键,HTetrisWindow在自身的构造函数中完成对这些界面元素的初始化及布局工作,同时建立起必要的信号-槽连接。
HTetrisPiece类表示基本方块单元,总共有7种,即I、T、J、L、O、Z、S,用HTetrisPieceShape来标识方块类型。
HTetrisPiece提供了设置方块形状、设置旋转、获取方块信息的一些公共成员函数。
HTetrisPiece使用coords[4][2]这个二维数组来存储方块的形状信息,这个数组的每行表示一个点的坐标。
HTetrisBoard是整个程序的核心,相对前两个类,这个类要复杂很多。
它提供了如下几
个槽:
start()、pause()、moveRight()、moveLeft()、moveDown()、rotateRight()、rotateLeft()。
提供了scoreChanged与levelChanged两个信号。
paintEvent负责整个HTetrisBoard的重绘。
removeFullLines负责判断是否某行全部为方块,如果是,则把该行消除,同时添加一定分数及经验。
4系统测试
程序的运行界面如上图所示,经测试,该程序具备了俄罗斯方块游戏的基本功能。
5课程设计总结
通过这次嵌入式实验,我对嵌入式技术有了更加深入的了解,在老师悉心帮助下,和其他同学的共同努力下,我们最终圆满地完成了这次课程设计。
但是实验中,也暴露了自己在软件运用方面的不足和缺点,以后在这方面上认真学习和研究,争取在毕业之前能更上一层楼。
6附录
6.1参考资料
[1]
[2]CplusplusGUIProgrammingwithQt42ndEdition[3]
6.2程序源码
/*
*Filename:
main.cpp
*Author:
HaleChan<
halechan@qq>
*Date:
20XX-11-24
*/
#include<
QtGui>
#include"
HTetrisWindow.h"
intmain(intargc,char*argv[])
{
QApplicationapp(argc,argv);
HTetrisWindowwindow;
window.show();
qsrand(QTime(0,0,0).secsTo(QTime:
currentTime()));
returnapp.exec();
}
HTetrisWindow.h
#ifndefHTetrisWINDOW_H#defineHTetrisWINDOW_H
QWidget>
classHTetrisBoard;
classQLabel;
classQLCDNumber;
classQPushButton;
classHTetrisWindow:
publicQWidget
{Q_OBJECT
public:
HTetrisWindow();
private:
QLabel*createLabel(constQString&
text);
HTetrisBoard*board;
QLabel*nextPieceLabel;
QLCDNumber*scoreLcd;
QLCDNumber*levelLcd;
QPushButton*leftButton;
QPushButton*rightButton;
QPushButton*upButton;
QPushButton*downButton;
QPushButton*aButton;
QPushButton*bButton;
};
#endif//HTetrisWINDOW_H
HTetrisWindow.cpp
#include"
HTetrisBoard.h"
#include<
HTetrisWindow:
HTetrisWindow()
board=newHTetrisBoard;
nextPieceLabel=newQLabel;
nextPieceLabel->
setFrameStyle(QFrame:
Box|QFrame:
Raised);
setAlignment(Qt:
AlignCenter);
setBaseSize(60,60);
setMinimumSize(60,60);
setMaximumSize(60,60);
setSizePolicy(QSizePolicy:
Fixed,QSizePolicy:
Fixed);
board->
setNextPieceLabel(nextPieceLabel);
scoreLcd=newQLCDNumber(6);
scoreLcd->
setSegmentStyle(QLCDNumber:
Filled);
setFixedWidth(70);
levelLcd=newQLCDNumber
(1);
levelLcd->
leftButton=newQPushButton;
leftButton->
setAutoRepeat(true);
setIcon(QIcon("
/images/left.png"
));
rightButton=newQPushButton;
rightButton->
/images/right.png"
upButton=newQPushButton;
upButton->
/images/up.png"
downButton=newQPushButton;
downButton->
/images/down.png"
aButton=newQPushButton(tr("
A"
aButton->
setFixedWidth(50);
bButton=newQPushButton(tr("
B"
bButton->
connect(leftButton,SIGNAL(clicked()),board,SLOT(moveLeft()));
connect(rightButton,SIGNAL(clicked()),board,SLOT(moveRight()));
connect(upButton,SIGNAL(clicked()),board,SLOT(pause()));
connect(downButton,SIGNAL(clicked()),board,SLOT(moveDown()));
connect(aButton,SIGNAL(clicked()),board,SLOT(rotateLeft()));
connect(bButton,SIGNAL(clicked()),board,SLOT(rotateRight()));
connect(board,SIGNAL(levelChanged(int)),levelLcd,SLOT(display(int)));
connect(board,SIGNAL(scoreChanged(int)),scoreLcd,SLOT(display(int)));
QGridLayout*mainLayout=newQGridLayout;
mainLayout->
addWidget(board,0,0,7,3,Qt:
addWidget(createLabel(tr("
Next"
)),0,3,Qt:
addWidget(nextPieceLabel,1,3,Qt:
setRowStretch(2,9);
Score"
)),3,3,Qt:
addWidget(scoreLcd,4,3,Qt:
AlignHCenter|Qt:
AlignTop);
Level"
)),5,3,Qt:
addWidget(levelLcd,6,3,Qt:
addWidget(upButton,7,1,Qt:
AlignBottom);
addWidget(aButton,7,3,Qt:
AlignBottom|Qt:
AlignHCenter);
addWidget(leftButton,8,0,Qt:
AlignTop|Qt:
AlignLeft);
addWidget(downButton,8,1,Qt:
addWidget(rightButton,8,2,Qt:
AlignRight|Qt:
addWidget(bButton,8,3,Qt:
setRowMinimumHeight(7,30);
setRowMinimumHeight(8,50);
this->
setLayout(mainLayout);
setWindowTitle(tr("
Tetris"
setFixedSize(240,400);
QLabel*HTetrisWindow:
createLabel(constQString&
text)
QLabel*lbl=newQLabel(text);
lbl->
returnlbl;
HTetrisPiece.h
#ifndefHTetrisPIECE_H#defineHTetrisPIECE_H
typedefenum{
HTetrisPieceShapeNone,
HTetrisPieceShapeI,
HTetrisPieceShapeT,
HTetrisPieceShapeJ,
HTetrisPieceShapeL,
HTetrisPieceShapeO,
HTetrisPieceShapeZ,
HTetrisPieceShapeS
}HTetrisPieceShape;
HTetrisPieceRotateZero,
HTetrisPieceRotate90,
HTetrisPieceRotate180,
HTetrisPieceRotate270
}HTetrisPieceRotate;
classHTetrisPiece
{public:
HTetrisPiece(){setShape(HTetrisPieceShapeNone);
voidsetRandomShape();
voidsetShape(HTetrisPieceShapeshape);
HTetrisPieceShapeshape()const{returnpieceShape;
}
intx(intindex)const{returncoords[index][0];
inty(intindex)const{returncoords[index][1];
intminX()const;
intmaxX()const;
intminY()const;
intmaxY()const;
voidsetRotate(HTetrisPieceRotaterotate);
HTetrisPiecepieceFromRotatedLeft()const;
H