QT-贪吃蛇

  • 贪吃蛇(gluttonous snake)
    基本要求:
    完成贪吃蛇游戏,使得游戏具有可玩性,对用户友好的交互性。通过配色与背景的搭配,以及音效的结合,形成游戏的完整要素,体现QT学习的阶段性结果。
    玩法介绍:
    点击开始进入游戏界面。最初的模式很简单,随着你吃的食物量的增加,它会逐渐变成困难模式,然后继续魔鬼模式。区别在于不同的模式,食物刷新的频率和蛇的速度是不同的,在游戏进行到一半时,如果你想停止,请按空格键,如果你想继续游戏,再按空格键继续。当游戏失败时,按enter键继续游戏。游戏显示你在游戏中的最高分。
    Click start to enter the game interface. The initial mode is simple, and as the amount of food you eat increases, it will gradually become difficult mode, and then continue to the devil mode.The difference lies in different modes, the frequency of food refresh and the speed of the snake are different, in the middle of the game, if you want to stop, please press the space bar, if you want to continue the game again press the space bar to continue.When the game fails, press enter to continue the game.The game shows you the highest score in the game.
  • 代码:
#include "form.h"
#include "ui_form.h"
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QDebug>
#include <QTimer>
#include <QTime>
#include <QtMultimedia/QSound>

Form::Form(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Form)
{
    time=100;//初始简单模式
    ui->setupUi(this);
    gameStart = true;
    QString dir=QCoreApplication ::applicationDirPath();
    QString filename(dir+"/bgm.wav");//整个游戏过程中穿插的bgm
    QSound *sound1 = new QSound(filename, this);
    sound1->play();
    sound1->setLoops(10000);
    resize(1000,700);
    snake.append(QRectF(200,500,snakeNodeWidth,snakeNodeHeight));
    addTopRectF();
    addTopRectF();
    //首先生成一个奖励节点
    rewardNode.append(QRectF(100,100,snakeNodeWidth,snakeNodeWidth));

    timer = new QTimer;
    connect(timer, SIGNAL(timeout()),this,SLOT(timeOut()));
    timer->start(time);

    rewardTimer = new QTimer;
    connect(rewardTimer,SIGNAL(timeout()),this,SLOT(rewardTimeOut()));
    rewardTimer->start(time*30);

}

Form::~Form()
{
    delete ui;
}
void Form::timeOut()
{
    int flage = 1;
    for(int i=0; i<rewardNode.length(); i++){
        if(rewardNode.at(i).contains(snake.at(0).topLeft()+QPointF(snakeNodeWidth/2,snakeNodeHeight/2))){
            if(rewardNode.at(i).width()>snakeNodeWidth){//额外奖励
                flage += 2;
            }
            flage++;//正常奖励
            rewardNode.removeAt(i);
            sound(0);//播放吃东西的音效
            break;
        }
    }
    while(flage--){
        switch (moveFlage) {
        case Up:
            addTopRectF();
            break;
        case Down:
            addDownRectF();
            break;
        case Right:
            addRightRectF();
            break;
        case Left:
            addLeftRectF();
            break;
        default:
            break;
        }
    }
    deleteLastRectF();//删除最后一个方块
    update();
}
//随机奖励
void Form::rewardTimeOut()
{
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
    if(rewardNode.length() > 5){
        rewardNode.removeAt(qrand()%5);
    }
    rewardNode.append(QRectF(qrand()%(this->width()/20)*20,qrand()%(this->height()/20)*20,snakeNodeWidth,snakeNodeWidth));
    if(qrand()%5 == 3){
        rewardNode.append(QRectF(qrand()%(this->width()/20)*20-5,qrand()%(this->height()/20)*20-5,snakeNodeWidth*2,snakeNodeWidth*2));
    }
}

