项目二源代码

1.snake_3_widget.h

#ifndef SNAKE_3_WIDGET_H
#define SNAKE_3_WIDGET_H

#include <QWidget>
#include<algorithm>
#include<QPainter>
#include<QBrush>
#include<QImage>
#include<QPaintEvent>
#include<QTimer>
#include<conio.h>
#include<QMediaPlaylist>
#include<QMediaPlayer>
#include<queue>
#include<QMessageBox>
#include<snake_mainmenu.h>
#include<his_TYPE.h>
#include<cmath>

QT_BEGIN_NAMESPACE

namespace Ui { class snake_3_Widget; }
QT_END_NAMESPACE



class snake_3_Widget : public QWidget
{
    Q_OBJECT

public:
    snake_3_Widget(QWidget *parent = nullptr,int dif = 1,std::priority_queue<his_type> = {});
    ~snake_3_Widget();

protected:
    void keyPressEvent(QKeyEvent *event);
    void paintEvent(QPaintEvent *event);
    void addTop();
    void addDown();
    void addLeft();
    void addRight();
    void deletelast();
    void addTop_2();
    void addDown_2();
    void addLeft_2();
    void addRight_2();
    void deletelast_2();
    void addbean();
    int  eatBean();//0没吃 1蓝吃 2绿吃
    bool rule();
    int rule_2();
    int dist(QRectF a,QRectF b);  //返回以格子为的单位的距离

protected slots:
    void timeout();        //判定
    void timeout_1();      //蓝色速度
    void timeout_2();      //绿色速度
    void start_timeout();  //游戏开始缓冲2.5秒
    void dif_3_timeout();  //每秒加速
private:
    Ui::snake_3_Widget *ui;
    QTimer *gametime,*game_startf,*game_dif_3,*game_1,*game_2;

    QList<QRectF>snake_loc,snake_loc_2;  //蛇每一节的坐标
    int snake_dire=0;  //蛇头方向:0上 1左 2下 3右
    int snake_dire_2=0;
    int nodeWidth = 100;
    int nodeHeight = 100;
    int snake_time=200,snake_1=200,snake_2=200;  //初始速度0.2秒
    QRectF * bean;
    bool game_start=true;
    bool first_start = false;  //游戏首次开始
    int pix_dl=1,pix_dl_2=1;   //蛇头图片动态图,0、1为左朝向图片,2、3为右朝向图片
    int pix_js=0,pix_js_2=0;  //控制结算图片
    bool dire_buffer,dire_buffer_2;  //方向是否正在缓冲
    int current_score;  //当前分数
    std::priority_queue<his_type> his_score;  //历史记录
    QMediaPlaylist * game_musiclist;
    QMediaPlayer * game_music;
    int difficulty=1;   //难度
    int max_length=7;   //双人模式最长蛇长

};
#endif // SNAKE_3_WIDGET_H

2.snake_mainmenu.h

#ifndef SNAKE_MAINMENU_H
#define SNAKE_MAINMENU_H

#include <QWidget>
#include<QMediaPlaylist>
#include<QMediaPlayer>
#include<QPainter>
#include <snake_3_widget.h>
#include <QSoundEffect>
#include<QString>
#include<queue>
#include<QDateTime>
#include<his_TYPE.h>
#include<QDir>

enum INTERFACE{
    MAIN,
    HISTORY,
    OPTION,
    HELP
};


namespace Ui {
class snake_mainmenu;
}

class snake_mainmenu : public QWidget
{
    Q_OBJECT

public:
    explicit snake_mainmenu(QWidget *parent = nullptr,std::priority_queue<his_type>his_score={});
    ~snake_mainmenu();
protected:
    void paintEvent(QPaintEvent *event);



private slots:

    void on_quit_button_clicked();

    void on_play_button_clicked();

    void on_record_button_clicked();

    void on_help_button_clicked();

    void on_back_button_clicked();

    void on_bgm_button_clicked();

    void on_stopvoice_button_clicked();

    void on_dif_1_button_clicked();




    void on_dif_2_button_clicked();

    void on_dif_3_button_clicked();



    void on_save_button_clicked();

    void on_clear_button_clicked();

    void on_dif_4_button_clicked();

private:
    Ui::snake_mainmenu *ui;
    int current_interface;   //当前界面:主菜单0 纪录1 模式难度2 帮助3
    QMediaPlaylist * menu_musiclist;
    QMediaPlayer * menu_music = new QMediaPlayer;

    QSoundEffect *effect;
    void interface(int);//对应界面
    std::priority_queue<his_type> his;
    int difficulty=1;  //难度
    void ReadtestFile(); //导入历史
    bool h_his;/*用于判断是否可以保存*/
};



#endif // SNAKE_MAINMENU_H

3.his_TYPE.h

#ifndef HIS_TYPE_H
#define HIS_TYPE_H
#include<QTime>

struct his_type  //历史记录结构体存历史记录完成时间和分数
{
    int score;
    int dif;
    QTime Time ;

    //按分数优先级排列
    friend bool operator < (his_type h1,his_type h2)
    {
        return h1.score<h2.score;
    }
};
#endif // HIS_TYPE_H

4.MyButton.h

#ifndef MYBUTTON_H
#define MYBUTTON_H
#include<QPushButton>
#include<QEvent>
#include<AudioThread.h>
#include<queue>

class MyButton :public QPushButton
{
Q_OBJECT;
public:
    MyButton(QWidget *parent = 0);
    ~MyButton();
public:
    void enterEvent(QEvent *e); //鼠标进入事件
    void menu_soundeffect(int sound_index);//生成对应音效

private:

};
#endif // MYBUTTON_H

 5.AudioThread.h

参考文章QSoundEffect独立声音播放线程 movetothread方式_ZLOZL的博客-CSDN博客_qt声音线程

#ifndef DLTHREAD_H
#define DLTHREAD_H

#include <QtCore>
#include <QObject>

