贪吃蛇小游戏(Qt)

运用Qt实现贪吃蛇小游戏的具体代码

游戏大厅

hall.h

c 复制代码
#ifndef HALL_H
#define HALL_H

#include <QWidget>
#include <QPaintEvent>
QT_BEGIN_NAMESPACE
namespace Ui { class Hall; }
QT_END_NAMESPACE

class Hall : public QWidget
{
    Q_OBJECT

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

    //重写绘图事件
    void paintEvent(QPaintEvent *event);



private:
    Ui::Hall *ui;
};
#endif // HALL_H

hall.cpp

c 复制代码
#include "hall.h"
#include "ui_hall.h"

#include <QPainter>
#include <QPixmap>
#include <QPushButton>
#include <QIcon>
#include <QFont>
#include <QDialog>
#include <QVBoxLayout>
#include <QSound>
#include <QLabel>
#include "game_select.h"
#include "hint.h"
Hall::Hall(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Hall)
{
    ui->setupUi(this);
    this->setFixedSize(1200,800);//设置窗口初始大小

    this->setWindowIcon(QIcon(":res/ico.png"));// 窗口图标
    this->setWindowTitle("贪吃蛇");

    QFont font("华文隶书",40);
    QPushButton* start=new QPushButton(this);

    start->move(440,630);
    start->setText("开始游戏");
    start->setFont(font);
    start->setStyleSheet("QPushButton{border-radius: 10px; background-color: green;}"
                         "QPushButton:pressed{background-color: white}");
    Game_select* gameselect=new Game_select;
    connect(start,&QPushButton::clicked,[=](){
        this->close();
        QSound::play(":res/clicked.wav");
        gameselect->setGeometry(this->geometry());
        gameselect->show();
    });


    QPushButton* hint=new QPushButton(this);
    Hint* H_t=new Hint;
    connect(hint,&QPushButton::clicked,[=](){
        H_t->show();


    });
    hint->move(20,20);
    hint->setIconSize(QSize(50,50));
    hint->setText("免责声明");
    hint->setFont(QFont("宋体",24));
    hint->setIcon(QIcon(":res/tishi.png"));


}

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





void Hall::paintEvent(QPaintEvent *event)
{
    (void) event;
    QPainter painter(this);
    QPixmap pixmap(":res/game_hall.png");
    painter.drawPixmap(0,0,this->width(),this->height(),pixmap);
}

选关界面

game_select.h

c 复制代码
#ifndef GAME_SELECT_H
#define GAME_SELECT_H

#include <QWidget>

class Game_select : public QWidget
{
    Q_OBJECT
public:
    explicit Game_select(QWidget *parent = nullptr);

    void paintEvent(QPaintEvent *event);

signals:

};

#endif // GAME_SELECT_H

game_select.cpp

