【Hexler】Qt5 贪吃蛇

前段时间做了做了一个图形化的贪吃蛇 自认为完成度比较高了 发出来纪念一下 (●’◡’●)
挖个坑,后期我可能还会做网络版,做个服务器然后多客户端进行比赛之类的,到时候的代码就不会发在csdn了,我会把代码打包,链接放在我的哔哩哔哩。

2021921更新 我的哔哩哔哩介绍项目视频 https://www.bilibili.com/video/BV1a64y1h7Am/

先上图哈
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个程序写的时间不是很长,用到的东西基本上也就是qt那些类自带的方法,全都是拿来把你,哈哈哈。
讲一下我的程序的一些思路吧。
1.首先,蛇的身体是用的qlist容器去存的,这里有个小坑就是qlist和标准的stl不一样,插入不是我们平时用pushback之类的,是append。
2.然后就是定时器的使用,需要固定刷新页面,游戏游玩又要加上按键事件,如果这里代码写的不够严谨,游戏就做不下去。
3.整个程序我有个问题是一直卡的我死死的,就是随机数种子这一块。我生成食物还有障碍物都需要用到随机数,并且随机数不能与我地图现有的item产生重叠,这会有一个很大的问题。
处理重叠我一开始的想法就是,遍历所有的item,如果产生重叠,就删除掉刚生成的,再调用生成。
然后Qdebug输出了应该有几百上千次之后才生成新的随机数,一直是生成重叠。。。。。。我一度怀疑是qt的随机数种子有问题,又换了c的也是一样。
最后发现是随机数的原理,我们在调用qsrand或者srand之后,你需要给一个种子嘛,我们一般是放的是当前时间,问题就在这里,程序执行太快,我们传入的是秒数,就是说在那一秒内,生成的随机数都是一样的,必须卡顿小于等于一秒钟的时间才能生成新的,最后在传入的currentDateTime().time()方法后面加上msec(),传入毫秒,虽然也会有大概十多次重叠,但是1ms的延迟基本上可以忽略了。
4.游戏整体逻辑真的很好理解我就不打字,我都带了非常非常详细的注释,有人用到了可以支持一下,如果不懂可以评论,我或许会在我的B站上出一期讲解视频。


贴代码时间到,分享不易还请多支持。


common.h

#ifndef COMMON_H
#define COMMON_H
#include <QObject>
#include <QMainWindow>
#include <QGraphicsItem>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QMessageBox>
#include <QApplication>
#include <QTimer>
#include <QPixmap>
#include <QPainter>
#include <QList>
#include <QAction>
#include <QMenuBar>
#include <QLabel>
#include <QHBoxLayout>
#include <QMenu>
#include <QSound>
#include <QSettings>
//#include <QDebug>
#include <QInputDialog>
#include <QStatusBar>
#include "greedysnake.h"
#define Display_Width 800
#define Display_Height 480
#define GRID_SIZE 20
#define MOVE_KEEP 0
#define MOVE_LEFT 1
#define MOVE_RIGHT 2
#define MOVE_UP 3
#define MOVE_DOWN 4
#define DRAW_RED 0
#endif // COMMON_H

aboutlayout.h

#ifndef OTHERLAYOUT_H
#define OTHERLAYOUT_H
#include <QObject>
#include <QMainWindow>
#include <QDialog>
#include <QListWidget>
#include <QTextEdit>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QTime>
#include <QLabel>
#include <QDebug>
class aboutLayout : public QDialog
{
    Q_OBJECT
public:
    explicit aboutLayout(QWidget *parent = 0);
};
#endif // OTHERLAYOUT_H

aboutlayout.cpp

#include "aboutlayout.h"
aboutLayout::aboutLayout(QWidget *parent) : QDialog(parent)
{
    this->setWindowTitle("关于游戏");
    this->setWindowIcon(QIcon("://1.png"));
    this->setWindowFlags(Qt::WindowCloseButtonHint);
    this->setFixedSize(380,200);
    QLabel *head=new QLabel;
    head->setPixmap(QPixmap("://1.png"));
    QLabel *text1=new QLabel("贪吃蛇1.7");
    QLabel *text2=new QLabel("Author:Hexler");
    QLabel *text3=new QLabel("Acknowledge:");
    QLabel *text4=new QLabel("Qt Creator 4.11.0");
    QLabel *text5=new QLabel("Qt_5_9_9_MinGW_32bit");
    QLabel *test6=new QLabel();
    test6->setOpenExternalLinks(true);
    test6->setText("<a style='color:red;' href=\"https://weibo.com/hexler\">作者weibo:@Hexler");
    QHBoxLayout *hlayout = new QHBoxLayout;
    hlayout->addWidget(head);
    QVBoxLayout *vlayout = new QVBoxLayout;
    vlayout->addStretch(0);
    vlayout->addWidget(text1);
    vlayout->addWidget(text2);
    vlayout->addWidget(text3);
    vlayout->addWidget(text4);
    vlayout->addWidget(text5);
    vlayout->addWidget(test6);
    vlayout->addStretch(0);
    QHBoxLayout *mainlayout = new QHBoxLayout(this);
    mainlayout->addLayout(hlayout);
    mainlayout->addLayout(vlayout);
    qDebug()<<"test 已执行关于游戏构造函数";
}