//向上移动
void Form::addTopRectF()
{
    if(snake.at(0).y()-snakeNodeHeight < 0){
        snake.insert(0,QRectF(QPointF(snake.at(0).x(),this->height()-snakeNodeHeight),
                              QPointF(snake.at(0).x()+snakeNodeWidth,this->height())));
    }else{
        snake.insert(0,QRectF(snake.at(0).topLeft()+QPointF(0,-snakeNodeHeight),snake.at(0).topRight()));
    }
}
//向下移动
void Form::addDownRectF()
{
    if(snake.at(0).y()+snakeNodeHeight*2 > this->height()){
        snake.insert(0,QRectF(QPointF(snake.at(0).x(),snakeNodeHeight),
                              QPointF(snake.at(0).x()+snakeNodeWidth,0)));
    }else{
        snake.insert(0,QRectF(snake.at(0).bottomLeft(),snake.at(0).bottomRight()+QPointF(0,snakeNodeHeight)));
    }
}
//向左移动
void Form::addLeftRectF()
{
    if(snake.at(0).x()-snakeNodeWidth < 0){
        snake.insert(0,QRectF(QPointF(this->width()-snakeNodeWidth,snake.at(0).y()),
                              QPointF(this->width(),snake.at(0).y()+snakeNodeHeight)));
    }else{
        snake.insert(0,QRectF(snake.at(0).topLeft()+QPointF(-snakeNodeWidth,0),snake.at(0).bottomLeft()));
    }
}
//向右移动
void Form::addRightRectF()
{
    if(snake.at(0).x()+snakeNodeWidth*2 > this->width()){
        snake.insert(0,QRectF(QPointF(0,snake.at(0).y()),
                              QPointF(snakeNodeWidth,snake.at(0).y()+snakeNodeHeight)));
    }else{
        snake.insert(0,QRectF(snake.at(0).topRight(),snake.at(0).bottomRight()+QPointF(snakeNodeWidth,0)));
    }
}
//删除结尾数据
void Form::deleteLastRectF()
{
    snake.removeLast();
}
//绘图
void Form::paintEvent(QPaintEvent *event)
{
    //this->hide();
    qDebug("画图");
    QPainter painter(this);
    QString dir=QCoreApplication ::applicationDirPath();
    QString filename(dir+"/bg.jpg");
    painter.drawPixmap(rect(),QPixmap(filename));//背景图片
    QPen pen;
    QBrush brush;
    QFont font("华文琥珀",13,QFont::ExtraLight,false);
    QFont font1("华文彩云",13,QFont::ExtraLight,false);
    //painter.drawRect(20,20,160,160);
    //反锯齿
    painter.setRenderHint(QPainter::Antialiasing);

    pen.setColor(Qt::white);
    brush.setStyle(Qt::SolidPattern);
    painter.setPen(pen);
    painter.setBrush(brush);
    for(int i=0; i<snake.length(); i++){
        if(i==0)
        {
            brush.setColor(Qt::cyan);
            painter.setBrush(brush);
            painter.drawRect(snake.at(i));//画蛇头
        }
        else {
            brush.setColor(Qt::gray);
            painter.setBrush(brush);
            painter.drawRect(snake.at(i));//画蛇身
        }
    }
    for(int i=0; i<rewardNode.length(); i++){
        int flag=i%5;//生成彩色的食物
        switch (flag) {
        case 0:pen.setColor(Qt::green);brush.setColor(Qt::green);break;
        case 1:pen.setColor(Qt::red);brush.setColor(Qt::red);break;
        case 2:pen.setColor(Qt::yellow);brush.setColor(Qt::yellow);break;
        case 3:pen.setColor(Qt::white);brush.setColor(Qt::white);break;
        case 4:pen.setColor(Qt::black);brush.setColor(Qt::black);break;
        }
        painter.setPen(pen);
        painter.setBrush(brush);
        painter.drawEllipse(rewardNode.at(i));
    }
    pen.setColor(Qt::white);
    painter.setPen(pen);
    painter.setFont(font);
    if(snake.length()>=20&&snake.length()<40)
    {
        painter.drawText(20,35,QString(tr("模式:Hard Model")));
        if(time!=50)
        {
            time=50;//困难模式
            timer->stop();
            rewardTimer->stop();
            gameStart = true;
            timer->start(time);
            rewardTimer->start(time*30);
            gameStart = false;
        }
        if(snake.length()==20)
        {
            painter.setFont(font1);
            painter.drawText((this->width()-300)/2,(this->height()-30)/2,QString(tr("           进入困难模式")));
            painter.setFont(font);
        }
    }
    else if(snake.length()>=40){
        painter.drawText(20,35,QString(tr("模式:Devil Model")));
        if(time!=25)
        {
            time=25;//魔鬼模式
            timer->stop();
            rewardTimer->stop();
            gameStart = true;
            timer->start(time);
            rewardTimer->start(time*30);
            gameStart = false;
        }
        if(snake.length()==40)
        {
            painter.setFont(font1);
            painter.drawText((this->width()-300)/2,(this->height()-30)/2,QString(tr("           进入魔鬼模式")));
            painter.setFont(font);
        }
    }
    else {
        painter.drawText(20,35,QString(tr("模式:Simple Model")));
        if(snake.length()==3)
        {
            painter.setFont(font1);
            painter.drawText((this->width()-300)/2,(this->height()-30)/2,QString(tr("           进入容易模式")));
            painter.setFont(font);
        }
    }
    painter.drawText((this->width()-300)/2,35,QString(tr("             当前得分:"))+QString("%1").arg(snake.length()-3));
    if(snake.length()-3>best)
    {
        best=snake.length()-3;
    }
    painter.drawText((this->width()-300),35,QString(tr("                 Best Score:"))+QString("%1").arg(best));

    if(snakeStrike()){
        QFont font(tr("Showcard Gothic"),33,QFont::ExtraLight,false);
        painter.setFont(font);
        painter.drawText((this->width()-300)/2-10,(this->height()-30)/2,QString("GAME OVER!"));
        QFont font1(tr("华文行楷"),15,QFont::ExtraLight,false);
        painter.setFont(font1);
        painter.drawText((this->width()-300)/2,(this->height()-30)/2+50,QString("      按回车键继续游戏"));
        timer->stop();
        rewardTimer->stop();
        gameOver = true;
    }

    QWidget::paintEvent(event);
}
void Form::keyPressEvent(QKeyEvent *event)
{
    switch(event->key()){
    case Qt::Key_Up:
        if(moveFlage != Down){
            moveFlage = Up;
        }
        break;
    case Qt::Key_Down:
        if(moveFlage != Up){
            moveFlage = Down;
        }
        break;
    case Qt::Key_Right:
        if(moveFlage != Left){
            moveFlage = Right;
        }
        break;
    case Qt::Key_Left:
        if(moveFlage != Right){
            moveFlage = Left;
        }
        break;
    case Qt::Key_Enter:
    case Qt::Key_Return:
        if(gameOver){
            time=100;//恢复简单模式
            snake.clear();
            rewardNode.clear();
            moveFlage = Up;
            snake.append(QRectF(200,500,snakeNodeWidth,snakeNodeHeight));
            addTopRectF();
            addTopRectF();
            //首先生成一个奖励节点
            rewardNode.append(QRectF(100,100,snakeNodeWidth,snakeNodeWidth));
            timer->start(time);
            rewardTimer->start(time*30);
            gameOver = false;
        }
        break;
    case Qt::Key_Space:
        if(gameStart && !gameOver){
            timer->start(time);
            rewardTimer->start(time*30);
            gameStart = false;
        }else if(!gameStart && !gameOver){
            timer->stop();
            rewardTimer->stop();
            gameStart = true;
        }
        break;
    default:
        break;
    }
}
//相撞判定
bool Form::snakeStrike()
{
    for(int i=0; i<snake.length(); i++){
        for(int j=i+1; j<snake.length(); j++){
            if(snake.at(i) == snake.at(j)){
                sound(1);//播放游戏失败音效
                return true;
            }
        }
    }
    return false;

}
void  Form::sound(int type)//播放音效的函数
{
    QString dir=QCoreApplication ::applicationDirPath();
    if(type==0)//吃东西的音效
    {
        QString filename(dir+"/eat.wav");
        QSound::play ( filename );
    }
    else if(type==1)//失败的音效
    {
        QString filename(dir+"/over.wav");
        QSound::play ( filename );
    }
}
  • 截图:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一个简单的贪吃蛇的实现思路和部分代码。 首先,您需要使用 Qt 框架创建一个新的 C++ 项目。然后,您需要创建一个 Snake 类来表示贪吃蛇的状态和行为。这个类应该包含以下属性: - 当前蛇的长度 - 当前蛇的位置 - 当前蛇的方向 - 当前蛇的速度 - 当前蛇的身体部分 贪吃蛇的主要行为包括: - 移动:根据当前方向和速度移动蛇的位置 - 改变方向:根据用户输入改变蛇的方向 - 吃食物:如果蛇的头部碰到了食物,就将其加入到蛇的身体中,并增加蛇的长度 - 碰撞检测:检测蛇是否与边界或自己的身体碰撞,如果是,则游戏结束 下面是一个简单的 Snake 类的实现: ```cpp class Snake { public: Snake(int x, int y, int length, int speed){ // 初始化蛇的位置、长度和速度 } void move(){ // 根据当前方向和速度移动蛇的位置 } void changeDirection(Direction direction){ // 根据用户输入改变蛇的方向 } void eatFood(Food food){ // 如果蛇的头部碰到了食物,就将其加入到蛇的身体中,并增加蛇的长度 } bool isGameOver(){ // 检测蛇是否与边界或自己的身体碰撞,如果是,则游戏结束 } private: int m_x; int m_y; int m_length; int m_speed; Direction m_direction; QList<QPoint> m_body; }; ``` 在主窗口中,您需要创建一个 QTimer 对象来定期更新游戏状态。在每次定时器超时时,您需要更新蛇的位置、检测是否吃到了食物、检测是否游戏结束等。您还需要在窗口中绘制蛇和食物的位置。下面是一个简单的 MainWindow 类的实现: ```cpp class MainWindow : public QMainWindow { public: MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) { // 设置窗口大小、标题等 // 创建游戏场景和蛇对象 // 创建定时器,设置定时器超时信号的槽函数 } private slots: void updateGame(){ // 更新蛇的位置、检测是否吃到了食物、检测是否游戏结束等 // 绘制蛇和食物的位置 } private: QGraphicsScene *m_scene; Snake *m_snake; QTimer *m_timer; }; ``` 这只是一个简单的贪吃蛇的实现思路,您可以根据需要进行修改和扩展。希望对您有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值