c 复制代码
#include "game_select.h"
#include "game_room.h"
#include "hall.h"
#include <QIcon>
#include <QPushButton>
#include <QSound>
#include <QPainter>
#include <QPixmap>
#include <QFont>
#include <QTextEdit>
#include <QFile>
#include <QTextStream>
Game_select::Game_select(QWidget *parent) : QWidget(parent)
{

    this->setFixedSize(800,900);
    this->setWindowIcon(QIcon(":res/ico.png"));// 窗口图标
    this->setWindowTitle("关卡选择");
    QPushButton* ret=new QPushButton(this);
    ret->resize(80,80);
    ret->setIcon(QIcon(":res/back.png"));
    ret->move(this->width()-100,this->height()-100);

    connect(ret,&QPushButton::clicked,[=](){
        this->close();
        Hall* hall=new Hall;
        hall->show();
        QSound::play(":res/eatfood.wav");
    });






    QFont font("华文隶书",40);

    Game_room* gameroom=new Game_room;

    QPushButton* simplebutt=new QPushButton(this);
    simplebutt->move(350,200);
    simplebutt->setText("简单模式");
    simplebutt->setFont(font);
    connect(simplebutt,&QPushButton::clicked,[=](){
       this->close();
       gameroom->setFixedSize(1200,800);
       gameroom->setWindowIcon(QIcon(":res/ico.png"));// 窗口图标
       gameroom->setWindowTitle("贪吃蛇: 简单模式");
       gameroom->show();

       gameroom->setTimeOut(300);//设置不同难度的速度
    });

    QPushButton* normalbutt=new QPushButton(this);
    normalbutt->move(350,400);
    normalbutt->setText("普通模式");
    normalbutt->setFont(font);
    connect(normalbutt,&QPushButton::clicked,[=](){
       this->close();
       gameroom->setFixedSize(1200,800);
       gameroom->setWindowIcon(QIcon(":res/ico.png"));// 窗口图标
       gameroom->setWindowTitle("贪吃蛇: 普通模式");
       gameroom->show();

       gameroom->setTimeOut(200);//设置不同难度的速度
    });

    QPushButton* hardbutt=new QPushButton(this);
    hardbutt->move(350,600);
    hardbutt->setText("困难模式");
    hardbutt->setFont(font);
    connect(hardbutt,&QPushButton::clicked,[=](){
       this->close();
       gameroom->setFixedSize(1200,800);
       gameroom->setWindowIcon(QIcon(":res/ico.png"));// 窗口图标
       gameroom->setWindowTitle("贪吃蛇: 困难模式");
       gameroom->show();

       gameroom->setTimeOut(100);//设置不同难度的速度
    });

    QPushButton* history=new QPushButton(this);
    history->move(60,80);
    history->setText("历史记录");
    history->setFont(font);

    connect(history,&QPushButton::clicked,[=](){
        QWidget* widget=new QWidget;

        widget->setWindowTitle("历史战绩");
        widget->setFixedSize(500,400);
        widget->setWindowIcon(QIcon(":res/ico.png"));
        QTextEdit* edit=new QTextEdit(widget);
        edit->setFont(QFont("黑体",30));
        edit->setFixedSize(500,400);
        QFile file("C:/Users/xcj/Desktop/snake/snake/his.txt");
        file.open(QIODevice::ReadOnly);
        QTextStream in(&file);
        int data=in.readLine().toInt();
        edit->setText("上一次得分为:");
        edit->append(QString::number(data));//追加

        widget->show();
    });

}

void Game_select::paintEvent(QPaintEvent *event)
{
   (void) event;
   QPainter painter(this);
   QPixmap pix(":res/game_select.png");
   painter.drawPixmap(0,0,this->width(),this->height(),pix);
}

游戏界面

game_room

c 复制代码
#ifndef GAME_ROOM_H
#define GAME_ROOM_H

#include <QWidget>
#include <QSound>
//枚举蛇的移动方向
enum class SnakeDirect
{
    UP=0,
    DOWN,
    LEFT,
    RIGHT
};

class Game_room : public QWidget
{
    Q_OBJECT
public:
    explicit Game_room(QWidget *parent = nullptr);

    void paintEvent(QPaintEvent *event);

    void moveUp();//向上移动
    void moveDOWN();//向下移动
    void moveLEFT();//向左移动
    void moveRIGHT();//向右移动

    bool isOver();//检测是否结束

    void createNewFood();//创建新的食物

    void setTimeOut(int timeout)
    {
        moveTimeout =timeout;
    }

private:
    const int kSnakeNodeWidth =20;//定义蛇节点的宽度
    const int kSnakeNodeHeight =20;//定义蛇节点的高度
    const int kDefaultTimeout = 200;//蛇的移动速度

    QList<QRectF> snakeList; //表示贪吃蛇链表
    QRectF foodRect; //食物节点
    SnakeDirect moveDirect=SnakeDirect::UP; //蛇默认移动方向位向上
    QTimer* timer;//定时器

    bool isGameStart = false;//是否开始游戏

    QSound * sound;//bgm

    int moveTimeout = kDefaultTimeout;

};

#endif // GAME_ROOM_H

game_room.cpp

