青岛市城市建设管理局网站,福州网站改版哪家好,四子王旗建设局网站,成都住建局官网Qt小项目贪吃蛇实线#xff0c;主要掌握定时器、信号与槽、按键事件、绘制事件、坐标运算、随机数生成等 Qt 贪吃蛇演示QWidget 绘制界面项目源文件 注释清晰widget.hwidget.cpp 拓展QTimerQKeyEventQRectFQPointFQPainterQIcon Qt 贪吃蛇演示 QWidget 绘制界面 项目源文件 注… Qt小项目贪吃蛇实线主要掌握定时器、信号与槽、按键事件、绘制事件、坐标运算、随机数生成等 Qt 贪吃蛇演示QWidget 绘制界面项目源文件 注释清晰widget.hwidget.cpp 拓展QTimerQKeyEventQRectFQPointFQPainterQIcon Qt 贪吃蛇演示 QWidget 绘制界面 项目源文件 注释清晰
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include QWidget
#include QtDebug#include QKeyEvent
#include QTimer
#include QRectF
#include QPointF#include QIcon
#include QPainterQT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEtypedef enum direct {dir_UP,dir_DOWN,dir_LEFT,dir_RIGHT
}dir_t;class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();private:void topAddRect();void deleteLast();void downAddRect();void leftAddRect();void rightAddRect();void addFood();bool checkHit();protected:// 按键按压处理void keyPressEvent(QKeyEvent *event);void paintEvent(QPaintEvent *event);private Q_SLOTS:void my_timeout();private:Ui::Widget *ui;int moveFlag dir_t::dir_UP;bool gameStart false;QTimer *timer;const int startTime 100;// 贪吃蛇QListQRectFsnakeList;// 贪吃蛇小方块const int nodeWidth 20;const int nodeHeight 20;// 食物QRectF food;};
#endif // WIDGET_H
widget.cpp
#include widget.h
#include ui_widget.h// 三个方块代码蛇最上面的第一个和最后面的一个通过按键进行交替删除 即snake[0]永远表示头Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);this-setWindowTitle(贪吃蛇疯子);this-setWindowIcon(QIcon(:/icons/title.jpg));qDebug()x this-x() y this-y() height this-height() width this-width();timer new QTimer();connect(timer, QTimer::timeout, this , Widget::my_timeout);// 初始化蛇身子 3个方块QRectF rect(this-width()/2,this-height()/2,nodeWidth,nodeHeight);snakeList.append(rect);topAddRect();topAddRect();// 添加食物addFood();
}Widget::~Widget()
{delete ui;
}// 增加一个方块 左上和右下确认一个方块坐标系
void Widget::topAddRect()
{QPointF leftTop; // 左上角坐标QPointF rightBottom; // 右上角坐标if (snakeList[0].y() 0) {// 当蛇移动到窗口顶部确认新坐标 y 窗口高度 - 蛇方块高度leftTop QPointF(snakeList[0].x(), this-height() - nodeHeight);rightBottom QPointF(snakeList[0].x() nodeWidth , this-height());}else {// 向上移动 y坐标必然减少 减少的右下角坐标为之前的下一个方块的右上角坐标leftTop QPointF(snakeList[0].x(), snakeList[0].y() - nodeHeight);rightBottom snakeList[0].topRight();}// 插入矩形小方块1个,由于采用的是List链表这是典型的前插追加snakeList.insert(0,QRectF(leftTop,rightBottom));
}void Widget::downAddRect()
{QPointF leftTop; // 左上角坐标QPointF rightBottom; // 右上角坐标if (snakeList[0].y() this-height() - nodeHeight) {// 当蛇移动到窗口底部确认新坐标 y 0leftTop QPointF(snakeList[0].x(), 0);rightBottom QPointF(snakeList[0].x() nodeWidth, 0 nodeHeight);}else {// 向下移动 y坐标必然增加leftTop QPointF(snakeList[0].x(), snakeList[0].y() nodeHeight);rightBottom snakeList[0].bottomRight() QPointF(0,nodeHeight);}// 插入矩形小方块1个snakeList.insert(0,QRectF(leftTop,rightBottom));
}void Widget::leftAddRect()
{QPointF leftTop; // 左上角坐标QPointF rightBottom; // 右上角坐标if (snakeList[0].x() 0) {// 当蛇移动到窗口最左部确认新坐标 x 窗口宽度 - 小方块宽度leftTop QPointF(this-width() - nodeWidth, snakeList[0].y());}else {// 向左移动x坐标必然减少leftTop QPointF(snakeList[0].x() - nodeWidth, snakeList[0].y());}// 右下角坐标 之前一个的左上角坐标x,y 小方块的宽高rightBottom leftTop QPointF(nodeWidth, nodeHeight);// 插入矩形小方块1个snakeList.insert(0,QRectF(leftTop,rightBottom));
}void Widget::rightAddRect()
{QPointF leftTop; // 左上角坐标QPointF rightBottom; // 右上角坐标if (snakeList[0].x() nodeWidth this-width()) {// 当蛇移动到窗口最右部确认新坐标 x 0leftTop QPointF(0, snakeList[0].y());}else {// 向右移动x坐标必然增加leftTop QPointF(snakeList[0].x() nodeWidth, snakeList[0].y());}// 右下角坐标 之前一个的左上角坐标x,y 小方块的宽高rightBottom leftTop QPointF(nodeWidth, nodeHeight);// 插入矩形小方块1个snakeList.insert(0,QRectF(leftTop,rightBottom));
}// 删除蛇身最后一个
void Widget::deleteLast()
{snakeList.removeLast();
}// 食物是随机出现的
void Widget::addFood()
{int rectX (qrand() % (this-width() / 20)) * 20;int rectY (qrand() % (this-height() / 20)) * 20;// 控制小球出现的范围if (rectX 0 rectY0) {food QRectF(rectX, rectY, nodeWidth, nodeHeight);qDebug()food food;}
}// 蛇头和蛇身碰撞检查其实就是蛇头和蛇尾其中一个方块重合
bool Widget::checkHit()
{// 整个蛇的长度都遍历一遍for (int i 0 ; i snakeList.length(); i) {// 从蛇头后的第一个开始检查 只要有for (int j i 1; j snakeList.length();j) {// rect0和rectx相等表示它们的坐标、宽度和高度都一致if (snakeList[0] snakeList[j]) {return true;}}}return false;
}void Widget::keyPressEvent(QKeyEvent *event)
{switch (event-key()) {case Qt::Key::Key_Up:if (moveFlag ! dir_DOWN) {moveFlag dir_UP;}break;case Qt::Key::Key_Down:if (moveFlag ! dir_UP) {moveFlag dir_DOWN ;}break;case Qt::Key::Key_Left:if (moveFlag ! dir_RIGHT) {moveFlag dir_LEFT;}break;case Qt::Key::Key_Right:if (moveFlag ! dir_LEFT) {moveFlag dir_RIGHT;}break;case Qt::Key_Space:if (gameStart false) {gameStart true;timer-start(startTime); // 100ms}else {gameStart false;timer-stop();}break;default:break;}
}void Widget::paintEvent(QPaintEvent *event)
{QPainter painter(this);QPen pen;QBrush brush;QPixmap pix;// 绘制图片背景pix.load(:/icons/bg_snake.png);painter.drawPixmap(0,0,this-width(),this-height(),pix);// 绘制蛇pen.setColor(Qt::color0);brush.setColor(Qt::darkGreen); // 绿色brush.setStyle(Qt::SolidPattern); // 实线图案painter.setPen(pen);painter.setBrush(brush);for (int i 0; i snakeList.length(); i) {painter.drawRect(snakeList[i]);}// 分数ui-label_score-setText(QString::number(snakeList.length() -3));// 绘制食物painter.drawEllipse(food);// 蛇头碰到蛇身结束游戏if (checkHit()) {QFont font(方正舒体,30,QFont::ExtraLight,false);painter.setFont(font);painter.drawText((this-width() - 200)/2,this-height()/2,QString(游戏结束));timer-stop();}QWidget::paintEvent(event);}// 定时器槽函数
void Widget::my_timeout()
{//int count 1; // 采用这种方式也可以加长蛇身不过我还是喜欢我的烂方法// 判断蛇是否吃到食物 是否重合[交叉相交贯穿横穿横断] 蛇变长if (snakeList[0].intersects(food)) {qDebug()吃到食物 snakeList[0] snakeList[0] food food;//count ; // 例如 2switch (moveFlag) {case dir_UP:this-topAddRect(); // 1break;case dir_DOWN:this-downAddRect(); // 1break;case dir_LEFT:this-leftAddRect(); // 1break;case dir_RIGHT:this-rightAddRect(); // 1break;default:break;}addFood(); // 食物位置变化return;}// 加长蛇身 每次在最前面增加一个// while (count--) {switch (moveFlag) {case dir_UP:this-topAddRect(); // 1break;case dir_DOWN:this-downAddRect(); // 1break;case dir_LEFT:this-leftAddRect(); // 1break;case dir_RIGHT:this-rightAddRect(); // 1break;default:break;}//}// 为了动态显示每次最前面插入一个最后面就减少一个deleteLast(); // 删除蛇尾 -1this-update(); // 刷新绘制函数
}
拓展
QTimer
QTimer是Qt中用于定时器操作的类它提供了一些常用的函数来控制和管理定时器的运行。下面是一些常用的QTimer函数的简介
start(int msec): 启动定时器以指定的毫秒数为间隔触发定时器的timeout()信号。stop(): 停止定时器不再触发timeout()信号。setInterval(int msec): 设置定时器的间隔时间以毫秒为单位。interval(): 获取当前定时器的间隔时间。isActive(): 判断定时器是否处于活动状态即是否正在运行。setSingleShot(bool singleShot): 设置定时器的运行模式如果设置为true则定时器只触发一次如果设置为false默认值则定时器会一直触发。singleShot(int msec, const QObject* receiver, const char* member): 创建一个单次触发的定时器指定触发时间、接收信号的对象和相应的槽函数。remainingTime(): 获取定时器剩余的触发时间以毫秒为单位。
这些函数提供了基本的定时器操作功能可以配合定时器的信号timeout()以及连接(Qt的信号与槽机制)来实现所需的定时操作。
QKeyEvent
QKeyEvent是Qt中用于处理键盘事件的类它提供了一些常用的函数来获取和处理键盘事件的相关信息。下面是一些常用的QKeyEvent函数的简介
key(): 获取触发键盘事件的按键的Qt键盘码返回一个Qt::Key枚举值。text(): 获取触发键盘事件的按键对应的文字返回一个QString。modifiers(): 获取触发键盘事件时的修饰键状态返回一个Qt::KeyboardModifiers枚举值可用于检查Shift、Ctrl、Alt等修饰键的状态。isAutoRepeat(): 判断触发键盘事件的按键是否是自动重复的按下事件。count(): 获取自动重复按键连续触发的次数。nativeVirtualKey(): 获取底层平台的虚拟键码返回一个int值。nativeModifiers(): 获取底层平台的修饰键状态返回一个int值。
这些函数可以帮助你获取与键盘事件相关的信息例如获取按下的键是哪个键是否同时按下了修饰键以及自动重复事件的次数等。你可以使用这些函数来处理键盘事件并根据需要执行相应的操作。
QRectF
QRectF是Qt中用于表示浮点数精度的矩形区域的类它提供了一些常用的函数来操作和管理矩形区域。下面是一些常用的QRectF函数的简介
QRectF(): 默认构造函数创建一个无效的矩形区域。QRectF(qreal x, qreal y, qreal width, qreal height): 构造函数创建一个以给定坐标、宽度和高度定义的矩形区域。setRect(qreal x, qreal y, qreal width, qreal height): 设置矩形区域的位置和尺寸。setCoords(qreal x1, qreal y1, qreal x2, qreal y2): 设置矩形区域的左上角和右下角的坐标。x(), y(), width(), height(): 获取矩形区域的左上角的x和y坐标以及宽度和高度。left(), top(), right(), bottom(): 获取矩形区域的左、上、右、下边界的坐标。setX(qreal x), setY(qreal y), setWidth(qreal width), setHeight(qreal height): 设置矩形区域的左上角的x和y坐标以及宽度和高度。setLeft(qreal left), setTop(qreal top), setRight(qreal right), setBottom(qreal bottom): 设置矩形区域的左、上、右、下边界的坐标。moveTo(qreal x, qreal y): 移动矩形区域的位置将其左上角设置为给定坐标。translated(qreal dx, qreal dy): 平移矩形区域沿x和y方向分别平移给定的距离。contains(const QPointF point): 判断矩形区域是否包含给定的点。isEmpty(): 判断矩形区域是否为空即宽度或高度是否为0。isNull(): 判断矩形区域是否为空即宽度和高度是否为0。
QPointF
QPointF是Qt中用于表示浮点数精度的二维点的类它提供了一些常用的函数来操作和管理点的坐标。下面是一些常用的QPointF函数的简介
QPointF(): 默认构造函数创建一个具有零值坐标的点。QPointF(qreal x, qreal y): 构造函数创建一个具有给定坐标的点。setX(qreal x), setY(qreal y): 设置点的x和y坐标。x(), y(): 获取点的x和y坐标。isNull(): 判断点是否为空即坐标是否为零值。manhattanLength(): 计算点到坐标原点的曼哈顿距离绝对值之和。distanceToLine(const QLineF line): 计算点到给定直线的距离。distanceToPoint(const QPointF point): 计算点到给定点的距离。operator(const QPointF p1, const QPointF p2): 判断两个点是否相等。operator!(const QPointF p1, const QPointF p2): 判断两个点是否不相等。isNull(const QPointF point): 判断给定点是否为空即坐标是否为零值。
这些函数提供了对点的基本操作包括设置坐标、获取坐标、判断点是否为空、计算与其他点或直线的距离等。你可以使用这些函数来创建、修改和计算点的坐标以满足你的需求。
QPainter
QPainter是Qt提供的一个用于绘图的类它封装了绘制图形、图像以及文本的功能。下面是一些常用的QPainter函数的简介
begin(QPaintDevice *device): 开始在给定的绘图设备上进行绘制device可以是QWidget、QImage等。end(): 结束绘制操作。setPen(const QPen pen): 设置绘制的画笔用于定义线条的样式、颜色等属性。setBrush(const QBrush brush): 设置绘制的刷子用于填充封闭图形的颜色、渐变等属性。setRenderHint(RenderHint hint, bool on true): 开启或关闭绘制的渲染提示例如抗锯齿、文本反锯齿等。drawLine(const QLine line): 绘制直线。drawRect(const QRect rect): 绘制矩形。drawEllipse(const QRect rect): 绘制椭圆。drawText(const QPointF pos, const QString text): 在给定点位置绘制文本。drawPixmap(const QRectF targetRect, const QPixmap pixmap): 在给定矩形区域绘制像素图。save(), restore(): 保存和恢复绘图状态用于实现绘制状态的切换、叠加效果等。resetTransform(): 重置坐标变换矩阵。translate(qreal dx, qreal dy): 平移画笔的原点。scale(qreal sx, qreal sy): 缩放画笔按比例调整绘图。rotate(qreal angle): 旋转画笔围绕原点进行旋转。
这些函数提供了绘制基本图形、文本和图像的能力通过设置画笔、刷子和渲染提示等属性可以实现不同样式的绘制效果。同时你还可以使用平移、缩放和旋转等变换函数来改变画笔的绘制位置和方向。使用这些函数你可以实现各种绘图需求创建出丰富多样的用户界面。
QIcon
QIcon是Qt提供的一个用于管理图标的类它可以加载、显示和操作图标。下面是一些常用的QIcon函数的简介
QIcon(): 默认构造函数创建一个空的图标。QIcon(const QString filename): 构造函数根据给定的文件名加载图标。QIcon(const QPixmap pixmap): 构造函数根据给定的像素图创建图标。QIcon(const QIcon other): 拷贝构造函数创建一个与给定图标相同的拷贝。addFile(const QString filename, const QSize size QSize(), QIcon::Mode mode QIcon::Normal, QIcon::State state QIcon::Off): 添加一个图像文件到图标中可以指定图像的大小、模式和状态。isNull(): 判断图标是否为空即没有加载任何图像。pixmap(const QSize size, QIcon::Mode mode QIcon::Normal, QIcon::State state QIcon::Off) const: 获取图标的像素图可以指定图像的大小、模式和状态。paint(QPainter *painter, const QRect rect, Qt::Alignment alignment Qt::AlignCenter, QIcon::Mode mode QIcon::Normal, QIcon::State state QIcon::Off) const: 在给定的矩形区域内绘制图标可以指定对齐方式、模式和状态。operator(const QIcon other): 赋值运算符将给定图标的内容复制到当前图标。operator, operator!: 用于比较两个图标是否相等或不相等。
这些函数提供了加载、显示和操作图标的功能你可以根据需要加载图像文件设置图标的大小、模式和状态绘制图标到指定的区域并进行图标的比较和赋值操作。QIcon类在Qt中广泛用于界面开发它使得图标的管理和使用变得简单和灵活。