#include <QSoundEffect>
#include <QThread>
#include<QTime>
enum VOICE_TYPE{
    VOICE_POSITIVE,
    VOICE_NEGATIVE,
    VOICE_TEMPERATURE,
    VOICE_TOOCLOSE,
    VOICE_GOOCLOSE
};

class AudioThread : public QObject
{
    Q_OBJECT
public:
    AudioThread(QObject *parent = nullptr);
    ~AudioThread();

signals:
    void doPlay();
    void doStop();

public slots:
    void play_strong(int type);
    void play(int type);

private:
    int voice_type;


    QSoundEffect effect;

    QThread thread;

};

#endif // DLTHREAD_H

6.snake_3_widget.cpp

#include "snake_3_widget.h"
#include "ui_snake_3_widget.h"
#include<QDebug>
#include<ctime>
using namespace std;

int cnt_g=0;



snake_3_Widget::snake_3_Widget(QWidget *parent,int dif,priority_queue<his_type> h)
    : QWidget(parent)
    , ui(new Ui::snake_3_Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("");

    gametime = new QTimer;
    game_startf = new QTimer;
    game_startf->start(2500);
    current_score=0;
    connect(gametime,SIGNAL(timeout()),this,SLOT(timeout()));
    connect(game_startf,SIGNAL(timeout()),this,SLOT(start_timeout()));
    setFixedSize(1600,900);

    //传入难度
    /*模式4:双人规则初始两条蛇长为2的蛇AB,
     * AB碰头平局,若A碰到B某一节身体,就将B从该节身体开始全部消除(B碰到自己同理),谁的蛇长先归为0谁就输
     * 初始蛇速都为200,每吃一块石头加一节蛇身,每加一节蛇身速度减20,蛇身最长为7,速度最慢为300
     * 模式5:人机 寻路方式:每次选择相对距离更近的方向走
     *            制定寻路相对距离规则:蛇头改变方向后的坐标到某点的坐标之间的距离乘上该点的权值
     *                               每个点的权值应该随着两蛇的位置和石头发生
    */
    difficulty=dif;
    if(difficulty==3)
    {
        snake_time=120;
        game_dif_3 = new QTimer;
        game_dif_3->start(1000);
        connect(game_dif_3,SIGNAL(timeout()),this,SLOT(dif_3_timeout()));
    }
    //添加背景图片
    if(difficulty<4)
    {
        QImage background = QImage(":/pic/prefix1/picture/bj1.png");
        QBrush *brush = new QBrush(background.scaled(this->size()));
        QPalette pa(this->palette());
        pa.setBrush(QPalette::Window,*brush);
        this->setPalette(pa);
    }
    else
    {
        QImage background = QImage(":/pic/prefix1/picture/bj2.jpg");
        QBrush *brush = new QBrush(background.scaled(this->size()));
        QPalette pa(this->palette());
        pa.setBrush(QPalette::Window,*brush);
        this->setPalette(pa);
    }

    qDebug()<<"60";
    //初始化音乐
    game_musiclist = new QMediaPlaylist;
    game_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_game_inToOppor.wav"));
    game_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_game_oppressive.wav"));
    game_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_game_inTofier.wav"));
    game_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_game_subfierce.wav"));
    game_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_game_fierce.wav"));
    game_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_game_fierce_happy.wav"));
    game_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_game_funny.wav"));
    game_music = new QMediaPlayer;
    game_music->setPlaylist(game_musiclist);
    game_musiclist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
    game_musiclist->setCurrentIndex(cnt_g++);
    game_music ->play();
    qDebug()<<"76";
    //初始化蛇身
    QRectF rect(300,600,nodeWidth,nodeHeight);
    QRectF rect_2(600,400,nodeWidth,nodeHeight);
    snake_loc.append(rect);
    addTop();
    if(difficulty!=4)addTop();
    else{
        snake_time=20;
        game_1 = new QTimer;
        game_2 = new QTimer ;
        connect(game_1,SIGNAL(timeout()),this,SLOT(timeout_1()));
        connect(game_2,SIGNAL(timeout()),this,SLOT(timeout_2()));
        snake_loc_2.append(rect_2);
        addTop_2();
    }

    //初始化豆子
    addbean();

    //设置分数显示
    ui->score_num->setDigitCount(3);
    ui->score_num->setDecMode();
    ui->score_num->setStyleSheet("border: none");
    ui->score_num->setSegmentStyle(QLCDNumber::Flat);
    if(difficulty==4){
        ui->score_num->hide();
    }

    //承接历史记录
    his_score = h;
}

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