c 复制代码
#include "game_room.h"
#include <QPushButton>
#include <QPainter>
#include <QPixmap>
#include <QTimer>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include "game_select.h"
Game_room::Game_room(QWidget *parent) : QWidget(parent)
{
    //初始化蛇
    snakeList.push_back(QRectF(this->width()*0.5,this->height()*0.5,kSnakeNodeWidth,kSnakeNodeHeight));

    moveUp();
    moveUp();

    //创建食物
    createNewFood();
    timer=new QTimer(this);
    connect(timer,&QTimer::timeout,[=](){
        int cnt=1;
        // 通过intersects方法来判断蛇头与食物是否相交
        if(snakeList.front().intersects(foodRect))
        {
            QSound::play(":res/eatfood.wav");
            createNewFood();
            cnt++;
        }

        while(cnt--)
        {
            switch (moveDirect)
            {
            case SnakeDirect::UP:
                moveUp();
                break;

            case SnakeDirect::DOWN:
                moveDOWN();
                break;

            case SnakeDirect::LEFT:
                moveLEFT();
                break;

            case SnakeDirect::RIGHT:
                moveRIGHT();
                break;
            }
        }

        snakeList.pop_back();
        update();//更新链表

    });


    //开始与暂停按钮
    QPushButton* startb=new QPushButton(this);
    QPushButton* stopb=new QPushButton(this);

    QFont font("华文隶书",20);
    startb->move(980,150);
    stopb->move(980,225);

    startb->setText("开始游戏");
    stopb->setText("暂停游戏");

    startb->setFont(font);
    stopb->setFont(font);

    connect(startb,&QPushButton::clicked,[=](){
        isGameStart=true;
        timer->start(moveTimeout);
        sound=new QSound(":res/BGM.wav");
        sound->play();
        sound->setLoops(-1);//只要是真就循环播放
    });

    connect(stopb,&QPushButton::clicked,[=](){
        isGameStart=false;
        timer->stop();
        sound->stop();
    });

    //控制方向
    QPushButton* up=new QPushButton(this);
    QPushButton* down=new QPushButton(this);
    QPushButton* left=new QPushButton(this);
    QPushButton* right=new QPushButton(this);

    up->move(1020,372);
    down->move(1020,440);
    left->move(952,440);
    right->move(1088,440);

    up->setText("↑");
    down->setText("↓");
    left->setText("←");
    right->setText("→");

    up->setStyleSheet("QPushButton{border-radius: 10px; background-color: green;}"
                      "QPushButton:pressed{background-color: white}");
    down->setStyleSheet("QPushButton{border-radius: 10px; background-color: green;}"
                      "QPushButton:pressed{background-color: white}");
    left->setStyleSheet("QPushButton{border-radius: 10px; background-color: green;}"
                      "QPushButton:pressed{background-color: white}");
    right->setStyleSheet("QPushButton{border-radius: 10px; background-color: green;}"
                      "QPushButton:pressed{background-color: white}");

    up->setShortcut(QKeySequence(Qt::Key_Up));
    down->setShortcut(QKeySequence(Qt::Key_Down));
    left->setShortcut(QKeySequence(Qt::Key_Left));
    right->setShortcut(QKeySequence(Qt::Key_Right));

    QFont FF("宋体",40);
    up->setFont(FF);
    down->setFont(FF);
    left->setFont(FF);
    right->setFont(FF);

    //控制蛇的方向
    connect(up,&QPushButton::clicked,[=](){
        if(moveDirect != SnakeDirect::DOWN)
            moveDirect=SnakeDirect::UP;
    });
    connect(down,&QPushButton::clicked,[=](){
        if(moveDirect != SnakeDirect::UP)
            moveDirect=SnakeDirect::DOWN;
    });
    connect(left,&QPushButton::clicked,[=](){
        if(moveDirect != SnakeDirect::RIGHT)
            moveDirect=SnakeDirect::LEFT;
    });
    connect(right,&QPushButton::clicked,[=](){
        if(moveDirect != SnakeDirect::LEFT)
            moveDirect=SnakeDirect::RIGHT;
    });

    //退出游戏
    QPushButton* exit =new QPushButton(this);
    exit->move(935,690);
    exit->setText("退出");
    exit->setFont(QFont("华文琥珀",15));
    exit->setStyleSheet("QPushButton{border-radius: 10px;background-color: pink;}"
                        "QPushButton:pressed{background-color: blue;}");

    QMessageBox* msg=new QMessageBox(this);
    QPushButton* ok=new QPushButton("确认");
    QPushButton* cancel=new QPushButton("取消");

    msg->addButton(ok,QMessageBox::AcceptRole);
    msg->addButton(cancel,QMessageBox::RejectRole);

    msg->setWindowTitle("退出游戏");
    msg->setText("是否"
                 "退出游戏?");
    msg->setFont(QFont("隶书",12));
    msg->setIconPixmap(QPixmap(":res/exit.png"));

    connect(exit,&QPushButton::clicked,[=](){
        QSound::play(":res/clicked.wav");
        msg->show();
        msg->exec();//事件轮询  等待用户输入

        Game_select* select=new Game_select;


        if(msg->clickedButton()==ok)
        {
            this->close();
            select->show();
        }
        else
        {
            msg->close();
        }
    });



}

