Qt:26.Qt项目:贪吃蛇游戏

一、项目功能演示:

  • 开始界面可以点击进入游戏。

        

  • 点击进入游戏之后,切换到选项界面,该界面可以选择游戏难度,回退,以及查询最近一次游戏得分。

        

  • 游戏具体界面如下。贴图啥的可以自己换,本人审美不咋行,随便找的贴图。

        

        

二、文件展示:

三、项目代码:

1.打开窗口实现:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
#include <QLabel>
#include <QFont>
#include <QSound>
#include "gameselect.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    //初始化窗口,标题,图标,窗口大小
    ui->setupUi(this);
    this->setWindowTitle("贪吃蛇");
    this->setWindowIcon(QIcon(":/image/pix.png"));
    this->setFixedSize(600,400);

    //窗口背景设置,将图片设置自动拉伸
    QLabel* label=new QLabel(this);
    label->setGeometry(0,0,this->width(),this->height());
    label->setPixmap(QPixmap(":/image/enter.jpg"));
    label->setScaledContents(true);

    //设置进入按钮
    QPushButton* enter_but=new QPushButton(this);
    enter_but->move(250,250);
    enter_but->setText("进入游戏");
    enter_but->setStyleSheet("QPushButton{border:0px;color:red;}");

    //按钮文本设置
    QFont font("华文行楷",18);
    enter_but->setFont(font);

    //创建选项页面,设置点击音效,打开新窗口,关闭旧窗口
    GameSelect* gameSelect=new GameSelect;
    connect(enter_but,&QPushButton::clicked,[=]()
    {
        gameSelect->setGeometry(this->geometry());
        QSound::play(":/image/6.wav");
        gameSelect->show();
        this->close();

    });

}

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

2.选项窗口实现:

#include "gameselect.h"
#include <QIcon>
#include <QLabel>
#include <QDebug>
#include <QVBoxLayout>
#include <QPushButton>
#include <QFont>
#include "mainwindow.h"
#include <QSound>
#include "gameroom.h"
#include <QFile>

GameSelect::GameSelect(QWidget *parent) : QWidget(parent)
{

    //窗口大小固定,设置图标,标题
    this->setFixedSize(600,400);
    this->setWindowTitle("关卡选择");
    this->setWindowIcon(QIcon(":/image/pix.png"));

    //加载背景
    QLabel* label=new QLabel(this);
    label->setGeometry(this->geometry());
    label->setPixmap(QPixmap(":/image/load.jpg"));

    //创建一个widget对象存放布局管理器,管理选项按钮
    QWidget* widget=new QWidget(this);
    widget->setGeometry(150,100,300,250);

    //创建布局管理器,并将它设置到widget对象
    QVBoxLayout* layout=new QVBoxLayout;
    widget->setLayout(layout);

    //选项按钮创建
    QPushButton* but_easy=new QPushButton("简单模式");
    QPushButton* but_normal=new QPushButton("正常模式");
    QPushButton* but_diff=new QPushButton("困难模式");
    QPushButton* but_grades=new QPushButton("战绩查询");
    QPushButton* but_ret=new QPushButton("返回上页");

    //按钮添加到布局管理器
    layout->addWidget(but_easy);
    layout->addWidget(but_normal);
    layout->addWidget(but_diff);
    layout->addWidget(but_grades);
    layout->addWidget(but_ret);

    //设置按钮的拉伸策略,是的可以占满整个布局管理器
    but_easy->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    but_normal->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    but_diff->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    but_grades->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    but_ret->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);

    QFont font("华文行楷",25);
    widget->setFont(font);

    //设置按钮无边框,文本显示颜色为蓝色
    but_easy->setStyleSheet("QPushButton{border: 0px;color:blue;}");
    but_normal->setStyleSheet("QPushButton{border: 0px;color:blue;}");
    but_diff->setStyleSheet("QPushButton{border: 0px;color:blue;}");
    but_grades->setStyleSheet("QPushButton{border: 0px;color:blue;}");
    but_ret->setStyleSheet("QPushButton{border: 0px;color:blue;}");


    //连接按钮和槽函数,直接使用lambda表达式
    connect(but_ret,&QPushButton::clicked,[=]()
    {
       MainWindow* mainwindow=new MainWindow;
       QSound::play(":/image/6.wav");
       mainwindow->show();
       this->close();
    });

    GameRoom* room=new GameRoom;
    connect(but_easy,&QPushButton::clicked,[=]()
    {

        room->setGeometry(this->geometry());
        QSound::play(":/image/6.wav");
        room->show();
        this->close();

        room->setMoveTimeout(300);

    });

    connect(but_normal,&QPushButton::clicked,[=]()
    {
        room->setGeometry(this->geometry());
        QSound::play(":/image/6.wav");
        room->show();
        this->close();
        room->setMoveTimeout(200);

    });

    connect(but_diff,&QPushButton::clicked,[=]()
    {
        room->setGeometry(this->geometry());
        QSound::play(":/image/6.wav");
        room->show();
        this->close();
        room->setMoveTimeout(100);
    });

    connect(but_grades, &QPushButton::clicked, [=]() {
        QSound::play(":/image/6.wav");
        QWidget* widget = new QWidget;
        widget->setWindowTitle("历史分数");
        widget->setWindowIcon(QIcon(":/image/pix.png"));
        widget->setFixedSize(400, 200);
        QLabel* label=new QLabel(widget);
        label->setGeometry(0,0,400,200);

        QFile file("C:/Users/86133/Desktop/Qt-tmp.txt");
        file.open(QIODevice::ReadOnly);
        QTextStream in(&file);
        QString grade=in.readLine();

        QFont font("行书",30);
        label->setFont(font);

        label->setText("最近得分:"+ grade);
        widget->show();
    });

}