greedysnake.h

#ifndef GREEDYSNAKE_H
#define GREEDYSNAKE_H
#include "common.h"
#include "aboutlayout.h"
#include "herolist.h"
class GreedySnake : public QMainWindow
{
    Q_OBJECT
public:
    GreedySnake(QWidget *parent = nullptr);
    ~GreedySnake();
    QAction *easy_action;
    QAction *just_action;
    QAction *difficulty_action;
    QAction *smallM_map_action;
    QAction *medium_map_action;
    QAction *big_map_action;
    QAction *heros_action;
    QAction *music_on;
    QAction *music_off;
    QAction *about_help;
    QAction *about_game;
    void create_action();//主窗口的菜单栏的布局
    QSound *move_sound;
    QSound *eta_sound;
    QSound *fail_sound;
    QLabel *map_show;
    QLabel *mode_show;
    QLabel *music_show;
    QLabel *score_show;
    int sound_col;//记录音乐开关状态
    int timer_value;//记录定时器的定时数值
    QSettings *settings;
    void saveSettings();//将程序数据保存
    void loadSettings();//加载程序数据
    void drawBody(int x, int y,int mode=1);//画身体有关的函数
    void drawObstacle();//添加障碍物
    void drawFood();//添加食物
    void moveBody(int flag);//移动身体处理函数
    void clearMap();//清除地图
public slots:
    void handle();//定时器处理刷新函数
    void slot_hero_list();//展示游戏排行榜
    void slot_game_help();//打开游戏帮助消息框
    void slot_game_about();//游戏关于信息
    void slot_stageGroup(QAction *opt);//菜单按钮处理函数
    void slot_mapGroup(QAction *opt);
    void slot_stageMusic(QAction *opt);
private:
    void gameViewSize();//准备游戏画面
    void initGame();//准备游戏开始的初始化
    void game_over();//游戏结束
    void keyPressEvent(QKeyEvent *event);//获取输入并执行相应操作
    void closeEvent(QCloseEvent *e);//关闭事件
    QGraphicsEllipseItem *food;//食物指针
    QGraphicsScene *map;
    QGraphicsView *view;
    HeroList *hero_list;//排行榜类指针
    QTimer *timer;//定时器指针
    int display_W,display_H;//当前游戏窗口的大小数据
    int x,y,Dir_flag,Body_len,alive;//初始化的一些数据
    QList<QGraphicsItem *> sBody_list;//保存蛇身的容器
    QList<QGraphicsItem *> obstacle_list;//保存障碍物的容器
};
#endif // GREEDYSNAKE_H

greedysnake.cpp

#include "greedysnake.h"

