QT 贪吃蛇



前言

好久没更新了,新工作转做QT开发,周末写个小游戏练练手,大佬略过,开发环境Qt5.14.2 !



一、效果图

功能很简单,不到200行代码,直接上图

在这里插入图片描述

二、源码

代码如下,注释很详细,就不再说明

2.1 头文件

#ifndef SNAKEGAME_H
#define SNAKEGAME_H

#include <QMainWindow>
#include <QLabel>
#include <QList>
#include <QTimer>

// 蛇移动方向,上下左右
enum class Direction
{
    Up = 1,
    Down,
    Left,
    Right
};

class SnakeGame : public QMainWindow
{
    Q_OBJECT

public:
    explicit SnakeGame(QWidget *parent = 0);
    ~SnakeGame();

    // 使用键盘控制方向
    void keyPressEvent(QKeyEvent *event);

    // 产生新食物
    QLabel* getFood(void);

private slots:
    // 蛇根据方向移动,调用一次移动一个步长
    void snakeMove(void);

private:
    const int       m_iFoodSize{ 30 };                   // 食物大小 矩形方块 一个步长等于一个食物大小
    QLabel*         m_lbFood{ nullptr };                // 随机生成的食物label
    QList<QLabel*>  m_lbListSnake{ };                   // 蛇长度lable列表
    QTimer*         m_timerGame{ nullptr };             // 游戏定时器 蛇移动 刷新界面
    Direction       m_eSnakeMoveDir{ Direction::Up };   // 蛇移动方向
};

#endif // SNAKEGAME_H


2.2 源文件

#include "SnakeGame.h"

#include <QPalette>
#include <QTime>
#include <QPainter>
#include <QMessageBox>

SnakeGame::SnakeGame(QWidget *parent) :
    QMainWindow(parent)
{
    this->resize(800, 600);

    // 随机数种子
    qsrand(QTime::currentTime().msec());

    // 生成蛇头,并设置成圆形
    m_lbListSnake.push_back(getFood());
    m_lbListSnake[0]->setStyleSheet(QString("QLabel{background-color:red; border-radius:%1px;}").arg(m_iFoodSize / 2));

    // 生成食物
    m_lbFood = getFood();

    // 初始化游戏刷新定时器,连接槽函数
    m_timerGame = new QTimer;
    connect(m_timerGame, &QTimer::timeout, this, &SnakeGame::snakeMove);
    m_timerGame->start(300);
}

SnakeGame::~SnakeGame()
{
}

void SnakeGame::keyPressEvent(QKeyEvent *event)
{
    switch (event->key()) {
    case Qt::Key_Up:
        // 不允许反方向走
        if(m_eSnakeMoveDir != Direction::Down)
        {
            m_eSnakeMoveDir = Direction::Up;
        }
        break;
    case Qt::Key_Down:
        if(m_eSnakeMoveDir != Direction::Up)
        {
            m_eSnakeMoveDir = Direction::Down;
        }
        break;
    case Qt::Key_Left:
        if(m_eSnakeMoveDir != Direction::Right)
        {
            m_eSnakeMoveDir = Direction::Left;
        }
        break;
    case Qt::Key_Right:
        if(m_eSnakeMoveDir != Direction::Left)
        {
            m_eSnakeMoveDir = Direction::Right;
        }
        break;
    default:
        break;
    }

}

QLabel *SnakeGame::getFood()
{
    // 创建食物
    QLabel* lbFood = new QLabel(this);
    lbFood->resize(m_iFoodSize, m_iFoodSize);
    // 设置随机背景色
    lbFood->setAutoFillBackground(true);
    lbFood->setPalette(QPalette(QColor(qrand() % 256, qrand() % 256, qrand() % 256)));
    lbFood->setFrameShape(QFrame::Box);

    // 设置位置随机,位置为FoodSize的整数倍,起始位置要减去一个步长
    int iPosX = ( qrand() % ( this->width()  - m_iFoodSize) ) /  m_iFoodSize * m_iFoodSize;
    int iPosY = ( qrand() % ( this->height() - m_iFoodSize) ) /  m_iFoodSize * m_iFoodSize;
    lbFood->move(iPosX, iPosY);

    lbFood->show();

    return lbFood;
}

void SnakeGame::snakeMove()
{
    // 蛇头移动前的坐标
    int iSnakeHeadX = m_lbListSnake[0]->x();
    int iSnakeHeadY = m_lbListSnake[0]->y();

    // 撞墙结束游戏
    if(iSnakeHeadX < 0 || iSnakeHeadY < 0 ||
            iSnakeHeadX > this->width() || iSnakeHeadY > this->height())
    {
        QMessageBox::warning(this, "Tips", "game over!");
        this->close();
    }

    // 撞到自己结束游戏,跳过蛇头,遍历列表
    int iSnakeLen = m_lbListSnake.length();
    for(auto i=1; i<iSnakeLen; i++)
    {
        if(iSnakeHeadX == m_lbListSnake[i]->x() && iSnakeHeadY == m_lbListSnake[i]->y())
        {
            QMessageBox::warning(this, "Tips", "game over!");
            this->close();
        }
    }

    // 当食物和蛇头重合时吃掉食物
    if(iSnakeHeadX == m_lbFood->x() && iSnakeHeadY == m_lbFood->y())
    {
        // 食物插入蛇头列表
        m_lbListSnake.push_back(m_lbFood);
        // 再重新生成一个食物
        m_lbFood = getFood();
    }

    // 后一个元素移动到前一个元素位置
    for(auto i=iSnakeLen-1; i>0; --i)
    {
        m_lbListSnake[i]->move(m_lbListSnake[i-1]->pos());
    }

    // 移动一个步长,重新计算坐标
    switch (m_eSnakeMoveDir) {
    case Direction::Up:
        iSnakeHeadY -= m_iFoodSize;
        break;
    case Direction::Down:
        iSnakeHeadY += m_iFoodSize;
        break;
    case Direction::Left:
        iSnakeHeadX -= m_iFoodSize;
        break;
    case Direction::Right:
        iSnakeHeadX += m_iFoodSize;
        break;
    default:
        break;
    }

    // 把蛇头移动到新坐标
    m_lbListSnake[0]->move(iSnakeHeadX, iSnakeHeadY);
}


2.3 main函数

#include "SnakeGame.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    SnakeGame w;
    w.show();

    return a.exec();
}



  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Li_Zhi_Yao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值