void snake_3_Widget::paintEvent(QPaintEvent *)
{

//    qDebug()<<snake_time<<"%%";
    QPixmap pix_yzlz1,pix_yzlz2,pix_yzly1,pix_yzly2,pix_ld,pix_ys,pix_yzlz3,pix_yzly3;
    QPixmap pix_yzlz1_2,pix_yzlz2_2,pix_yzly1_2,pix_yzly2_2,pix_ld_2,pix_yzlz3_2,pix_yzly3_2;
    pix_yzlz1.load(":/pic/prefix1/picture/yzlz1.png");//岩贼龙动作1
    pix_yzlz2.load(":/pic/prefix1/picture/yzlz3.png");//岩贼龙动作2
    pix_yzly1.load(":/pic/prefix1/picture/yzly2.png");//岩贼龙动作3
    pix_yzly2.load(":/pic/prefix1/picture/yzly1.png");//岩贼龙动作4
    pix_yzlz3.load(":/pic/prefix1/picture/yzlz4.png");//岩贼龙动作5
    pix_yzly3.load(":/pic/prefix1/picture/yzly4.png");//岩贼龙动作6
    pix_ld.load(":/pic/prefix1/picture/ld2.png");  //龙蛋
    if(difficulty==4){
        pix_yzlz1_2.load(":/pic/prefix1/picture/yzlz1_2.png");//岩贼龙动作1
        pix_yzlz2_2.load(":/pic/prefix1/picture/yzlz3_2.png");//岩贼龙动作2
        pix_yzly1_2.load(":/pic/prefix1/picture/yzly2_2.png");//岩贼龙动作3
        pix_yzly2_2.load(":/pic/prefix1/picture/yzly1_2.png");//岩贼龙动作4
        pix_yzlz3_2.load(":/pic/prefix1/picture/yzlz4_2.png");//岩贼龙动作5
        pix_yzly3_2.load(":/pic/prefix1/picture/yzly4_2.png");//岩贼龙动作6
        pix_ld_2.load(":/pic/prefix1/picture/ld2_2.png");  //龙蛋
    }
//    pix_bj.load(":/pic/prefix1/picture/bj1.png");  //背景

    pix_ys.load(":/pic/prefix1/picture/ys.png");   //岩石


    QPainter painter(this);  //设置画笔
    painter.setRenderHint(QPainter::Antialiasing,true);   //抗锯齿

//    painter.drawPixmap(0,0,1600,900,pix_bj);  //插入背景图片


    painter.drawPixmap(bean->x(),bean->y(),nodeWidth,nodeHeight,pix_ys);//画岩石
    for(int i=1;i<snake_loc.length();i++)
    {
        painter.drawPixmap(snake_loc[i].x(),snake_loc[i].y(),nodeWidth,nodeHeight,pix_ld);  //画龙蛋
    }
    if(difficulty==4)
    {
        for(int i=1;i<snake_loc_2.length();i++)
        {
            painter.drawPixmap(snake_loc_2[i].x(),snake_loc_2[i].y(),nodeWidth,nodeHeight,pix_ld_2);  //画龙蛋
        }
    }

    if(!pix_js)  //画岩贼龙
    {
        switch ((int)pix_dl) {
        case 0:
            painter.drawPixmap(snake_loc[0].x(),snake_loc[0].y(),nodeWidth,nodeHeight,pix_yzlz2);
            break;
        case 1:
            painter.drawPixmap(snake_loc[0].x(),snake_loc[0].y(),nodeWidth,nodeHeight,pix_yzlz1);
            break;
        case 2:
            painter.drawPixmap(snake_loc[0].x(),snake_loc[0].y(),nodeWidth,nodeHeight,pix_yzly1);
            break;
        case 3:
            painter.drawPixmap(snake_loc[0].x(),snake_loc[0].y(),nodeWidth,nodeHeight,pix_yzly2);
            break;

        }
    }
    else
    {
        if(pix_js==1)painter.drawPixmap(snake_loc[0].x(),snake_loc[0].y(),nodeWidth,nodeHeight,pix_yzlz3);
        if(pix_js==2)painter.drawPixmap(snake_loc[0].x(),snake_loc[0].y(),nodeWidth,nodeHeight,pix_yzly3);
        gametime->stop();
    }
    if(difficulty==4)
    {
        if(!pix_js_2)  //画岩贼龙
        {
            switch ((int)pix_dl_2) {
            case 0:
                painter.drawPixmap(snake_loc_2[0].x(),snake_loc_2[0].y(),nodeWidth,nodeHeight,pix_yzlz2_2);
                break;
            case 1:
                painter.drawPixmap(snake_loc_2[0].x(),snake_loc_2[0].y(),nodeWidth,nodeHeight,pix_yzlz1_2);
                break;
            case 2:
                painter.drawPixmap(snake_loc_2[0].x(),snake_loc_2[0].y(),nodeWidth,nodeHeight,pix_yzly1_2);
                break;
            case 3:
                painter.drawPixmap(snake_loc_2[0].x(),snake_loc_2[0].y(),nodeWidth,nodeHeight,pix_yzly2_2);
                break;

            }
        }
        else
        {
            if(pix_js_2==1)painter.drawPixmap(snake_loc_2[0].x(),snake_loc_2[0].y(),nodeWidth,nodeHeight,pix_yzlz3_2);
            if(pix_js_2==2)painter.drawPixmap(snake_loc_2[0].x(),snake_loc_2[0].y(),nodeWidth,nodeHeight,pix_yzly3_2);
            gametime->stop();
        }
    }


//    painter.setPen(QPen(QColor(0, 160, 230), 2));   //画笔颜色尺寸
//    painter.drawPoint(QPointF(400,400));  //绘制点
//    painter.drawEllipse(QPointF(120, 60), 5, 5);  //绘制椭圆
//    painter.setClipRect(rect.adjusted(20,20,-20,-20));
//    painter.drawLine(rect.topLeft(),rect.bottomRight());   //绘制线


}


void snake_3_Widget::keyPressEvent(QKeyEvent *event)   //键盘事件
{
    switch(event->key())
    {
        case Qt::Key_W:  //W键
            if(!dire_buffer&&snake_dire!=2)
                snake_dire=0,dire_buffer=true;
            break;
        case Qt::Key_A:  //A键
            if(!dire_buffer&&snake_dire!=3)
                snake_dire=1,dire_buffer=true;
            break;
        case Qt::Key_S:  //S键
            if(!dire_buffer&&snake_dire!=0)
                snake_dire=2,dire_buffer=true;
            break;
        case Qt::Key_D:  //D键
            if(!dire_buffer&&snake_dire!=1)
                snake_dire=3,dire_buffer=true;
            break;
        case Qt::Key_Up:  //up键
            if(difficulty==4&&!dire_buffer_2&&snake_dire_2!=2)
                snake_dire_2=0,dire_buffer_2=true;
            break;
        case Qt::Key_Left:  //left键
            if(difficulty==4&&!dire_buffer_2&&snake_dire_2!=3)
                snake_dire_2=1,dire_buffer_2=true;
            break;
        case Qt::Key_Down:  //down键
            if(difficulty==4&&!dire_buffer_2&&snake_dire_2!=0)
                snake_dire_2=2,dire_buffer_2=true;
            break;
        case Qt::Key_Right:  //right键
            if(difficulty==4&&!dire_buffer_2&&snake_dire_2!=1)
                snake_dire_2=3,dire_buffer_2=true;
            break;
//        case Qt::Key_E:  //慢速
//            if(snake_time>=400)break;
//            else snake_time+=50;
//            if(game_start==true)
//                gametime->start(snake_time);
//            break;
//        case Qt::Key_Q:  //加速
//            if(snake_time==20)break;
//            else snake_time-=10;
//            if(game_start==true)
//                gametime->start(snake_time);
//            break;
        case Qt::Key_J:   //切换bgm
            game_musiclist->setCurrentIndex(cnt_g++);
            if(cnt_g==7)cnt_g=0;
//            qDebug()<<game_musiclist->currentIndex()<<"**";
            game_musiclist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
            game_music ->play();
            break;
        case Qt::Key_P:  //暂停
            if(game_music->isMuted())game_music->setMuted(false);
            else game_music->setMuted(true);
            break;
        case Qt::Key_Escape:  //退出
            this->close();
            break;
        case Qt::Key_Space:   //开始/暂停
            if(first_start)
            {
                if(!game_start)
                {
                    game_start=true;
                    if(difficulty==3)game_dif_3->start(1000);
                    gametime->start(snake_time);
                    game_1->start(snake_1);
                    game_2->start(snake_2);
                }
                else
                {
                    game_start=false;
                    gametime->stop();
                    game_1->stop();
                    game_2->stop();
                    if(difficulty==3)game_dif_3->stop();
                }
            }
            break;
    }


}


