QT项目-贪吃蛇的实现

本文详细介绍了如何使用QT框架开发一款贪吃蛇游戏,涉及QTimer的使用来控制蛇的移动,按键事件处理游戏控制,以及QSound类在实现游戏背景音乐和特殊效果音效上的应用。游戏包括关卡选择、随机奖品、得分显示和游戏结束条件等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

QT项目-贪吃蛇的实现

程序流程图如下

在这里插入图片描述

项目运行截图

在这里插入图片描述在这里插入图片描述在这里插入图片描述

项目功能介绍

1、界面选择(选择游戏关卡)
2、实现按键事件对游戏控制(如上下左右实现贪吃蛇移动方向,空格实现游戏的暂停和开始,AIt按键实现游戏的退出)
3、运行游戏背影音乐的启动
4、奖品的随机出现
5、吃到奖励的得分显示
6、游戏过关等

贪吃蛇项目的实现

QT的QTimer介绍
简述

QTimer类提供了定时器信号和单触发定时器。

它在内部使用定时器事件来提供更通用的定时器。QTimer很容易使用:创建一个QTimer,使用start()来开始并且把它的timeout()连接到适当的槽。当这段时间过去了,它将会发射timeout()信号。

注意当QTimer的父对象被销毁时,它也会被自动销毁。

成员函数介绍

void start(int msec)
启动或重新启动一个超时时间间隔为毫秒的定时器。

如果定时器正在运行,它将被停止和重新启动。如果singleShot为true,定时器将只激活一次。

void start()
同上,重载了start()。

void stop()
停止定时器。

bool isActive()
如果定时器正在运行,返回true,否则返回false。

int remainingTime()
返回定时器的剩余时间(毫秒为单位),直到超时。

如果定时器不活跃,返回值是-1。如果定时器过期,返回值为0。

void setInterval(int msec)
设置超时间隔(毫秒为单位)。

默认值是0,这时,一旦窗口系统事件队列中的所有事件都已经被处理完,一个时间间隔为0的QTimer就会触发。

void setSingleShot(bool singleShot)
设置定时器是否为单次触发。

单次触发定时器只触发一次,非单次的话,则每过一个时间间隔都会触发。

void setTimerType(Qt::TimerType atype)
设置定时器的准确性。默认值是Qt::CoarseTimer。

int timerId() const
如果定时器正在运行,返回定时器的ID,否则返回-1。

信号

void timeout()
定时器超时后,这个信号被发射。

注意:这是一个私有的信号。它可以在信号连接使用,但不能由用户发出。

QT的QTimer实现了贪吃蛇的移动

start()启动计时器,在一定时间后QTimer发送timeout信号,相应的槽函数timeout()执行,实现贪吃蛇的移动。实现方式采用蛇身头插尾删的方式实现移动效果。在timeout函数中,当蛇吃到一定奖励时,回重新选择关卡难度。

实现代码如下

void Widget::timeout()
{
    int count=1;
    //吃到奖励时
    if(snake[0].intersects(rewardNode))
    {
        count++;
        eat->play();	//吃到奖励时的声音
        addNewReword();	//
    }
    while(count--)
    {
        switch(moveFlag)
        {
        case DIR_UP:
            addTop();	//在头部加一个小方块
            break;
        case DIR_DOWN:
            addDown();	//在尾部添加一个小方块
            break;
        case DIR_RIGHT:
            addRight();  //在右边添加一个小方块
            break;
        case DIR_LEFT:
            addLeft();	//在左边添加一个小方块
            break;
        default:
            break;
        }
    }
    deleteLast();	//在尾部删除一个方块
    update();		//界面刷新
    //当吃到一定奖励之后就过关
    int fshu=snake.length()-3;
    if(fshu==10)	//当吃到一定奖励时,选择下一关卡,即晋级
    {
        timer->stop();
        startsound->stop();
        close();
        guanqiaDialog gd;
        gd.exec();
    }
    label2->setText(QString::number(fshu));	//分数
}
蛇身头插尾删操作

实现代码(列举在头部增加方块的情况)

