代码思路:
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
实现效果:

贪吃蛇游戏
浙公网安备 33010602011771号