void snake_3_Widget::dif_3_timeout()
{
    snake_time=max(snake_time-20,20);
    gametime->start(snake_time);
}

void snake_3_Widget::start_timeout()
{
    first_start=true;


    if(difficulty==4)
    {
        game_1->start(snake_1);
        game_2->start(snake_2);
    }
    gametime->start(snake_time);
    game_startf->stop();
}

void snake_3_Widget::timeout_1()
{
    switch (snake_dire)
    {
    case 0:
        addTop();
        if(pix_dl<=1)
        {
            if(pix_dl==1)pix_dl=0;
            else pix_dl=1;
        }
        else
        {
            if(pix_dl==2)pix_dl=3;
            else pix_dl=2;
        }
        break;
    case 1:
        addLeft();
        if(pix_dl==1)pix_dl=0;
        else pix_dl=1;
        break;
    case 2:
        addDown();
        if(pix_dl<=1)
        {
            if(pix_dl==1)pix_dl=0;
            else pix_dl=1;
        }
        else
        {
            if(pix_dl==2)pix_dl=3;
            else pix_dl=2;
        }
        break;
    case 3:
        addRight();
        if(pix_dl==2)pix_dl=3;
        else pix_dl=2;
        break;


    }
    dire_buffer=false;//方向缓冲解除
    if(eatBean()!=1)
    {
        deletelast();
    }

}
void snake_3_Widget::timeout_2()
{
    switch (snake_dire_2)
    {
    case 0:
        addTop_2();
        if(pix_dl_2<=1)
        {
            if(pix_dl_2==1)pix_dl_2=0;
            else pix_dl_2=1;
        }
        else
        {
            if(pix_dl_2==2)pix_dl_2=3;
            else pix_dl_2=2;
        }
        break;
    case 1:
        addLeft_2();
        if(pix_dl_2==1)pix_dl_2=0;
        else pix_dl_2=1;
        break;
    case 2:
        addDown_2();
        if(pix_dl_2<=1)
        {
            if(pix_dl_2==1)pix_dl_2=0;
            else pix_dl_2=1;
        }
        else
        {
            if(pix_dl_2==2)pix_dl_2=3;
            else pix_dl_2=2;
        }
        break;
    case 3:
        addRight_2();
        if(pix_dl_2==2)pix_dl_2=3;
        else pix_dl_2=2;
        break;


    }

    dire_buffer_2=false;//方向缓冲解除
    if(eatBean()!=2)
    {
        deletelast_2();
    }

}


void snake_3_Widget::timeout()
{ 

    if(difficulty<4)
    {
        if(!rule())
        {
            gametime->stop();
            if(difficulty==3)game_dif_3->stop();
            if(pix_dl<=1)pix_js=1;
            else pix_js=2;
            update();
            QTime Time = QTime::currentTime();
            his_score.push({current_score,difficulty,Time});
            QString df = "你的得分是:"+QString::number(current_score);
            QMessageBox::information(this,"游戏结束!",df);
            this->close();
            game_music->stop();
            snake_mainmenu *m = new snake_mainmenu(nullptr,his_score);
            m->show();
        }
        else
        {
            switch (snake_dire)
            {
                case 0:
                addTop();
                if(pix_dl<=1)
                {
                    if(pix_dl==1)pix_dl=0;
                    else pix_dl=1;
                }
                else
                {
                    if(pix_dl==2)pix_dl=3;
                    else pix_dl=2;
                }
                break;
            case 1:
                addLeft();
                if(pix_dl==1)pix_dl=0;
                else pix_dl=1;
                break;
            case 2:
                addDown();
                if(pix_dl<=1)
                {
                    if(pix_dl==1)pix_dl=0;
                    else pix_dl=1;
                }
                else
                {
                    if(pix_dl==2)pix_dl=3;
                    else pix_dl=2;
                }
                break;
            case 3:
                addRight();
                if(pix_dl==2)pix_dl=3;
                else pix_dl=2;
                break;


            }
            dire_buffer=false;//方向缓冲解除
        }
        if(eatBean())
        {
            delete bean;
            current_score++;
            ui->score_num->display(current_score);
            addbean();

        }
        else
        {
            deletelast();
        }

        update();
    }



    //判定双人规则
    else
    {
//        qDebug()<<"绿色分数"<<current_score_2;
        int r=rule_2();
        if(r)
        {
            gametime->stop();
            game_1->stop();
            game_2->stop();
            switch (r) {
            case 1:
                if(pix_dl_2<=1)pix_js_2=1;
                else pix_js_2=2;
                update();
                QMessageBox::information(this,"游戏结束!","蓝色胜利!");
                break;
            case 2:
                if(pix_dl<=1)pix_js=1;
                else pix_js=2;
                update();
                QMessageBox::information(this,"游戏结束!","绿色胜利!");
                break;
            case 3:
                QMessageBox::information(this,"游戏结束!","平局!");
                break;
            }

            QTime Time = QTime::currentTime();
            his_score.push({r,difficulty,Time});
            this->close();
            game_music->stop();
            snake_mainmenu *m = new snake_mainmenu(nullptr,his_score);
            m->show();
        }
       else
        {
            switch (eatBean()) {
            case 0:

                break;
            case 1:
                if(snake_loc.size()<=max_length)
                {
                    delete bean;
                    addbean();
                    snake_1=min(snake_1+20,300);
                    game_1->start(snake_1);
                }
                break;
            case 2:
                if(snake_loc_2.size()<=max_length)
                {
                    delete bean;
                    addbean();
                    snake_2=min(snake_2+20,300);
                    game_2->start(snake_2);
                }

                break;

            }

            //蓝色被吃
            for(int i=1;i<snake_loc.size();i++)
            {
                if(snake_loc_2[0]==snake_loc[i]||snake_loc[0]==snake_loc[i])
                {
                    while(snake_loc.size()>i)deletelast();
                    snake_1=200+(snake_loc.size()-2)*20;
                    game_1->start(snake_1);
                }
            }

            //绿色被吃
            for(int i=1;i<snake_loc_2.size();i++)
            {
                if(snake_loc[0]==snake_loc_2[i]||snake_loc_2[0]==snake_loc_2[i])
                {
                    while(snake_loc_2.size()>i)deletelast_2();
                    snake_2=200+(snake_loc_2.size()-2)*20;
                    game_2->start(snake_2);
                }
            }
            update();
        }


    }



}