3.游戏窗口实现

#include "gameroom.h"
#include <QIcon>
#include <QPainter>
#include <QTimer>
#include <QPushButton>
#include <QMessageBox>
#include "gameselect.h"
#include <QFile>
#include <QTextStream>
#include <QShortcut>

GameRoom::GameRoom(QWidget *parent) : QWidget(parent)
{
    
    //初始化窗口,标题,图标,大小
    this->setWindowTitle("游戏房间");
    this->setWindowIcon(QIcon(":/image/pix.png"));
    this->setFixedSize(600,400);

    //尾插一个节点作为头节点
    snakeList.push_back(QRectF(160,220,kSnakeNodeWidth,kSnakeNodeHeight));
    moveUp();
    moveUp();

    //创建食物
    createFood();

    //定时器设置
    timer=new QTimer(this);
    connect(timer,&QTimer::timeout,[=]()
    {
        //如果吃到食物,重新生成食物
        int cnt=1;
        if(snakeList.front().intersects(foodRect))
        {
            createFood();
            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* sta_but=new QPushButton("开始游戏",this);
    QPushButton* stop_but=new QPushButton("暂停游戏",this);

    sta_but->move(450,100);
    stop_but->move(450,150);

    QFont font("楷体",15);
    sta_but->setFont(font);
    stop_but->setFont(font);

    //开始功能实现,音乐播放,音乐持续播放设置
    connect(sta_but,&QPushButton::clicked,[=]()
    {
        isGameStart=true;
        timer->start(moveTimeout);
        sound=new QSound(":/image/2.wav");
        sound->play();
        sound->setLoops(-1);
    });

    connect(stop_but,&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(480,230);
    down->move(480,270);
    left->move(440,250);
    right->move(520,250);

    up->setStyleSheet("QPushButton{border:0px}");
    down->setStyleSheet("QPushButton{border:0px}");
    left->setStyleSheet("QPushButton{border:0px}");
    right->setStyleSheet("QPushButton{border:0px}");

    QFont ft("楷体",25);
    up->setFont(ft);
    down->setFont(ft);
    left->setFont(ft);
    right->setFont(ft);

    QShortcut* s1=new QShortcut(QKeySequence("W"),up);
    QShortcut* s2=new QShortcut(QKeySequence("S"),down);
    QShortcut* s3=new QShortcut(QKeySequence("A"),left);
    QShortcut* s4=new QShortcut(QKeySequence("D"),right);

    QObject::connect(s1,&QShortcut::activated,up,&QPushButton::click);
    QObject::connect(s2,&QShortcut::activated,down,&QPushButton::click);
    QObject::connect(s3,&QShortcut::activated,left,&QPushButton::click);
    QObject::connect(s4,&QShortcut::activated,right,&QPushButton::click);

    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_but=new QPushButton("退出游戏",this);
    exit_but->move(450,350);
    exit_but->setFont(font);

    QMessageBox* msg=new QMessageBox(this);
    QPushButton* ok=new QPushButton("ok");
    QPushButton* cancel=new QPushButton("cancel");
    msg->addButton(ok,QMessageBox::AcceptRole);
    msg->addButton(cancel,QMessageBox::RejectRole);
    msg->setWindowTitle("退出");
    msg->setText("是否确定退出?");

    connect(exit_but,&QPushButton::clicked,[=]()
    {
        msg->exec();
        QSound::play(":/image/6.wav");
        if(msg->clickedButton()==ok)
        {
            GameSelect* gameselect=new GameSelect;
            gameselect->show();
            this->close();
        }
        else
        {
            msg->close();
        }
    });


}

void GameRoom::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/image/main.jpg");
    painter.drawPixmap(0,0,400,400,pix);
    pix.load(":/image/control.jpg");
    painter.drawPixmap(400,0,200,400,pix);

    //绘制蛇头
    if(moveDirect==SnakeDirect::UP)
        pix.load(":/image/up.png");
    else if(moveDirect==SnakeDirect::DOWN)
        pix.load(":/image/down.png");
    else if(moveDirect==SnakeDirect::LEFT)
        pix.load(":/image/left.png");
    else
        pix.load(":/image/right.png");
    auto snakeHead=snakeList.front();
    painter.drawPixmap(snakeHead.x(),snakeHead.y(),snakeHead.width(),snakeHead.height(),pix);

    //绘制蛇身
    pix.load(":/image/circle.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);

    }

    //绘制蛇尾
    auto snakeTail=snakeList.back();
    painter.drawPixmap(snakeTail.x(),snakeTail.y(),snakeTail.width(),snakeTail.height(),pix);

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

    //将分数绘制到界面
    QPen pen;
    pen.setColor(Qt::black);
    painter.setPen(pen);
    QFont font("楷体",15);
    painter.setFont(font);

    painter.drawText(430,30,"当前等分:");
    painter.drawText(530,30,QString("%1").arg(snakeList.size()-3));

    //绘制失败效果
    if(checkFail())
    {
        pen.setColor(Qt::red);
        QFont font("楷体",30);
        painter.setPen(pen);
        painter.setFont(font);
        painter.drawText(100,180,"Game Over");
        timer->stop();
        sound->stop();
    }

    //将当前分数保存到文件中
    int c=snakeList.size()-3;
    QFile file("C:/Users/86133/Desktop/Qt-tmp.txt");
    if(file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        QTextStream out(&file);
        int num=c;
        out<<num;
        file.close();
    }


}

void GameRoom::moveUp()
{
    QPointF leftTop;
    QPointF rightBottom;
    auto snakeHead=snakeList.front();
    int headX=snakeHead.x();
    int headY=snakeHead.y();

    if(headY<20)
    {
        leftTop=QPointF(headX,this->height()-kSnakeNodeHeight);
    }
    else
    {
        leftTop=QPointF(headX,headY-kSnakeNodeHeight);
    }
    rightBottom=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);
    snakeList.push_front(QRectF(leftTop,rightBottom));
}

void GameRoom::moveDown()
{
    QPointF leftTop;
    QPointF rightBottom;
    auto snakeHead=snakeList.front();
    int headX=snakeHead.x();
    int headY=snakeHead.y();

    if(headY>this->height()-40)
    {
        leftTop=QPointF(headX,0);
    }
    else
    {
        leftTop=snakeHead.bottomLeft();
    }
    rightBottom=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);
    snakeList.push_front(QRectF(leftTop,rightBottom));
}

void GameRoom::moveLeft()
{
    QPointF leftTop;
    QPointF rightBottom;
    auto snakeHead=snakeList.front();
    int headX=snakeHead.x();
    int headY=snakeHead.y();

    if(headX<20)
    {
        leftTop=QPointF(400-kSnakeNodeWidth,headY);
    }
    else
    {
        leftTop=QPointF(headX-kSnakeNodeWidth,headY);
    }
    rightBottom=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);
    snakeList.push_front(QRectF(leftTop,rightBottom));
}

