基于Qt实现的贪吃蛇游戏

一,游戏功能

1,创建定时器,利用槽函数定时刷新游戏界面

2,通过按键方式,实现蛇的方向控制( ↑  ↓  ←  → )

3,通过按键方式,实现游戏的开始和暂停( 空格键 )

4,方块链表表示蛇,在首尾增加或删除方块,实现蛇的移动

5,判断蛇头是否碰壁或者咬到自己导致游戏结束

6,随机出现食物方块,判断蛇头是否和食物位置重合

7,蛇每吃到一个食物(蛇头和食物重合),得分+1,长度+1

8,把游戏背景图、蛇、食物、分数等元素画入游戏界面


注:以上操作都局限于单文件,还未将蛇、食物等分出单独的类进行操作

 二,操作演示

1,游戏开始界面

基于Qt实现的贪吃蛇游戏_第1张图片

2,游戏进行页面

基于Qt实现的贪吃蛇游戏_第2张图片

3,游戏结束页面

基于Qt实现的贪吃蛇游戏_第3张图片

 三,附源代码

1,widget.h 

#ifndef WIDGET_H
#define WIDGET_H

#include 
#include
#include
#include

typedef enum Direct{
    //枚举类型 上下左右
    DIR_LEFT,
    DIR_RIGHT,
    DIR_UP,
    DIR_DOWN
}dir_t;

namespace Ui {
class Widget;
}
class Widget : public QWidget
{
    Q_OBJECT

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

    void addUp();//上方添加长度
    void addDown();//下方添加长度
    void addLeft();//左边添加长度
    void addRight();//右边添加长度
    bool checkMeet();//判断是否咬到自己
    void keyPressEvent(QKeyEvent *event);//处理按键事件 上下左右 空格键
    void paintEvent(QPaintEvent *event);//画家事件 用于画蛇和食物 及背景
    void addNewFood();//当食物被吃掉后 添加食物

private:
    Ui::Widget *ui;

    bool gameStart = false;//判断游戏是否开始
    QTimer *timer;//创建定时器
    int time = 200;//超时时间间隔100ms
    bool meet = false;//判断蛇头是否碰壁
    int score = 0;//记录分数
    QRectF food;//食物小方块
    QList snake;//链表表示 蛇身体,由一串小方格组成
    int nodeWidth = 20;//定义小方块的宽度
    int nodeHeight = 20;//定义小方块的长度
    dir_t moveFlag = DIR_UP;//蛇当前的移动方向
    int window_length = 1200;
    int window_width = 800;

protected slots:
    void timeout();//槽函数 超时处理
};

#endif // WIDGET_H

2,widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    timer = new QTimer();//使用定时器
    //信号槽(信号和对应的函数关联起来) 定时器有一个timeout信号
    connect(timer,&QTimer::timeout,this,timeout);//超时函数处理,实现蛇的移动
    //connect(timer,SIGNAL(timeout()),this,SLOT(timeout()));//旧的写法

    this->setFixedSize( window_length,window_width);//定义窗口初始大小
    //resize(window_length,window_width);//没有固定窗口大小

    //初始化蛇的长度
    QRectF head(window_length/2,window_width/2,nodeWidth,nodeHeight);//蛇头
    snake.append(head);//画出蛇的第一个方块(尾部插入)
    addUp();//上方插入,增加蛇身
    addUp();
    addUp();
    addUp();
    addUp();
    addUp();
    addUp();
    //增加初始的食物
    addNewFood();
}

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

//超时函数
void Widget::timeout()
{
    int flag = 1;//判断有没有重合(吃到食物)
    if(snake[0].intersects(food))//蛇头和食物
    {
        flag++;//吃到加一,下面循环的时候多一次,增加一个长度
        addNewFood();//添加新的食物
        score++;//分数增加
    }
    while(flag--)//一次或者两次
    {
        switch (moveFlag) {
            case DIR_UP://上面加一个
                addUp();
                break;
            case DIR_DOWN://下面加一个
                addDown();
                break;
            case DIR_LEFT://左边加一个
                addLeft();
                break;
            case DIR_RIGHT://右边加一个
                addRight();
                break;
            default:
                break;
        }
    }
    snake.removeLast();//头部添加了一个(或两个),尾部减少一个,实现蛇的移动
    update();//直接调用paintEvent刷新页面***paintEvent***的调用
//    每当内容需要更新时,都会调用虚拟paintEvent()函数。然后,重新实现
//    此函数的子类可以简单地在窗口上打开 QPainter。
}

//上方添加长度
void Widget::addUp()
{
    QPointF leftTop;//左上角的点坐标
    QPointF rightBotom;//右下角的点坐标
    if(snake[0].y()-nodeHeight < 0)//蛇头碰到 上墙壁
    {
        meet = true;//碰壁变量为真
    }
    else
    {
        leftTop = QPointF(snake[0].x(),snake[0].y()-nodeHeight);//左上角
        rightBotom = snake[0].topRight();//右下角
    }
    snake.insert(0,QRectF(leftTop,rightBotom));//插入蛇的新节点(蛇头)
}