void snake_3_Widget::addTop()
{
    QPointF leftTop;  //蛇头左上角坐标
    QPointF rightBotom; //蛇头右下角坐标
    if(snake_loc[0].y() - nodeHeight<0)  //出界处理
    {
        leftTop = QPointF(snake_loc[0].x(),this->height()-nodeHeight);
        rightBotom = QPointF(snake_loc[0].x()+nodeWidth,this->height());
    }
    else
    {
        leftTop = QPointF(snake_loc[0].x(),snake_loc[0].y()-nodeHeight);
        rightBotom = snake_loc[0].topRight();
    }

    snake_loc.insert(0,QRectF(leftTop,rightBotom));
}
void snake_3_Widget::addDown()
{
    QPointF leftTop;  //蛇头左上角坐标
    QPointF rightBotom; //蛇头右下角坐标
    if(snake_loc[0].y() + nodeHeight>=this->height())  //出界处理
    {
        leftTop = QPointF(snake_loc[0].x(),0);
        rightBotom = QPointF(snake_loc[0].x()+nodeWidth,nodeHeight);
    }
    else
    {
        rightBotom = QPointF(snake_loc[0].x()+nodeWidth,snake_loc[0].y()+2*nodeHeight);
        leftTop = snake_loc[0].bottomLeft();
    }

    snake_loc.insert(0,QRectF(leftTop,rightBotom));
}
void snake_3_Widget::addLeft()
{
    QPointF leftTop;  //蛇头左上角坐标
    QPointF rightBotom; //蛇头右下角坐标
    if(snake_loc[0].x() - nodeHeight<0)  //出界处理
    {
        leftTop = QPointF(this->width()-nodeWidth,snake_loc[0].y());
        rightBotom = QPointF(this->width(),snake_loc[0].y()+nodeHeight);
    }
    else
    {
        leftTop = QPointF(snake_loc[0].x()-nodeWidth,snake_loc[0].y());
        rightBotom = snake_loc[0].bottomLeft();
    }

    snake_loc.insert(0,QRectF(leftTop,rightBotom));
}
void snake_3_Widget::addRight()
{
    QPointF leftTop;  //蛇头左上角坐标
    QPointF rightBotom; //蛇头右下角坐标
    if(snake_loc[0].x() + nodeHeight>=this->width())  //出界处理
    {
        leftTop = QPointF(0,snake_loc[0].y());
        rightBotom = QPointF(nodeWidth,snake_loc[0].y()+nodeWidth);
    }
    else
    {
        rightBotom = QPointF(snake_loc[0].x()+2*nodeWidth,snake_loc[0].y()+nodeHeight);
        leftTop = snake_loc[0].topRight();
    }

    snake_loc.insert(0,QRectF(leftTop,rightBotom));
}

inline void snake_3_Widget::deletelast()
{
    snake_loc.removeLast();
}

void snake_3_Widget::addTop_2()
{
    QPointF leftTop;  //蛇头左上角坐标
    QPointF rightBotom; //蛇头右下角坐标
    if(snake_loc_2[0].y() - nodeHeight<0)  //出界处理
    {
        leftTop = QPointF(snake_loc_2[0].x(),this->height()-nodeHeight);
        rightBotom = QPointF(snake_loc_2[0].x()+nodeWidth,this->height());
    }
    else
    {
        leftTop = QPointF(snake_loc_2[0].x(),snake_loc_2[0].y()-nodeHeight);
        rightBotom = snake_loc_2[0].topRight();
    }

    snake_loc_2.insert(0,QRectF(leftTop,rightBotom));
}
void snake_3_Widget::addDown_2()
{
    QPointF leftTop;  //蛇头左上角坐标
    QPointF rightBotom; //蛇头右下角坐标
    if(snake_loc_2[0].y() + nodeHeight>=this->height())  //出界处理
    {
        leftTop = QPointF(snake_loc_2[0].x(),0);
        rightBotom = QPointF(snake_loc_2[0].x()+nodeWidth,nodeHeight);
    }
    else
    {
        rightBotom = QPointF(snake_loc_2[0].x()+nodeWidth,snake_loc_2[0].y()+2*nodeHeight);
        leftTop = snake_loc_2[0].bottomLeft();
    }

    snake_loc_2.insert(0,QRectF(leftTop,rightBotom));
}
void snake_3_Widget::addLeft_2()
{
    QPointF leftTop;  //蛇头左上角坐标
    QPointF rightBotom; //蛇头右下角坐标
    if(snake_loc_2[0].x() - nodeHeight<0)  //出界处理
    {
        leftTop = QPointF(this->width()-nodeWidth,snake_loc_2[0].y());
        rightBotom = QPointF(this->width(),snake_loc_2[0].y()+nodeHeight);
    }
    else
    {
        leftTop = QPointF(snake_loc_2[0].x()-nodeWidth,snake_loc_2[0].y());
        rightBotom = snake_loc_2[0].bottomLeft();
    }

    snake_loc_2.insert(0,QRectF(leftTop,rightBotom));
}
void snake_3_Widget::addRight_2()
{
    QPointF leftTop;  //蛇头左上角坐标
    QPointF rightBotom; //蛇头右下角坐标
    if(snake_loc_2[0].x() + nodeHeight>=this->width())  //出界处理
    {
        leftTop = QPointF(0,snake_loc_2[0].y());
        rightBotom = QPointF(nodeWidth,snake_loc_2[0].y()+nodeWidth);
    }
    else
    {
        rightBotom = QPointF(snake_loc_2[0].x()+2*nodeWidth,snake_loc_2[0].y()+nodeHeight);
        leftTop = snake_loc_2[0].topRight();
    }

    snake_loc_2.insert(0,QRectF(leftTop,rightBotom));
}