void Game_room::paintEvent(QPaintEvent *event)
{
    (void) event;
    QPainter painter(this);
    QPixmap pix;

    pix.load(":res/game_room.png");
    painter.drawPixmap(0,0,900,this->height(),pix);

    pix.load(":res/game_room.2.png");
    painter.drawPixmap(900,0,300,this->height(),pix);

    //绘制蛇
    //蛇头
    if(moveDirect ==SnakeDirect::UP)
    {
        pix.load(":res/up.png");
    }
    else if(moveDirect == SnakeDirect::DOWN)
    {
        pix.load(":res/down.png");
    }
    else if(moveDirect == SnakeDirect::LEFT)
    {
        pix.load(":res/left.png");
    }
    else if(moveDirect == SnakeDirect::RIGHT)
    {
        pix.load(":res/right.png");
    }

    auto snakeHead=snakeList.front();
    painter.drawPixmap(snakeHead.x(),snakeHead.y(),kSnakeNodeWidth,kSnakeNodeHeight,pix);

    //绘制身体
    if(moveDirect ==SnakeDirect::UP)
    {
        pix.load(":res/bd.png");
    }
    else if(moveDirect == SnakeDirect::DOWN)
    {
        pix.load(":res/bd_D.png");
    }
    else if(moveDirect == SnakeDirect::LEFT)
    {
        pix.load(":res/bd_L.png");
    }
    else if(moveDirect == SnakeDirect::RIGHT)
    {
        pix.load(":res/bd_R.png");
    }
    for (int i=1;i<snakeList.size()-1;i++)
    {
        auto node = snakeList.at(i);
        painter.drawPixmap(node.x(),node.y(),node.width(),node.height(),pix);
    }

    //绘制尾部
    if(moveDirect ==SnakeDirect::UP)
    {
        pix.load(":res/tail.png");
    }
    else if(moveDirect == SnakeDirect::DOWN)
    {
        pix.load(":res/tail_D.png");
    }
    else if(moveDirect == SnakeDirect::LEFT)
    {
        pix.load(":res/tail_L.png");
    }
    else if(moveDirect == SnakeDirect::RIGHT)
    {
        pix.load(":res/tail_R.png");
    }
    auto snakeTail = snakeList.back();
    painter.drawPixmap(snakeTail.x(),snakeTail.y(),snakeTail.width(),snakeTail.height(),pix);

    //绘制食物
    pix.load(":res/food.png");
    painter.drawPixmap(foodRect.x(),foodRect.y(),kSnakeNodeWidth,kSnakeNodeHeight,pix);

    //绘制分数
    pix.load(":res/scores_bg.png");
    painter.drawPixmap(920,4,230,150,pix);
    QPen pen;
    pen.setColor(Qt::black);
    painter.setPen(pen);
    QFont num("方正舒体",30);
    painter.setFont(num);
    painter.drawText(1000,95,QString("%1").arg(snakeList.size()));

    //写入分数;
    int n=snakeList.size();
    QFile file("C:/Users/xcj/Desktop/snake/snake/his.txt");
    if(file.open(QIODevice::WriteOnly))
    {
        QTextStream out(&file);
        int num=n;
        out<<num;//把num写入文件
        file.close();
    }


    //绘制游戏结束
    if(isOver())
    {
        pen.setColor(Qt::green);
        painter.setPen(pen);
        QFont over("华文琥珀",80);
        painter.setFont(over);
        painter.drawText(80,this->height()*0.5,QString("GAME OVER!"));
        timer->stop();
        QSound::play(":res/gameover.wav");

        sound->stop();
    }

}