//下方添加长度
void Widget::addDown()
{
    QPointF leftTop;//左上角的点坐标
    QPointF rightBotom;//右下角的点坐标
    if(snake[0].y()+nodeHeight*2 > window_width)//蛇头碰到 下墙壁
    {
        meet = true;//碰壁变量为真
    }
    else
    {
        leftTop = QPointF(snake[0].x(),snake[0].y()+nodeHeight);//左上角
        rightBotom = QPointF(snake[0].x()+nodeWidth,snake[0].y()+nodeHeight*2);//右下角
    }
    snake.insert(0,QRectF(leftTop,rightBotom));//插入蛇的新节点(蛇头)
}

//左边添加长度
void Widget::addLeft()
{
    QPointF leftTop;//左上角的点坐标
    QPointF rightBotom;//右下角的点坐标
    if(snake[0].x()-nodeWidth < 0)//蛇头碰到 左墙壁
    {
        meet = true;//碰壁变量为真
    }
    else
    {
        leftTop = QPointF(snake[0].x()-nodeWidth,snake[0].y());//左上角
        rightBotom = QPointF(snake[0].x(),snake[0].y()+nodeHeight);//右下角
    }
    snake.insert(0,QRectF(leftTop,rightBotom));//插入蛇的新节点(蛇头)
}

//右边添加长度
void Widget::addRight()
{
    QPointF leftTop;//左上角的点坐标
    QPointF rightBotom;//右下角的点坐标
    if(snake[0].x()+nodeWidth*2 > window_length)//蛇头碰到 右墙壁
    {
        meet = true;//碰壁变量为真
    }
    else
    {
        leftTop = QPointF(snake[0].x()+nodeWidth,snake[0].y());//左上角
        rightBotom = QPointF(snake[0].x()+nodeWidth*2,snake[0].y()+nodeHeight);//右下角
    }
    snake.insert(0,QRectF(leftTop,rightBotom));//插入蛇的新节点(蛇头)
}

//判断蛇头是否咬到自己 或者 碰壁
bool Widget::checkMeet()
{
    if(meet == true)//判断蛇头是否碰壁
        return true;
    for(int i=0;ikey())//传入的按键信号
    {
    case Qt::Key_Up:
        if(moveFlag != DIR_DOWN)//当前方向不是下,就改变为上
        moveFlag = DIR_UP;
        break;

    case Qt::Key_Down:
        if(moveFlag != DIR_UP)//当前方向不是上,就改变为下
        moveFlag = DIR_DOWN;
        break;

    case Qt::Key_Left:
        if(moveFlag != DIR_RIGHT)//当前方向不是右,就改变为左
        moveFlag = DIR_LEFT;
        break;

    case Qt::Key_Right:
        if(moveFlag != DIR_LEFT)//当前方向不是左,就改变为右
        moveFlag = DIR_RIGHT;
        break;

    case Qt::Key_Space://空格键
        if(gameStart == false)
        {
            gameStart = true;//如果游戏暂停,则开始
           timer->start(time);//超时时间间隔,刷新
        }
        else
        {
            gameStart = false;//如果游戏已经开始,则暂停
            //timer->stop();//游戏暂停,移到打印字体的语句中
        }
        break;
    default:
        break;
    }
}

//添加食物
void Widget::addNewFood()
{
        food = QRectF(//除以20再乘以18是为了 使得随机数都是长宽的
                      //公因数(等于蛇方块的大小),保证食物和蛇头是对齐的
                    qrand()%(this->width()/20)*20,//x坐标
                    qrand()%(this->height()/20)*20,//y坐标
                    nodeWidth,
                    nodeHeight);
}

void Widget::paintEvent(QPaintEvent *event)
{
    //背景图片
    QPainter painter(this);//定义这个窗口的画家
    QPen pen;//笔
    QBrush brush;//画刷

    QPixmap pix;//背景图片
    pix.load(":/BGP.png");//加载背景图片
    painter.drawPixmap(0,0,window_length,window_width,pix);//画出背景图

    //改变画笔和画刷的样式
    pen.setColor(Qt::black);
    brush.setColor(Qt::green);
    brush.setStyle(Qt::SolidPattern);
    painter.setPen(pen);
    painter.setBrush(brush);
    //画蛇
    for(int i=0;istop();//游戏结束 计时器停止
    }

    if(gameStart == false)//游戏暂停的时候
    {
        QFont font("宋体",30,QFont::ExtraBold,false);//设置字体样式
        painter.setFont(font);
        painter.drawText(0,//x坐标
                         nodeHeight*7,//y坐标
                         QString("欢迎试玩"));
        timer->stop();
    }

    pen.setColor(Qt::red);
    brush.setColor(Qt::red);
    painter.setPen(pen);
    painter.setBrush(brush);
    QFont font("宋体",30,QFont::ExtraBold,false);
    painter.setFont(font);
    painter.drawText(0,nodeHeight*3,
                     QString("分数:"+QString::number(score)));
                       //将分数转化为字符串,然后输出

    QWidget::paintEvent(event);//防止报错:未使用的参数“event”
}





参考视频在这里

你可能感兴趣的:(Qt,游戏)