inline void snake_3_Widget::deletelast_2()
{
    snake_loc_2.removeLast();
}


void snake_3_Widget::addbean()
{
    bean = new QRectF;
    bool bean_valid;  //是否非法
    srand(time(NULL));
    do{
        bean_valid=false;
        * bean=QRectF(rand()%(this->width()/100)*100,
                    rand()%(this->height()/100)*100,
                    nodeWidth,
                    nodeHeight
                    );
        for(auto temp:snake_loc)
            if(temp==*bean)
            {
                bean_valid=true;
                break;
            }
        if(difficulty==4&&!bean_valid)
        {
            for(auto temp:snake_loc_2)
                if(temp==*bean)
                {
                    bean_valid=true;
                    break;
                }
        }
    }while(bean_valid);
}

int snake_3_Widget::eatBean()
{
    if(snake_loc[0]==* bean)
    {

        switch (difficulty) {
        case 2:
            snake_time=max(snake_time-20,50);
            gametime->start(snake_time);
            break;
        case 3:
            snake_time=max(snake_time+20,120);
            gametime->start(snake_time);
            break;
        case 4:

            break;
        }
        return 1;
    }
    else if(difficulty==4&&snake_loc_2[0]==* bean)
    {

        return 2;
    }
    else return 0;
}


bool snake_3_Widget::rule()
{
    for(int i=1;i<snake_loc.length();i++)
        if(snake_loc[0]==snake_loc[i])
        {
            return false;
        }
    return true;
}

int snake_3_Widget::rule_2()  //1蓝赢 2绿赢 3平局 否则平局
{
    if(snake_loc.size()==1||snake_loc_2.size()>max_length)return 2;  //绿赢
    if(snake_loc_2.size()==1||snake_loc.size()>max_length)return 1;
    if(snake_loc[0]==snake_loc_2[0])return 3;
    return 0;
}

int snake_3_Widget::dist(QRectF a,QRectF b)
{
    return std::abs(a.x()-b.x())/nodeWidth+std::abs(a.y()-b.y())/nodeHeight;
}

7.snake_mainmenu.cpp

#include "snake_mainmenu.h"
#include "ui_snake_mainmenu.h"
#include<MyButton.h>


int cnt=0;   //播放列表位置
snake_mainmenu::snake_mainmenu(QWidget *parent,std::priority_queue<his_type> h) :
    QWidget(parent),
    ui(new Ui::snake_mainmenu)
{
    ui->setupUi(this);
    setFixedSize(750,700);
    this->setWindowTitle("贪吃蛇之怪物猎人");
    ui->his_record_edit->setReadOnly(true);
    ui->help_edit->setReadOnly(true);

    //设置主界面
    current_interface=0;
    interface(current_interface);

    //导入历史记录

    if(h.empty())ReadtestFile(),h_his=false;   //没有纪录(首次打开游戏)
    else his = h,h_his=true;                    //存在历史纪录

    //导入音乐
    menu_musiclist = new QMediaPlaylist;
    menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_other_fierce.wav"));
    menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_other_grand.wav"));
    menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_other_kAndR.wav"));
    menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_other_kind.wav"));
    menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_other_kind2.wav"));
    menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_menu_start.wav"));
    menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_other_relieve.wav"));
    menu_musiclist->addMedia(QUrl("qrc:/voi/wavbgm/bgm_otherORgame_inter.wav"));
    menu_music->setPlaylist(menu_musiclist);

    menu_musiclist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
    menu_musiclist->setCurrentIndex(cnt++);

    menu_music->play();
    update();

}

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



void snake_mainmenu::interface(int t)
{
    switch (t) {
    case MAIN:
        ui->menu_frame->show();
        ui->logo_main->show();
        ui->back_button->hide();
        ui->model_frame->hide();
        ui->his_record_edit->hide();
        ui->help_edit->hide();
        ui->save_button->hide();
        ui->clear_button->hide();
        break;
    case HISTORY:
        ui->his_record_edit->show();
        ui->save_button->show();
        ui->logo_main->hide();
        ui->menu_frame->hide();
        ui->model_frame->hide();
        ui->back_button->show();
        ui->help_edit->hide();
        ui->clear_button->show();
        break;
    case OPTION:
        ui->model_frame->show();
        ui->back_button->show();
        ui->menu_frame->hide();
        ui->his_record_edit->hide();
        ui->logo_main->hide();
        ui->help_edit->hide();
        ui->save_button->hide();
        ui->clear_button->hide();
        break;
    case HELP:
        ui->model_frame->hide();
        ui->back_button->show();
        ui->menu_frame->hide();
        ui->his_record_edit->hide();
        ui->logo_main->hide();
        ui->help_edit->show();
        ui->save_button->hide();
        ui->clear_button->hide();
        break;

    }
}




void snake_mainmenu::on_quit_button_clicked()
{
    this->close();
}