GreedySnake::GreedySnake(QWidget *parent) : QMainWindow(parent),map(new QGraphicsScene(this)),view(new QGraphicsView(map,this))
{
    this->setWindowIcon(QIcon("://1.png"));
    this->setWindowTitle(tr("贪吃蛇"));
    this->setWindowFlags(Qt::WindowCloseButtonHint);
    move_sound = new QSound("://sound/click.wav",this);
    eta_sound = new QSound("://sound/question.wav",this);
    fail_sound = new QSound("://sound/youfail.wav",this);//用了声音之后 程序每次退出会返回 QCoreApplication::postEvent: Unexpected null receiver
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(handle()));
    settings = new QSettings("settingsGui.ini",QSettings::IniFormat,this);
    hero_list=new HeroList;
    this->loadSettings();   //加载应用程序数据
    create_action();
    gameViewSize();
    timer->start(timer_value);//设置定时器
}
GreedySnake::~GreedySnake()
{
}
void GreedySnake::create_action()
{
    easy_action = new QAction(tr("简单"),this);
    easy_action->setCheckable(true);
    just_action = new QAction(tr("普通"),this);
    just_action->setCheckable(true);
    difficulty_action = new QAction(tr("困难"),this);
    difficulty_action->setCheckable(true);
    if(timer_value==200){easy_action->setChecked(true);}
    else if(timer_value==150){just_action->setChecked(true);}
    else{difficulty_action->setChecked(true);}
    smallM_map_action = new QAction(tr("小地图"),this);
    smallM_map_action->setCheckable(true);
    medium_map_action = new QAction(tr("中地图"),this);
    medium_map_action->setCheckable(true);
    big_map_action = new QAction(tr("大地图"),this);
    big_map_action->setCheckable(true);
    if(display_W==400){smallM_map_action->setChecked(true);}
    else if(display_W==600){medium_map_action->setChecked(true);}
    else{big_map_action->setChecked(true);}
    heros_action=new QAction(tr("排行榜"),this);
    music_on = new QAction(tr("音乐/开"),this);
    music_on->setCheckable(true);
    music_off = new QAction(tr("音乐/关"),this);
    music_off->setCheckable(true);
    if(sound_col){music_on->setChecked(true);}
    else{music_off->setChecked(true);}
    about_help = new QAction(tr("游戏帮助"),this);
    about_game = new QAction(tr("关于游戏"),this);
    QActionGroup *stageGroup = new QActionGroup(this);
    stageGroup->addAction(easy_action);
    stageGroup->addAction(just_action);
    stageGroup->addAction(difficulty_action);
    QActionGroup *mapGroup = new QActionGroup(this);
    mapGroup->addAction(smallM_map_action);
    mapGroup->addAction(medium_map_action);
    mapGroup->addAction(big_map_action);
    QActionGroup *musicGroup = new QActionGroup(this);
    musicGroup->addAction(music_off);
    musicGroup->addAction(music_on);
    QMenuBar *mbr = this->menuBar();
    QMenu *game_menu = mbr->addMenu(tr("菜 单"));
    QMenu *about_menu = mbr->addMenu(tr("帮 助"));
    game_menu->addAction(easy_action);
    game_menu->addAction(just_action);
    game_menu->addAction(difficulty_action);
    game_menu->addSeparator();
    game_menu->addAction(heros_action);
    game_menu->addSeparator();
    game_menu->addAction(smallM_map_action);
    game_menu->addAction(medium_map_action);
    game_menu->addAction(big_map_action);
    game_menu->addSeparator();
    game_menu->addAction(music_on);
    game_menu->addAction(music_off);
    about_menu->addAction(about_help);
    about_menu->addAction(about_game);
    QStatusBar *statusBar = this->statusBar();
    QString mapstat="  地图:";
    if(display_W==400) mapstat+="小地图 ";
    else if(display_W==600) mapstat+="中地图 ";
    else if(display_W==800) mapstat+="大地图 ";
    QString modestat="   难度:";
    if(timer_value==100) modestat+="困难 ";
    else if(timer_value==150) modestat+="普通 ";
    else if(timer_value==200) modestat+="简单 ";
    QString musicstat="   音乐:";
    if(sound_col==0){musicstat+="关 ";}
    else{musicstat+="开 ";}
    map_show=new QLabel(mapstat);
    mode_show=new QLabel(modestat);
    music_show=new QLabel(musicstat);
    score_show=new QLabel("\t得分:0");
    statusBar->addWidget(map_show);
    statusBar->addWidget(mode_show);
    statusBar->addWidget(music_show);
    statusBar->addPermanentWidget(score_show);
    this->connect(stageGroup,SIGNAL(triggered(QAction *)),this,SLOT(slot_stageGroup(QAction *)));//菜单栏 信号槽 处理
    this->connect(mapGroup,SIGNAL(triggered(QAction *)),this,SLOT(slot_mapGroup(QAction *)));
    this->connect(musicGroup,SIGNAL(triggered(QAction *)),this,SLOT(slot_stageMusic(QAction *)));
    this->connect(about_help,SIGNAL(triggered(bool)),this,SLOT(slot_game_help()));
    this->connect(about_game,SIGNAL(triggered(bool)),this,SLOT(slot_game_about()));
    this->connect(heros_action,SIGNAL(triggered(bool)),this,SLOT(slot_hero_list()));
}
void GreedySnake::saveSettings()
{
    settings->beginGroup("posSize");
    settings->setValue("pos",this->frameGeometry().topLeft());
    settings->setValue("x",display_W);
    settings->setValue("y",display_H);
    settings->endGroup();
    settings->beginGroup("playlevel");
    settings->setValue("timer_value",timer_value);
    settings->endGroup();
    settings->beginGroup("Music");
    settings->setValue("sound_col",sound_col);
    settings->endGroup();
}
void GreedySnake::loadSettings()
{
    settings->beginGroup("posSize");
    QPoint pos = settings->value("pos",QPoint(600,300)).toPoint();
    display_W=settings->value("x",600).toInt();
    display_H=settings->value("y",300).toInt();
    settings->endGroup();
    this->move(pos);
    this->resize(QSize(display_W,display_H));
    settings->beginGroup("playlevel");
    timer_value=settings->value("timer_value",200).toInt();
    settings->endGroup();
    settings->beginGroup("Music");
    sound_col=settings->value("sound_col",0).toInt();
    settings->endGroup();
}
void GreedySnake::drawBody(int x, int y,int mode)
{
    QGraphicsRectItem  *pItem = new QGraphicsRectItem();
    sBody_list.append(pItem);//将新建的item添加到容器当中
    QPen pen = pItem->pen();
    pen.setWidth(0);
    pen.setColor(Qt::white);
    pItem->setPen(pen);
    if(mode==DRAW_RED)
    {pItem->setBrush(QBrush(Qt::red));}
    else{pItem->setBrush(QBrush(Qt::green));}
    pItem->setRect(QRectF((x-1)*20+GRID_SIZE+1,(y-1)*20+GRID_SIZE+1,GRID_SIZE-2,GRID_SIZE-2 ));
    map->addItem(pItem);
}
void GreedySnake::drawObstacle()
{
    qsrand(QDateTime::currentDateTime().time().msec()+17);
    QList<QGraphicsItem *>::Iterator it;//迭代器用来遍历容器
    QGraphicsRectItem *pItem = new QGraphicsRectItem();
    obstacle_list.append(pItem);
    QPen pen = pItem->pen();
    pen.setWidth(0);
    pen.setColor(Qt::white);
    pItem->setPen(pen);
    pItem->setBrush(QBrush(Qt::black));
    int x=qrand()%(display_W/20-2)+1;//随机数字 生成
    int y=qrand()%(display_H/20-2)+1;
    pItem->setRect(QRectF((x-1)*20+GRID_SIZE+1,(y-1)*20+GRID_SIZE+1,GRID_SIZE-2,GRID_SIZE-2 ));
    map->addItem(pItem);
    for(it = sBody_list.begin(); it != sBody_list.end(); it++)//开始判断是否重叠
    {
        if(pItem->collidesWithItem(*it,Qt::IntersectsItemShape))
        {
            map->removeItem(pItem);//把障碍从场景当中移去
            delete  pItem;
            obstacle_list.removeLast();
            pItem=NULL;
            drawObstacle();
            break;
        }
    }
    if(pItem!=NULL)
    {
        if(pItem->collidesWithItem(food,Qt::IntersectsItemShape))
        {
            map->removeItem(pItem);//把障碍从场景当中移去
            delete  pItem;
            pItem=NULL;
            obstacle_list.removeLast();
            drawObstacle();
        }
    }
}
void GreedySnake::drawFood()
{
    qsrand(QDateTime::currentDateTime().time().msec());
    QList<QGraphicsItem *>::Iterator it;//迭代器用来遍历容器
    QGraphicsEllipseItem *pItem = new QGraphicsEllipseItem ();
    food=pItem;
    QPen pen = pItem->pen();
    pen.setWidth(0);
    pen.setColor(Qt::white);
    pItem->setPen(pen);
    pItem->setBrush(QBrush(Qt::blue));
    int x=qrand()%(display_W/20-2)+1;//随机数字 生成
    int y=qrand()%(display_H/20-2)+1;
    pItem->setRect(QRectF((x-1)*20+GRID_SIZE+1,(y-1)*20+GRID_SIZE+1,GRID_SIZE-2,GRID_SIZE-2 ));
    map->addItem(pItem);
    for(it = sBody_list.begin(); it != sBody_list.end(); it++)
    {
        if(food->collidesWithItem(*it,Qt::IntersectsItemShape))
        {
            map->removeItem(food);//把食物从场景当中移去
            delete  food;
            food=NULL;
            drawFood();
            break;
        }
    }
    for(it = obstacle_list.begin(); it != obstacle_list.end(); it++)
    {
        if(food->collidesWithItem(*it,Qt::IntersectsItemShape))
        {
            map->removeItem(food);//把食物从场景当中移去
            delete  food;
            food=NULL;
            drawFood();
            break;
        }
    }
}
void GreedySnake::moveBody(int flag)
{
    Dir_flag=flag;
    QGraphicsItem *temp;
    QList<QGraphicsItem *>::Iterator it;//迭代器用来遍历容器
    switch(flag)
    {
    case MOVE_KEEP: break;
    case MOVE_UP: --y; break;
    case MOVE_DOWN: ++y; break;
    case MOVE_LEFT: --x; break;
    case MOVE_RIGHT: ++x; break;
    }
    if(x<1||x>display_W/20-2||y<1||y>display_H/20-2)//之前是先绘制再判断 为了视图居中 先判断再绘图
    {
        alive=0;
        timer->stop();
        if(x<1) x=1;
        if(x>display_W/20-2) x=display_W/20-2;
        if(y<1) y=1;
        if(y>display_H/20-2) y=display_H/20-2;
        drawBody(x,y,DRAW_RED);
        if(sound_col){fail_sound->play();}
        game_over();
        return;
    }
    if(flag)
    {
        if(sound_col){ move_sound->play();}
        drawBody(x,y);//绘制身体
    }
    if(flag!=MOVE_KEEP && alive==1)
    {
        if((*(it= sBody_list.end()-1))->collidesWithItem(food,Qt::IntersectsItemShape))//这是 是否 吃到食物的判断
        {
            Body_len++;//蛇的身体加一
            score_show->setText("\t得分:"+QString::number(Body_len));
            if(sound_col){eta_sound->play();}
            map->removeItem(food);//把食物从场景当中移去
            delete  food;
            food=NULL;
            drawFood();
            if(Body_len%3==0) drawObstacle();//每获得三分 随机生成一块障碍物
        }
        else//没有吃到就删除蛇尾
        {
            it = sBody_list.begin();
            map->removeItem(*it);//场景当中移去
            temp=*it;
            delete temp;//删除掉item
            sBody_list.removeFirst();//从容器当中删除掉item
        }
    }
    for(it = sBody_list.begin(); it != sBody_list.end()-1; it++)//检测撞到自身死亡
    {
        if((*(sBody_list.end()-1))->collidesWithItem(*it,Qt::IntersectsItemShape))
        {
            alive=0;
            if(sound_col){fail_sound->play();}
            drawBody(x,y,DRAW_RED);
            timer->stop();
            game_over();
            break;
        }
    }
    for(it = obstacle_list.begin(); it != obstacle_list.end(); it++)//检测撞到障碍物死亡
    {
        if((*(sBody_list.end()-1))->collidesWithItem(*it,Qt::IntersectsItemShape))
        {
            alive=0;
            if(sound_col){fail_sound->play();}
            drawBody(x,y,DRAW_RED);
            timer->stop();
            game_over();
            break;
        }
    }
    view->show();
}
void GreedySnake::clearMap()//每次开始新的一句游戏之前 必要做的清理
{
    QList<QGraphicsItem *>::Iterator it;
    QList<QGraphicsItem *> item_list = map->items();
    QGraphicsItem *item = NULL;
    for(it = item_list.begin(); it != item_list.end(); it++)
    {
        item = *it;
        map->removeItem(*it);
        delete item;
    }
    for(it = sBody_list.begin(); it != sBody_list.end(); it++)
    {
        sBody_list.removeFirst();
    }
    for(it = obstacle_list.begin(); it != obstacle_list.end(); it++)
    {
        obstacle_list.removeFirst();
    }
}
void GreedySnake::gameViewSize()
{
    score_show->setText("\t得分:0");
    this->setFixedSize(display_W,display_H+40);//这个是固定窗口大小的
    map->clear();
    delete map;
    map=new QGraphicsScene(this);
    view->setScene(map);
    resize(display_W,display_H+40);
    setCentralWidget(view);
    QPen pen;//定义画笔,设置画笔颜色和宽度
    pen.setColor((Qt::black));
    pen.setWidth(1);
    for(int i=0;i<display_H/20-1;i++)
    {
        map->addLine(20,20*i+20,display_W-20,i*20+20,pen);
    }
    for(int j=0;j<display_W/20-1;j++)
    {
        map->addLine(20*j+20,20,20*j+20,display_H-20,pen);
    }
    initGame();
}
void GreedySnake::handle()
{
    this->setFocus();//锁定不了就每次都设置
    moveBody(Dir_flag);
}
void GreedySnake::game_over()
{
    int mode;
    if(timer_value==100){mode=0;}
    if(timer_value==150){mode=1;}
    if(timer_value==200){mode=2;}
    if(hero_list->readheros(Body_len,mode))
    {
        bool ok;
        QString name = QInputDialog::getText(this, tr("恭喜!"),tr("达到新纪录 请留下大名:"), QLineEdit::Normal,"你的名字",&ok,Qt::MSWindowsFixedSizeDialogHint);
        hero_list->saveheros(display_W,name,Body_len,mode);
        clearMap();
        timer->stop();
        gameViewSize();//保存用户信息之后 开始下一次游戏
        timer->start();
    }
    else
    {
        if(QMessageBox::question(this,tr("游戏结束"),tr("你的分数为:")+QString::number(Body_len)+tr("分 再来一把?"),QMessageBox::Yes,QMessageBox::No )==QMessageBox::Yes)
        {
            clearMap();
            timer->stop();
            gameViewSize();
            timer->start();
        }
        else
        {/*点击否的话 可能代表不想玩了 询问是否退出程序*/}
    }
}
void GreedySnake::slot_hero_list()
{
    HeroList w;
    w.exec();
}
void GreedySnake::slot_stageGroup(QAction *opt)
{
    if(alive)
    {
        if(opt==easy_action)
        {timer->start(timer_value=200);mode_show->setText("   难度:简单 ");}
        else if(opt==just_action)
        {timer->start(timer_value=150);mode_show->setText("   难度:普通 ");}
        else
        {timer->start(timer_value=100);mode_show->setText("   难度:困难 ");}
    }
    else
    {
        clearMap();
        if(opt==easy_action)
        {timer->start(timer_value=200);mode_show->setText("   难度:简单 ");}
        else if(opt==just_action)
        {timer->start(timer_value=150);mode_show->setText("   难度:普通 ");}
        else
        {timer->start(timer_value=100);mode_show->setText("   难度:困难 ");}
        gameViewSize();//重新开始游戏
    }
}
void GreedySnake::slot_mapGroup(QAction *opt)
{
    clearMap();
    timer->stop();
    if(opt==smallM_map_action)
    {display_W=400,display_H=240;map_show->setText("  地图:小地图 ");}
    else if(opt==medium_map_action)
    {display_W=600,display_H=300;map_show->setText("  地图:中地图 ");}
    else if(opt==big_map_action)
    {display_W=800,display_H=480;map_show->setText("  地图:大地图 ");}
    gameViewSize();
    timer->start();
}
void GreedySnake::slot_stageMusic(QAction *opt)
{
    if(opt==music_on){sound_col=1;music_show->setText("   音乐:开 ");}
    else if(opt==music_off){sound_col=0;music_show->setText("   音乐:关 ");}
}
void GreedySnake::slot_game_help()
{
    QMessageBox::information(this,tr("游戏帮助"),tr("1.键盘方向键控制蛇进行移动\n2.左上角菜单进行游戏设定\n3.长按空格可以加速\n4.每得三分就会随机出现一个障碍物\n"),QMessageBox::Ok);
}
void GreedySnake::slot_game_about()
{
    aboutLayout w;
    w.exec();
}

