贪吃蛇小游戏(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);
}
相关推荐
isyangli_blog10 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb20081110 小时前
FastAPI APIRouter
开发语言·python
Benszen10 小时前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆10 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木10 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
杨充11 小时前
1.3 浮点型数据设计灵魂
开发语言·python·算法
噜噜噜阿鲁~11 小时前
python学习笔记 | 11.3、面向对象高级编程-多重继承
java·开发语言
basketball61611 小时前
Go 语言从入门到进阶:4. 数组和MAP使用方法总结
开发语言·后端·golang
春生野草11 小时前
反射、Tomcat执行
java·开发语言
雪的季节12 小时前
企业级 Qt 全功能项目
开发语言·数据库·qt