void snake_mainmenu::paintEvent(QPaintEvent *)
{
    QPainter menu_painter(this);
    QPixmap menu_main,menu_help,menu_model,menu_record;
    menu_main.load(":/pic/prefix1/picture/mjl.jpg");
    menu_model.load(":/pic/prefix1/picture/sl.jpg");
    menu_help.load(":/pic/prefix1/picture/hl.jpg");
    menu_record.load(":/pic/prefix1/picture/mhw.jpg");
    menu_painter.setRenderHint(QPainter::Antialiasing,true);   //抗锯齿
    switch(current_interface){
    case MAIN:
        menu_painter.drawPixmap(0,0,750,700,menu_main);
        break;
    case HISTORY:
        menu_painter.drawPixmap(0,0,750,700,menu_record);
        break;
    case OPTION:
        menu_painter.drawPixmap(0,0,750,700,menu_model);
        break;
    case HELP:
        menu_painter.drawPixmap(0,0,750,700,menu_help);
        break;
    }
}

void snake_mainmenu::on_play_button_clicked()
{
    ui->play_button->menu_soundeffect(0);
    current_interface=2;
    interface(current_interface);
    update();
}

void snake_mainmenu::on_record_button_clicked()
{
    ui->record_button->menu_soundeffect(0);
    current_interface=1;
    interface(current_interface);
    ui->his_record_edit->setText("历史最高纪录");
    auto temp = his;
    for(unsigned i=0;i<his.size();i++)
    {
        if(temp.top().dif<4)
        {
            QString diff;
            switch (temp.top().dif) {
            case 1:
                diff="简单";
                break;
            case 2:
                diff="普通";
                break;
            case 3:
                diff="困难";
                break;

            }

            ui->his_record_edit->append(temp.top().Time.toString()+"时在"+diff+"模式下得分"+QString::number(temp.top().score));
        }
        else
        {
            QString winner;
            switch (temp.top().score) {
            case 1:
                winner = "蓝色胜出";
                break;
            case 2:
                winner = "绿色胜出";
                break;
            case 3:
                winner = "平局";
                break;
            }
            ui->his_record_edit->append(temp.top().Time.toString()+"时在双人模式下"+winner);
        }
        temp.pop();
    }
//    qDebug()<<"历史记录长度"<<his.size();
    update();
}

void snake_mainmenu::on_help_button_clicked()
{
    ui->help_button->menu_soundeffect(0);
    current_interface=3;
    interface(current_interface);
    update();
}

void snake_mainmenu::on_back_button_clicked()
{
    ui->back_button->menu_soundeffect(2);
    switch(current_interface){
    case 0:
        break;
    case 1:
        current_interface=0;
        interface(current_interface);

        break;
    case 2:
        current_interface=0;
        interface(current_interface);
        break;
    case 3:
        current_interface=0;
        interface(current_interface);
        break;
    }
    update();
}

void snake_mainmenu::on_bgm_button_clicked()
{
    if(!menu_music->isMuted())
    {
        ui->bgm_button->menu_soundeffect(2);
        menu_musiclist->setCurrentIndex(cnt++);
        if(cnt==8)cnt=0;
        qDebug()<<menu_musiclist->currentIndex();
        menu_musiclist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
        menu_music->play();
    }
}

void snake_mainmenu::on_stopvoice_button_clicked()
{
    ui->stopvoice_button->menu_soundeffect(2);
    if(menu_music->isMuted())
    {
        menu_music->setMuted(false);
        ui->stopvoice_button->setStyleSheet("qproperty-icon: url(:/pic/prefix1/picture/voice.png);"
                                            "background:transparent;");
    }
    else
    {
        menu_music->setMuted(true);
        ui->stopvoice_button->setStyleSheet("qproperty-icon: url(:/pic/prefix1/picture/stopvoice.png);"
                                            "background:transparent;");
    }
}

void snake_mainmenu::on_dif_1_button_clicked()
{
    ui->dif_1_button->menu_soundeffect(1);
    difficulty=1;
    menu_music->stop();
    this ->close();
    snake_3_Widget * game = new snake_3_Widget(nullptr,difficulty,his);
    game->show();
}

void snake_mainmenu::on_dif_2_button_clicked()
{
    ui->dif_2_button->menu_soundeffect(1);
    difficulty=2;
    menu_music->stop();
    this ->close();
    snake_3_Widget * game = new snake_3_Widget(nullptr,difficulty,his);
    game->show();
}

void snake_mainmenu::on_dif_3_button_clicked()
{
    ui->dif_3_button->menu_soundeffect(1);
    difficulty=3;
    menu_music->stop();
    this ->close();
    snake_3_Widget * game = new snake_3_Widget(nullptr,difficulty,his);
    game->show();
}





void snake_mainmenu::on_save_button_clicked()
{
    ui->save_button->menu_soundeffect(4);
    if(his.empty())
    {
        QMessageBox::information(this,"纪录","没有纪录!");
    }
    else if(h_his)
    {
        //保存为TXT文件
        bool exist;
        QString fileName;

        QDir *folder = new QDir;
        exist = folder->exists("D:/QT/QT_project/snake_3/his_record");//查看目录是否存在

        if(!exist){//不存在就创建
            bool ok = folder->mkdir("D:/QT/QT_project/snake_3/his_record");
            if(ok){
                qDebug()<<"创建成功!";//添加提示方便查看是否成功创建
            }else{
                QMessageBox::information(this,"纪录","保存失败");
            }
        }
        fileName = tr("D:/QT/QT_project/snake_3/his_record/%1.txt").arg("data");

        QFile f(fileName);
        if(!f.open(QIODevice::ReadWrite | QIODevice::Append | QIODevice::Text))
        {//追加写入 添加结束符\r\n
            QMessageBox::information(this,"纪录","保存失败");
            return ;
        }
        else
        {
            QTextStream out(&f);
            auto temp = his;

            for(unsigned i=0;i<his.size();i++)
            {
                out<<temp.top().Time.toString()<<endl<<temp.top().score<<endl<<temp.top().dif<<endl<<QObject::tr("go on")<<endl;
                temp.pop();
            }
            QMessageBox::information(this,"纪录","已保存");
        }
        f.close();
    }


}