void GreedySnake::initGame()
{
    QPixmap bg(GRID_SIZE,GRID_SIZE);
    QPainter p(&bg);
    p.setBrush(QBrush(Qt::gray));
    p.drawRect(0,0,GRID_SIZE,GRID_SIZE);
    p.setPen(Qt::blue);
    x=7,y=5;
    Dir_flag=0;//默认方向为0 不动
    Body_len=0;//长度为4 分数为0
    alive=1;//活着
    drawBody(5,5);
    drawBody(6,5);
    drawBody(7,5);
    drawFood();
    view->show();//视图更新
}
void sleep(unsigned int msec)
{
    QTime dieTime = QTime::currentTime().addMSecs(msec);
    while( QTime::currentTime() < dieTime )
    {QCoreApplication::processEvents(QEventLoop::AllEvents, 100);}
}
void GreedySnake::keyPressEvent(QKeyEvent *event)
{
    if(event->key()==Qt::Key_Escape)//根据按键执行相应的函数
    {
        this->close();//结束游戏 后期给一个暂停窗口
    }
    if(event->key()==Qt::Key_Space)
    {
        if(alive)
        {
            moveBody(Dir_flag);
            sleep(100);
        }
    }
    if(event->key()==Qt::Key_Up){Dir_flag=MOVE_UP;}
    if(event->key()==Qt::Key_Down){Dir_flag=MOVE_DOWN;}
    if(event->key()==Qt::Key_Left){Dir_flag=MOVE_LEFT;}
    if(event->key()==Qt::Key_Right){Dir_flag=MOVE_RIGHT;}
    if(event->key()==Qt::Key_0){moveBody(MOVE_RIGHT);}
    view->show();
}
void GreedySnake::closeEvent(QCloseEvent *e)//按下关闭按钮之后 触发关闭事件
{
    timer->stop();//关闭事件 可以 直接关闭定时器
    if(QMessageBox::question(this,tr("退出"),tr("确定要退出游戏吗?"),QMessageBox::Yes,QMessageBox::No )==QMessageBox::Yes)
    {
        this->saveSettings();
        e->accept();//不会将事件传递给组件的父组件
    }
    else if(alive)//如果玩家还没有死的话 需要重新启动定时器
    {
        e->ignore();
        timer->start();
    }
    else//点击否 忽略掉
    {
        e->ignore();
    }
}