void GameRoom::moveRight()
{
    QPointF leftTop;
    QPointF rightBottom;
    auto snakeHead=snakeList.front();
    int headX=snakeHead.x();
    int headY=snakeHead.y();

    if(headX>360)
    {
        leftTop=QPointF(0,headY);
    }
    else
    {
        leftTop=snakeHead.topRight();
    }
    rightBottom=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);
    snakeList.push_front(QRectF(leftTop,rightBottom));
}

bool GameRoom::checkFail()
{
    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 GameRoom::createFood()
{
    foodRect=QRectF(qrand()%(400/kSnakeNodeWidth)*kSnakeNodeWidth,
                    qrand()%(400/kSnakeNodeHeight)*kSnakeNodeHeight,kSnakeNodeWidth,kSnakeNodeHeight);
}


需要项目的源文件,私发。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是使用Qt编写的贪吃蛇游戏代码示例: ```cpp #include <QMainWindow> #include <QPainter> #include <QKeyEvent> #include <QTimer> class SnakeGame : public QMainWindow { Q_OBJECT public: SnakeGame(QWidget *parent = nullptr) : QMainWindow(parent) { setFixedSize(400, 400); snake_.push_back({200, 200}); snake_.push_back({200, 210}); snake_.push_back({200, 220}); food_ = generateFood(); QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(update())); timer->start(100); } protected: void paintEvent(QPaintEvent *event) override { QPainter painter(this); painter.setPen(Qt::NoPen); painter.setBrush(Qt::black); painter.drawRect(0, 0, width(), height()); painter.setBrush(Qt::red); painter.drawRect(food_.x(), food_.y(), 10, 10); painter.setBrush(Qt::green); for (const auto &pos : snake_) { painter.drawRect(pos.x(), pos.y(), 10, 10); } } void keyPressEvent(QKeyEvent *event) override { if (event->key() == Qt::Key_Left && direction_ != Direction::Right) { direction_ = Direction::Left; } else if (event->key() == Qt::Key_Right && direction_ != Direction::Left) { direction_ = Direction::Right; } else if (event->key() == Qt::Key_Up && direction_ != Direction::Down) { direction_ = Direction::Up; } else if (event->key() == Qt::Key_Down && direction_ != Direction::Up) { direction_ = Direction::Down; } } private slots: void update() { QPoint head = snake_.front(); switch (direction_) { case Direction::Left: head.rx() -= 10; break; case Direction::Right: head.rx() += 10; break; case Direction::Up: head.ry() -= 10; break; case Direction::Down: head.ry() += 10; break; } if (head == food_) { snake_.push_front(head); food_ = generateFood(); } else { snake_.pop_back(); if (std::find(snake_.begin(), snake_.end(), head) != snake_.end() || head.x() < 0 || head.x() > width() || head.y() < 0 || head.y() > height()) { snake_.clear(); snake_.push_back({200, 200}); snake_.push_back({200, 210}); snake_.push_back({200, 220}); food_ = generateFood(); } else { snake_.push_front(head); } } update(); } private: enum class Direction { Left, Right, Up, Down }; QList<QPoint> snake_; QPoint food_; Direction direction_ = Direction::Up; QPoint generateFood() { int x = (qrand() % (width() / 10)) * 10; int y = (qrand() % (height() / 10)) * 10; return {x, y}; } }; ``` 此代码使用Qt绘制了一个400x400像素的窗口,并在其中创建了一个贪吃蛇游戏。运行程序后,玩家可以通过方向键控制蛇的移动,吃到食物后蛇的长度会增加。如果蛇碰到了边界或自己的身体,则游戏会重新开始。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

S+叮当猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值