void snake_mainmenu::ReadtestFile()
{

    QFile file("D:/QT/QT_project/snake_3/his_record/data.txt");    //文件路径   也可以用相对路径
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qDebug()<<"Can't open the file!"<<endl;
        return;
    }
    QTextStream in(&file);  //文件流
    QString line =in.readLine();   //读取一行
    his_type cur_h;
    int index=1;
    while (!line.isNull())
    {
        if(index==4)
        {
            index=0;
            his.push(cur_h);
        }
        else
        {
            switch (index) {
            case 1:
                cur_h.Time= QTime::fromString(line, "hh:mm:ss");
                break;
            case 2:
                cur_h.score=line.toInt();
                break;
            case 3:
                cur_h.dif=line.toInt();
                break;

            }
        }
        line = in.readLine();
        index++;
    }
//    qDebug()<<his.top().Time;

}


void snake_mainmenu::on_clear_button_clicked()
{
    ui->clear_button->menu_soundeffect(4);
    if(!his.empty())
    {
        QMessageBox::StandardButton result=QMessageBox::question(this,"清除纪录","确定要清除当前纪录吗?");
        if(result)
            while (!his.empty()) his.pop();
        ui->his_record_edit->setText("历史最高纪录");
    }
    else
    {
        QMessageBox::StandardButton result=QMessageBox::question(this,"清除历史纪录","确定要清除历史纪录吗?");
        if(result)
        {
            QFile file("D:/QT/QT_project/snake_3/his_record/data.txt");
            file.open(QFile::WriteOnly|QFile::Truncate);
            file.close();
            QMessageBox::information(this,"清除历史纪录","历史纪录已清除!");
        }
    }
}

void snake_mainmenu::on_dif_4_button_clicked()
{
    ui->dif_4_button->menu_soundeffect(1);
    difficulty=4;
    menu_music->stop();
    this ->close();
    snake_3_Widget * game = new snake_3_Widget(nullptr,difficulty,his);
    game->show();
}

8.MyButton.cpp

#include"MyButton.h"
#include<snake_mainmenu.h>

MyButton::MyButton(QWidget* parent) :QPushButton(parent)
{

}
MyButton::~MyButton()
{

}

void MyButton::enterEvent(QEvent *)
{
    AudioThread * e = new AudioThread;
//    e->setSource(QUrl::fromLocalFile("D:/QT/QT_project/snake_3/voice_1.0/menu/wavmenu/menu_mousechoosing.wav"));
    e->play(3);
}
void MyButton::menu_soundeffect(int sound_index)//生成对应音效
{
    AudioThread * e = new AudioThread;
//    e->setSource(QUrl::fromLocalFile("D:/QT/QT_project/snake_3/voice_1.0/menu/wavmenu/"+sound_index));
    e->play(sound_index);
}
//void MyButton::mousePressEvent(QMouseEvent *ev)
//{
//    //代表鼠标左键按下
//    if(ev->button()==Qt::LeftButton&&!effect->isPlaying())
//    {
//        effect->setSource(QUrl::fromLocalFile("D:/QT/QT_project/snake_3/voice_1.0/menu/wavmenu/menu_chosed.wav"));
//        effect->setLoopCount(1);  //循环次数
//        effect->setVolume(0.95f); //音量  0~1之间
//        effect->play();
//    }
//}

9.AudioThread.cpp

参考文章QSoundEffect独立声音播放线程 movetothread方式_ZLOZL的博客-CSDN博客_qt声音线程

#include <AudioThread.h>
#include <QUrl>

AudioThread::AudioThread(QObject *parent) :
    QObject(parent)
{
    effect.moveToThread(&thread);
    connect(this, SIGNAL(doPlay()), &effect, SLOT(play()));
    connect(this, &AudioThread::doStop, &effect, &QSoundEffect::stop);
    thread.start();
}

AudioThread::~AudioThread()
{
    if(thread.isRunning())
    {
        thread.terminate();
    }
}

void AudioThread::play_strong(int type)
{

    if(effect.isPlaying())
    {
        emit this->doStop();
        effect.stop();
    }

    voice_type = type;
    QString fileName;
    switch (voice_type)
    {
    case VOICE_POSITIVE:
    {
        fileName = "menu_model_chosed.wav";
    }
        break;
    case VOICE_NEGATIVE:
    {
        fileName = "menu_gamestart.wav";
    }
        break;
    case VOICE_TEMPERATURE:
    {
        fileName = "menu_chosed.wav";
    }
        break;
    case VOICE_TOOCLOSE:
    {
        fileName = "menu_mousechoosing.wav";
    }
        break;
    default:
    {
        return;
    }
    }

    effect.setSource(QUrl("qrc:/voi/wavmenu/"+fileName));
    effect.setLoopCount(1);
    effect.setVolume(1.0f);

    emit this->doPlay();
}

void AudioThread::play(int type)
{
    if(effect.isPlaying())
    {
        return;
    }

    voice_type = type;
    QString fileName;
    switch (voice_type)
    {
    case VOICE_POSITIVE:
    {
        fileName = "menu_model_chosed.wav";
    }
        break;
    case VOICE_NEGATIVE:
    {
        fileName = "menu_gamestart.wav";
    }
        break;
    case VOICE_TEMPERATURE:
    {
        fileName = "menu_chosed.wav";
    }
        break;
    case VOICE_TOOCLOSE:
    {
        fileName = "menu_mousechoosing.wav";
    }
        break;
    case VOICE_GOOCLOSE:
    {
        fileName = "menu_choose.wav";
    }
        break;
    default:
    {
        return;
    }
    }

    effect.setSource(QUrl("qrc:/voi/wavmenu/"+fileName));
    effect.setLoopCount(1);
    effect.setVolume(1.0f);
    emit this->doPlay();
}

main.cpp和.qrc和.ui文件略

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值