void Game_room::moveUp()
{
    QPointF leftTop;//左上角坐标
    QPointF rightbutt;//右下角坐标

    auto snakeNode = snakeList.front();//表示蛇头
    int headx = snakeNode.x();
    int heady = snakeNode.y();

    if(heady<0)//穿墙时
    {
        leftTop = QPointF(headx,this->height()-kSnakeNodeHeight);
    }
    else
    {
        leftTop = QPointF(headx,heady-kSnakeNodeHeight);
    }

    rightbutt=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);

    snakeList.push_front(QRectF(leftTop,rightbutt));
}

void Game_room::moveDOWN()
{
    QPointF leftTop;//左上角坐标
    QPointF rightbutt;//右下角坐标

    auto snakeNode = snakeList.front();//表示蛇头
    int headx = snakeNode.x();
    int heady = snakeNode.y();

    if(heady>this->height())//穿墙时
    {
        leftTop = QPointF(headx,0);
    }
    else
    {
        leftTop = snakeNode.bottomLeft();//获取矩形左下角坐标
    }

    rightbutt=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);

    snakeList.push_front(QRectF(leftTop,rightbutt));
}

void Game_room::moveLEFT()
{
    QPointF leftTop;//左上角坐标
    QPointF rightbutt;//右下角坐标

    auto snakeNode = snakeList.front();//表示蛇头
    int headx = snakeNode.x();
    int heady = snakeNode.y();

    if(headx<0)//穿墙时
    {
        leftTop = QPointF(900-kSnakeNodeWidth,heady);
    }
    else
    {
        leftTop = QPointF(headx-kSnakeNodeWidth,heady);
    }

    rightbutt=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);

    snakeList.push_front(QRectF(leftTop,rightbutt));
}

void Game_room::moveRIGHT()
{
    QPointF leftTop;//左上角坐标
    QPointF rightbutt;//右下角坐标

    auto snakeNode = snakeList.front();//表示蛇头
    int headx = snakeNode.x();
    int heady = snakeNode.y();

    if(headx+kSnakeNodeWidth>880)//穿墙时
    {
        leftTop = QPointF(0,heady);
    }
    else
    {
        leftTop = snakeNode.topRight();
    }

    rightbutt=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);

    snakeList.push_front(QRectF(leftTop,rightbutt));
}

bool Game_room::isOver()
{
    for(int i=0;i<snakeList.size();i++)
    {
        for(int j=i+1;j<snakeList.size();j++)
        {
            if(snakeList.at(i) == snakeList.at(j))
            {
                return true;
            }
        }
    }

    return false;
}

void Game_room::createNewFood()
{
    foodRect = QRectF(qrand()%(900/kSnakeNodeWidth)*kSnakeNodeWidth,
                     qrand()%(this->height()/kSnakeNodeHeight)*kSnakeNodeHeight,
                     kSnakeNodeWidth,kSnakeNodeHeight);
}
相关推荐
zongzi_49426 分钟前
二次封装的天气时间日历选择组件
开发语言·javascript·ecmascript
平头哥在等你32 分钟前
求一个3*3矩阵对角线元素之和
c语言·算法·矩阵
kikyo哎哟喂36 分钟前
Java 代理模式详解
java·开发语言·代理模式
AI_小站37 分钟前
RAG 示例:使用 langchain、Redis、llama.cpp 构建一个 kubernetes 知识库问答
人工智能·程序人生·langchain·kubernetes·llama·知识库·rag
duration~42 分钟前
SpringAOP模拟实现
java·开发语言
一条晒干的咸魚1 小时前
【Web前端】实现基于 Promise 的 API:alarm API
开发语言·前端·javascript·api·promise
尹蓝锐1 小时前
C语言-11-18笔记
c语言
ahadee1 小时前
蓝桥杯每日真题 - 第18天
c语言·vscode·算法·蓝桥杯
就爱六点起1 小时前
C/C++ 中的类型转换方式
c语言·开发语言·c++
我明天再来学Web渗透1 小时前
【SQL50】day 2
开发语言·数据结构·leetcode·面试