void Widget::addTop()
{	//在头部添加一个小方块
	//获取方块的左上、右下角像素坐标
    QPointF leftTop;
    QPointF rightBotom;
    if(snake[0].y()-nodeHeight<0)
    {	//蛇头移动到边界的情况
        leftTop=QPointF(snake[0].x(),this->height()-nodeHeight);
        rightBotom=QPointF(snake[0].x()+nodeWidth,this->height());
    }
    else
    {
        leftTop=QPointF(snake[0].x(),snake[0].y()-nodeHeight);
        rightBotom=snake[0].topRight();
    }
    snake.insert(0,QRectF(leftTop,rightBotom));
}

void Widget::deleteLast()
{	//在尾部删除一个小方块
    snake.removeLast();
}

分析图示如下

在这里插入图片描述

按键事件实现贪吃蛇的移动方向

我们重载QWidget类的keyPressEvent()事件实现对贪吃蛇移动方向的改变,代码如下

void Widget::keyPressEvent(QKeyEvent *event)
{
    switch (event->key())
    {
        //向上
        case Qt::Key_Up:
            //先判断是否撞到蛇身
            if(!checkContact())
            {
                if(moveFlag !=DIR_DOWN)
                {
                    moveFlag=DIR_UP;
                }
            }
            break;
            //向下
        case Qt::Key_Down:
            if(!checkContact())
            {
                if(moveFlag!=DIR_UP)
                {
                    moveFlag=DIR_DOWN;
                }
            }
            break;
            //向右
        case Qt::Key_Right:
            if(!checkContact())
            {
                if(moveFlag!=DIR_LEFT)
                {
                    moveFlag=DIR_RIGHT;
                }
            }
            break;
            //向左
        case Qt::Key_Left:
            if(!checkContact())
            {
                if(moveFlag!=DIR_RIGHT)
                {
                    moveFlag=DIR_LEFT;
                }
            }
            break;
            //空格——暂停/开始
        case Qt::Key_Space:
            if(!checkContact())
            {
                if(kaishi==false)
                {
                    if(gameStart==false)
                    {
                        gameStart=true;
                        timer->stop();
                        startsound->stop();
                    }
                    else
                    {
                        gameStart=false;
                        timer->start(time);
                        startsound->play();
                        startsound->setLoops(-1);
                    }
                }
            }
            break;
        case Qt::Key_Alt:
            {//退出
                close();
                startsound->stop();
                guanqiaDialog kd;
                kd.exec();

            }
            break;
        default:
            break;
    }
}

QT的QSound类的介绍

在QT使用Qsound调用之前操作

1、在.pro 文件中加 QT += multimedia,才可以使用Qsound

2、在使用的文件中添加头文件:#include

简介

QSound类提供了对平台音频设备的访问,提供了GUI应用程序中最常用的音频操作:异步播放一个声音文件

主要接口函数介绍

1、使用静态函数play : QSound::play(“…/mySound.wav”);

这时运行程序就可以播放指定的音频文件了,注意这里将音频文件放在了项目目录中。因为现在QSound并不支持资源文件,所以音频文件必须要放在程序外面。

2、先构建QSound对象,然后再调用play()槽进行播放可以使用stop()槽来停止声音的播放,还可以使用setLoops()函数设置播放重复的次数,如果设置为-1表示无限循环。

贪吃蛇背景音乐的实现代码如下

  startsound=new QSound("D:/Qt/Test_Project/snake_2023/res/bgm.wav", this);	//贪吃蛇背景音乐的播放
  eat=new QSound("D:/Qt/Test_Project/snake_2023/res/chi.wav", this);	//贪吃蛇吃到奖励的声音播放
  die=new QSound("D:/Qt/Test_Project/snake_2023/res/die.wav", this);	//贪吃蛇死亡声音的播放
  startsound->play();		//背景音乐播放
  sound->setLoops(-1);//设置循环次数
贪吃蛇死亡情况

当贪吃蛇的头部与身体的某个部位相撞时游戏结束,代码如下

bool Widget::checkContact()
{
    for(int j=0;j<snake.length();j++)
    {
        for(int i=j+1;i<snake.length();i++)
        {
            if(snake[j]==snake[i])
            {
                return true;
            }
        }
    }
    return false;
}

通过返回bool值,判断贪吃蛇的蛇头和蛇身是否是相撞状态。

程序代码链接如下

https://download.youkuaiyun.com/download/weixin_56169816/87988875?spm=1001.2014.3001.5501

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值