herolist.h

#ifndef HEROLIST_H
#define HEROLIST_H
#include <QWidget>
#include <QSettings>
#include <QDebug>
#include <QLabel>
#include <QIcon>
#include <QDialog>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QString>
#include <QString>
class HeroList : public QDialog
{
    Q_OBJECT
public:
    explicit HeroList(QWidget *parent = nullptr);
    QString easy_name1;
    int easy_score1;
    QString easy_mode1;
    QString easy_name2;
    int easy_score2;
    QString easy_mode2;
    QString easy_name3;
    int easy_score3;
    QString easy_mode3;
    QString medium_name1;
    int medium_score1;
    QString medium_mode1;
    QString medium_name2;
    int medium_score2;
    QString medium_mode2;
    QString medium_name3;
    int medium_score3;
    QString medium_mode3;
    QString diff_name1;
    int diff_score1;
    QString diff_mode1;
    QString diff_name2;
    int diff_score2;
    QString diff_mode2;
    QString diff_name3;
    int diff_score3;
    QString diff_mode3;
    QSettings *heros;
    int readheros(int score,int mode);    //将读取程序数据进行判断
    void saveheros(int display_W,QString name,int score,int mode);//保存排行榜信息
    void loadheros();    //从文件读取排行榜信息
};
#endif // HEROLIST_H

