代码思路:

1、创建工程

New project ->Application-> Qt Widgets Application -> 设置项目名称和路径->选择编译套件->设置类名Snake、选择基类为QWidget->完成

 

2、绘制蛇

(1)QVector<QPoint> snake;

(2)声明并实现绘图事件函数paintEvent(QPaintEvent *event):Snake类的构造函数初始化蛇snake向量、paintEvent函数中创建画家、实现并调用drawSnake函数

 

3、通过定时器移动蛇:

           ① 定时器connect超时信号槽连接:connect(timer, &QTimer::timeout, this, &Snake::updateSnake)

    ② 声明并编写Snake::updateSnake函数:取蛇头坐标,根据方向更新蛇头坐标并prepend到蛇snake,然后删除蛇的尾巴节点removeLast;

           ③ timer->start( 200) 设置开始计时,且计时超时时间为200ms

 

4、控制蛇的运动方向

  ① 增加枚举 enum Direction{UP, DOWN, LEFT, RIGHT}

         ② 声明并且编写键盘事件函数 Snake::keyPressEvent(QKeyEvent *event), 根据event->key()的枚举值设置方向direction

  ③ update更新绘图事件

 

5、更新食物位置

(1)声明 foodPointx 和 foodPointy;

(2)编写Snake::updateSnake函数:判断蛇头的坐标和食物坐标,如果相等则更新foodPointx和foodPointy, 通过append函数增加snake的尾巴节点;

(3)Snake构造函数中设置foodPointx和foodPointy

 

6、设置空格键暂停

 在键盘事件函数keyPressEvent中判断flagStatus的状态并重新设置flagStatus和timer定时器:

case Qt::Key_Space:
    if(flagPause == true)
    {
        flagPause = false;
        timer->stop();
    }
    else
    {
        flagPause = true;
        timer->start(200);
    }

 

7、判断游戏结束

 Snake::updateSnake函数中判断蛇头点坐标,如果坐标等于边界值或者和蛇身体重合,则通过QMessageBox弹出游戏结束

 

贪吃蛇游戏源代码:

snake.cpp

#include "snake.h"
#include "ui_snake.h"
#include <QRandomGenerator>
#include <QPainter>
#include <QMessageBox>

Snake::Snake(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Snake)
    , direction(RIGHT)
    , flagPause(false)
{
    ui->setupUi(this);

    setWindowTitle("贪吃蛇");
    setFixedSize(820,680);

    snake.append(QPoint(100,100));
    snake.append(QPoint(80,100));
    snake.append(QPoint(60,100));
    snake.append(QPoint(40,100));

    pointx = QRandomGenerator::global()->bounded(width());
    pointx = (pointx/20)*20;
    pointy = QRandomGenerator::global()->bounded(height());
    pointy= (pointy/20)*20;

    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &Snake::updateSnake);
    timer->start(200);
}

Snake::~Snake()
{
    delete ui;
}

/* 实现画蛇函数 */
void Snake::drawSnake(QPainter &painter)
{

    for(int i=0; i<snake.size(); i++)
    {
        if(i == 0)
        {
            painter.setBrush(Qt::yellow);
            painter.drawRect(snake[i].x(),snake[i].y(),20,20);
        }
        else
        {
            painter.setBrush(Qt::green);
            painter.drawRect(snake[i].x(),snake[i].y(),20,20);
        }
    }
}

/* 实现绘画事件函数 */
void Snake::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    painter.setPen(Qt::black);

    drawSnake(painter);

    painter.setBrush(Qt::red);

    painter.drawEllipse(pointx, pointy, 20, 20);
}

/* 蛇移动事件函数 */
void Snake::snakeMove()
{
    QPoint newHead = snake.first();
    switch(direction)
    {
        case UP:
            newHead.ry() -= 20;
            break;
        case DOWN:
            newHead.ry() += 20;
            break;
        case LEFT:
            newHead.rx() -= 20;
            break;
        case RIGHT:
            newHead.rx() += 20;
            break;
    }
    snake.prepend(newHead);
    snake.removeLast();
}

void Snake::updateSnake()
{
    snakeMove();
    QPoint newHead = snake.first();
    if( (newHead.rx() == pointx) && (newHead.ry() == pointy))
    {
        pointx = QRandomGenerator::global()->bounded(width());
        pointx = (pointx/20)*20;
        pointy = QRandomGenerator::global()->bounded(height());
        pointy = (pointy/20)*20;

        switch (direction)
        {
        case UP:
            snake.append(QPoint((snake.last().rx()),snake.last().ry()-20));
            break;
        case DOWN:
            snake.append(QPoint((snake.last().rx()),snake.last().ry()+20));
            break;
        case LEFT:
            snake.append(QPoint((snake.last().rx()+20),snake.last().ry()));
            break;
        case RIGHT:
            snake.append(QPoint((snake.last().rx()-20),snake.last().ry()));
            break;
        }
    }
    else if(newHead.rx() == 820 || newHead.rx() == -20   ||
            newHead.ry() == 680 || newHead.ry() == -20 )
    {
        QMessageBox::information(this, "游戏结束", "超出移动范围");
        this->close();
    }

    for(QVector<QPoint>::iterator it = snake.begin()+1; it != snake.end(); it++)
    {
        if(it->rx() == newHead.rx() && it->ry() == newHead.ry())
        {
            QMessageBox::information(this, "游戏结束", "吃到自己了");
            this->close();
        }
    }

    update();
}

void Snake::keyPressEvent(QKeyEvent *event)
{
    Q_UNUSED(event);

    switch(event->key())
    {
        case Qt::Key_Up:
             direction = UP;
             break;
        case Qt::Key_Down:
             direction = DOWN;
             break;
        case Qt::Key_Left:
             direction = LEFT;
             break;
        case Qt::Key_Right:
             direction = RIGHT;
             break;
        case Qt::Key_Space:
             if(flagPause == true)
             {
                flagPause = false;
                timer->stop();
             }
             else
             {
                flagPause = true;
                timer->start(200);
             }

             break;
    }
    update();
}

 

snake.h

#ifndef SNAKE_H
#define SNAKE_H

#include <QWidget>
#include <QVector>      /* 添加QVector头文件 */
#include <QPoint>       /* 添加Point头文件 */
#include <QPaintEvent>  /* 添加QPaintEvent头文件 */
#include <QPainter>
#include <QTimer>
#include <QKeyEvent>

QT_BEGIN_NAMESPACE
namespace Ui { class Snake; }
QT_END_NAMESPACE

enum Direction
{
    UP,
    DOWN,
    LEFT,
    RIGHT
};

class Snake : public QWidget
{
    Q_OBJECT

public:
    Snake(QWidget *parent = nullptr);
    ~Snake();


private:
    Ui::Snake *ui;
    QVector<QPoint> snake; /* 声明贪吃蛇对象 */
    void drawSnake(QPainter &painter); /* 声明画蛇函数 */
    QTimer *timer;
    Direction direction;
    int pointx;
    int pointy;
    bool flagPause;

protected:
    void paintEvent(QPaintEvent *event) override;  /* 声明绘画事件函数 */
    void keyPressEvent(QKeyEvent *event) override; /* 声明键盘时间函数 */

public slots:
    void updateSnake();
    void snakeMove();
};

#endif // SNAKE_H

 

实现效果:

posted on 2025-04-30 23:06  轩~邈  阅读(85)  评论(0)    收藏  举报