herolist.cpp

#include "herolist.h"

HeroList::HeroList(QWidget *parent) : QDialog(parent)
{
    this->setWindowTitle("玩家排行榜:");
    this->setWindowIcon(QIcon("://1.png"));
    this->setWindowFlags(Qt::WindowCloseButtonHint);
    this->setFixedSize(600,300);
    QLabel *head=new QLabel;
    head->setPixmap(QPixmap("://1.png"));
    this->loadheros();//从文件读取用户排行信息
    QLabel *text1=new QLabel("难度:简单");
    QLabel *text2=new QLabel("用户名:"+easy_name1+"\t得分:"+QString::number(easy_score1)+"\t地图:"+easy_mode1);
    QLabel *text3=new QLabel("用户名:"+easy_name2+"\t得分:"+QString::number(easy_score2)+"\t地图:"+easy_mode2);
    QLabel *text4=new QLabel("用户名:"+easy_name3+"\t得分:"+QString::number(easy_score3)+"\t地图:"+easy_mode3);
    QLabel *text5=new QLabel("难度:普通");
    QLabel *text6=new QLabel("用户名:"+medium_name1+"\t得分:"+QString::number(medium_score1)+"\t地图:"+medium_mode1);
    QLabel *text7=new QLabel("用户名:"+medium_name2+"\t得分:"+QString::number(medium_score2)+"\t地图:"+medium_mode2);
    QLabel *text8=new QLabel("用户名:"+medium_name3+"\t得分:"+QString::number(medium_score3)+"\t地图:"+medium_mode3);
    QLabel *text9=new QLabel("难度:困难");
    QLabel *text10=new QLabel("用户名:"+diff_name1+"\t得分:"+QString::number(diff_score1)+"\t地图:"+diff_mode1);
    QLabel *text11=new QLabel("用户名:"+diff_name2+"\t得分:"+QString::number(diff_score2)+"\t地图:"+diff_mode2);
    QLabel *text12=new QLabel("用户名:"+diff_name3+"\t得分:"+QString::number(diff_score3)+"\t地图:"+diff_mode3);
    QHBoxLayout *hlayout = new QHBoxLayout;
    hlayout->addWidget(head);
    QVBoxLayout *vlayout = new QVBoxLayout;
    vlayout->addStretch(0);
    vlayout->addWidget(text1);
    vlayout->addWidget(text2);
    vlayout->addWidget(text3);
    vlayout->addWidget(text4);
    vlayout->addWidget(text5);
    vlayout->addWidget(text6);
    vlayout->addWidget(text7);
    vlayout->addWidget(text8);
    vlayout->addWidget(text9);
    vlayout->addWidget(text10);
    vlayout->addWidget(text11);
    vlayout->addWidget(text12);
    vlayout->addStretch(0);
    QHBoxLayout *mainlayout = new QHBoxLayout(this);
    mainlayout->addLayout(hlayout);
    mainlayout->addLayout(vlayout);
}
int HeroList::readheros(int score,int mode)   //判断程序
{
    loadheros();//如果玩家不打开排行榜的情况 我们需要手动读取数据
    if(mode==2)//简单难度
    {
        if(easy_score3<score)
        {
            return 1;
        }
    }
    else if(mode==1)//普通难度
    {
        if(medium_score3<score)
        {
            return 1;
        }
    }
    else if(mode==0)//困难难度
    {
        if(diff_score3<score)
        {
            return 1;
        }
    }
    return 0;
}
void HeroList::saveheros(int display_W, QString name, int score,int mode)
{
    heros = new QSettings("gamedatalist.ini",QSettings::IniFormat,this);
    if(name.isEmpty())
    {
        name="无名氏";
    }
    heros->beginGroup("gameUserData");
    QString modestr="";
    if(display_W==400)
    {
        modestr="小地图";
    }
    else if(display_W==600)
    {
        modestr="中地图";
    }
    else if(display_W==800)
    {
        modestr="大地图";
    }
    if(mode==2)//简单难度
    {
        if(easy_score2<score)//判断是不是大于第二名
        {
            if(easy_score1<score)//判断是不是大于第一名
            {
                heros->setValue("easy_name3",easy_name2);//第二名的数据给第三名
                heros->setValue("easy_score3",easy_score2);
                heros->setValue("easy_mode3",easy_mode2);
                heros->setValue("easy_name2",easy_name1);//第一名的数据给第二名
                heros->setValue("easy_score2",easy_score1);
                heros->setValue("easy_mode2",easy_mode1);
                heros->setValue("easy_name1",name);//当前数据给第二名
                heros->setValue("easy_score1",score);
                heros->setValue("easy_mode1",modestr);
            }
            else//不大于第一名就是第二名
            {
                heros->setValue("easy_name3",easy_name2);//第二名的数据给第三名
                heros->setValue("easy_score3",easy_score2);
                heros->setValue("easy_mode3",easy_mode2);
                heros->setValue("easy_name2",name);//当前数据给第二名
                heros->setValue("easy_score2",score);
                heros->setValue("easy_mode2",modestr);
            }
        }
        else//不大于第二名那就是第三名
        {
            heros->setValue("easy_name3",name);
            heros->setValue("easy_score3",score);
            heros->setValue("easy_mode3",modestr);
        }
    }
    else if(mode==1)//普通难度
    {
        if(medium_score2<score)//判断是不是大于第二名
        {
            if(medium_score1<score)//判断是不是大于第一名
            {
                heros->setValue("medium_name3",medium_name2);//第二名的数据给第三名
                heros->setValue("medium_score3",medium_score2);
                heros->setValue("medium_mode3",medium_mode2);
                heros->setValue("medium_name2",medium_name1);//第一名的数据给第二名
                heros->setValue("medium_score2",medium_score1);
                heros->setValue("medium_mode2",medium_mode1);
                heros->setValue("medium_name1",name);//当前数据给第二名
                heros->setValue("medium_score1",score);
                heros->setValue("medium_mode1",modestr);
            }
            else//不大于第一名就是第二名
            {
                heros->setValue("medium_name3",medium_name2);//第二名的数据给第三名
                heros->setValue("medium_score3",medium_score2);
                heros->setValue("medium_mode3",medium_mode2);
                heros->setValue("medium_name2",name);//当前数据给第二名
                heros->setValue("medium_score2",score);
                heros->setValue("medium_mode2",modestr);
            }
        }
        else//不大于第二名那就是第三名
        {
            heros->setValue("medium_name3",name);
            heros->setValue("medium_score3",score);
            heros->setValue("medium_mode3",modestr);
        }
    }
    else if(mode==0)//困难难度
    {
        if(diff_score2<score)//判断是不是大于第二名
        {
            if(diff_score1<score)//判断是不是大于第一名
            {
                heros->setValue("diff_name3",diff_name2);//第二名的数据给第三名
                heros->setValue("diff_score3",diff_score2);
                heros->setValue("diff_mode3",diff_mode2);
                heros->setValue("diff_name2",diff_name1);//第一名的数据给第二名
                heros->setValue("diff_score2",diff_score1);
                heros->setValue("diff_mode2",diff_mode1);
                heros->setValue("diff_name1",name);//当前数据给第二名
                heros->setValue("diff_score1",score);
                heros->setValue("diff_mode1",modestr);
            }
            else//不大于第一名就是第二名
            {
                heros->setValue("diff_name3",diff_name2);//第二名的数据给第三名
                heros->setValue("diff_score3",diff_score2);
                heros->setValue("diff_mode3",diff_mode2);
                heros->setValue("diff_name2",name);//当前数据给第二名
                heros->setValue("diff_score2",score);
                heros->setValue("diff_mode2",modestr);
            }
        }
        else//不大于第二名那就是第三名
        {
            heros->setValue("diff_name3",name);
            heros->setValue("diff_score3",score);
            heros->setValue("diff_mode3",modestr);
        }
    }
    heros->endGroup();
}
void HeroList::loadheros()    //加载程序数据
{
    heros = new QSettings("gamedatalist.ini",QSettings::IniFormat,this);
    heros->beginGroup("gameUserData");
    easy_name1 = heros->value("easy_name1","xxx").toString();
    easy_score1 = heros->value("easy_score1",0).toInt();
    easy_mode1 = heros->value("easy_mode1","xxx").toString();
    easy_name2 = heros->value("easy_name2","xxx").toString();
    easy_score2 = heros->value("easy_score2",0).toInt();
    easy_mode2 = heros->value("easy_mode2","xxx").toString();
    easy_name3 = heros->value("easy_name3","xxx").toString();
    easy_score3 = heros->value("easy_score3",0).toInt();
    easy_mode3 = heros->value("easy_mode3","xxx").toString();
    medium_name1 = heros->value("medium_name1","xxx").toString();
    medium_score1 = heros->value("medium_score1",0).toInt();
    medium_mode1 = heros->value("medium_mode1","xxx").toString();
    medium_name2 = heros->value("medium_name2","xxx").toString();
    medium_score2 = heros->value("medium_score2",0).toInt();
    medium_mode2 = heros->value("medium_mode2","xxx").toString();
    medium_name3 = heros->value("medium_name3","xxx").toString();
    medium_score3 = heros->value("medium_score3",0).toInt();
    medium_mode3 = heros->value("medium_mode3","xxx").toString();
    diff_name1 = heros->value("diff_name1","xxx").toString();
    diff_score1 = heros->value("diff_score1",0).toInt();
    diff_mode1 = heros->value("diff_mode1","xxx").toString();
    diff_name2 = heros->value("diff_name2","xxx").toString();
    diff_score2 = heros->value("diff_score2",0).toInt();
    diff_mode2 = heros->value("diff_mode2","xxx").toString();
    diff_name3 = heros->value("diff_name3","xxx").toString();
    diff_score3 = heros->value("diff_score3",0).toInt();
    diff_mode3 = heros->value("diff_mode3","xxx").toString();
    heros->endGroup();
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值