欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

QT實(shí)現(xiàn)貪吃蛇游戲

 更新時(shí)間:2021年05月17日 15:50:16   作者:白家名  
這篇文章主要為大家詳細(xì)介紹了QT實(shí)現(xiàn)貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

為了熟悉QT的相關(guān)知識,我用了大約8個(gè)小時(shí)的時(shí)間用QT再次寫了一遍貪吃蛇。

因?yàn)镼T的機(jī)制和平時(shí)寫的程序流程不同,所以程序中可能沒有遵守代碼規(guī)范。

運(yùn)行效果:

程序內(nèi)除了實(shí)現(xiàn)貪吃蛇的基本功能外,還添加了記錄得分、調(diào)節(jié)游戲速度、重新開始游戲等功能。

游戲內(nèi)容使用QPainter類進(jìn)行繪制。

編譯環(huán)境:

Windows Qt 5.9.0 Qt Creator 4.3.0

思路:

數(shù)組存儲蛇節(jié)點(diǎn)坐標(biāo)的貪吃蛇游戲思路。

因?yàn)榫帉戇^程中使用了分文件編寫,且QT框架的其他部分較多,這里僅展示程序?qū)崿F(xiàn)主要代碼。

代碼:

MainWindow.h 主窗口類頭文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPainter>     //畫家類
#include "snake.h"      //蛇類
#include <QKeyEvent>    //鍵盤事件
#include "food.h"       //食物類
#include <QTimer>       //定時(shí)器類

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

    //繪圖事件
    void paintEvent(QPaintEvent *);

    //游戲結(jié)束的情況
    void GameOver();

private:
    Ui::Widget *ui;

    Snake snake;        //蛇對象
    char key = 'd';     //接收鍵值,初始向右
    Food food;          //食物對象
    //創(chuàng)建定時(shí)器
    QTimer *timer = new QTimer(this);
    bool gameflag = false;//游戲結(jié)束標(biāo)記
    int score = 0;      //記錄得分
    int timerspeed = 200; //定時(shí)器速度
    bool bugflag = false; //用于解決操控過快導(dǎo)致撞死自己的bug的標(biāo)志

    //鍵盤事件,改變鍵值
    void keyPressEvent(QKeyEvent *ev);
};

#endif // WIDGET_H

MainWindow.cpp函數(shù)實(shí)現(xiàn)

#include "MainWindow.h"
#include "ui_widget.h"
#include <QLabel>
#include <QPushButton>

//主窗口構(gòu)造函數(shù)
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);      //初始化出.ui界面

    //一個(gè)格子寬高25像素,地圖寬高600像素,每行有24個(gè)格子

    //設(shè)置固定窗口大小
    setFixedSize(1000,600);

    //設(shè)置得分標(biāo)簽控件的屬性
    ui->label->setFont(QFont("黑體", 20, QFont::Bold, false));

    //設(shè)置游戲速度標(biāo)簽內(nèi)容
    ui->label_2->setFont(QFont("楷體", 16, QFont::Bold, false));
    ui->label_2->setText("游戲速度:");

    //滑動(dòng)條控件,這里將數(shù)值按一定比例放大縮小
    ui->horizontalSlider->setValue(200 >> 2);

    //監(jiān)聽滑動(dòng)條控件滑動(dòng)時(shí),改變定時(shí)器速度為滑動(dòng)條的值
    connect(ui->horizontalSlider,QSlider::valueChanged,[=]()
    {
        timerspeed = ui->horizontalSlider->value() << 2;
    });

    //設(shè)置重新開始按鈕屬性和內(nèi)容
    ui->pushButton_3->setFont(QFont("黑體",12));
    ui->pushButton_3->setText("重新開始");

    //監(jiān)聽重新開始按鈕
    connect(ui->pushButton_3,QPushButton::clicked,[=]()
    {
        snake.Reset();      //重置蛇
        score = 0;          //得分清0
        key = 'd';          //key值向右
        timerspeed = 200 << 2;//重置游戲速度
        timer->start(timerspeed);//重置定時(shí)器
        ui->horizontalSlider->setValue(200 >> 2);//重置滑動(dòng)條
        gameflag = false;   //重置游戲結(jié)束標(biāo)志
    });

    //開啟定時(shí)器
    timer->start(timerspeed);

    //監(jiān)聽定時(shí)器的信號,執(zhí)行表達(dá)式內(nèi)容
    connect(timer,&QTimer::timeout,[=]()
    {
        timer->start(timerspeed); //調(diào)整定時(shí)器的速度

        snake.Move(key);    //蛇移動(dòng)函數(shù)

        //吃到食物的情況
        (food.getfoodX() == snake.snakevec.at(0).x && food.getfoodY() == snake.snakevec.at(0).y) ?
        score++, food.randfood():    //得分+1,隨機(jī)產(chǎn)生一個(gè)食物坐標(biāo)
        snake.snakevec.pop_back();   //刪除蛇尾

        GameOver();    //游戲失敗的情況

        update();      //調(diào)用繪圖函數(shù)

        //更新標(biāo)簽控件的文本內(nèi)容
        ui->label->setText(QString("得分:%1").arg(score));
    });
}

//游戲失敗情況
void Widget::GameOver()
{
    //撞墻失敗
    if(snake.snakevec.at(0).x >= 24 * 25 || snake.snakevec.at(0).x < 0 ||
       snake.snakevec.at(0).y < 0 || snake.snakevec.at(0).y >= 24 * 25)
    {
        gameflag = true;
        timer->stop();      //暫停定時(shí)器
        return;
    }

    //撞自己失敗
    for(int i = 1; i < snake.snakevec.size(); i++)
    {
        if(snake.snakevec.at(0).x == snake.snakevec.at(i).x &&
           snake.snakevec.at(0).y == snake.snakevec.at(i).y)
            gameflag = true, timer->stop();
    }
}


//繪圖事件
void Widget::paintEvent(QPaintEvent *)
{
    //創(chuàng)建畫家對象,指定繪圖設(shè)備為this主窗口
    QPainter painter(this);

    //設(shè)置畫刷為紅色
    QBrush brush1(Qt::red);
    //讓畫家使用畫刷
    painter.setBrush(brush1);
    //畫食物
    painter.drawRect(QRect(food.getfoodX(),food.getfoodY(),25,25));

    //設(shè)置畫刷為黑色
    QBrush brush2(Qt::blue);
    painter.setBrush(brush2);

    //遍歷蛇坐標(biāo)容器,畫出代表蛇身的矩形
    for(auto snakenodei : snake.snakevec)
        //蛇頭畫圓形
        (snakenodei.x == snake.snakevec.at(0).x &&
         snakenodei.y == snake.snakevec.at(0).y) ?
        //蛇頭畫圓形
        painter.setRenderHint(QPainter::Antialiasing),  //用抗鋸齒畫圓
        painter.drawEllipse(QPoint(snakenodei.x + 12,snakenodei.y + 12),12,12):
        //蛇身畫矩形
        painter.drawRect(QRect(snakenodei.x,snakenodei.y,25,25));

    bugflag = false;    //在畫出蛇之后將標(biāo)志設(shè)為假

    //設(shè)置畫刷為黑色
    QBrush brush3(QColor(128, 64, 0));
    painter.setBrush(brush3);

    //畫出墻壁
    for(int i = 0; i < 24; i++)
          painter.drawRect(QRect(25 * 25, i * 25, 25, 25));

    //游戲結(jié)束時(shí)的繪圖
    if(gameflag)
    {   //設(shè)置文字屬性
        QFont font("楷體", 80, QFont::Bold, false);
        painter.setFont(font);      //使用字體
        painter.drawText(QRect(240, 200, 1000, 500), "游戲結(jié)束");   //畫出游戲結(jié)束文字
    }
}

//鍵盤事件,改變貪吃蛇移動(dòng)方向
void Widget::keyPressEvent(QKeyEvent *ev)
{
    if(bugflag)     //bug標(biāo)志為真直接返回
        return;

    switch (ev->key())
    {
    case Qt::Key_W:
        if(key == 's') break;   //按下與當(dāng)前方向相反按鍵時(shí)break
        key = 'w';
        bugflag = true; break;        //按鍵之后將標(biāo)志設(shè)為真
    case Qt::Key_S:
        if(key == 'w') break;
        key = 's';
        bugflag = true; break;
    case Qt::Key_A:
        if(key == 'd') break;
        key = 'a';
        bugflag = true; break;
    case Qt::Key_D:
        if(key == 'a') break;
        key = 'd';
        bugflag = true; break;
    case Qt::Key_Space:     //空格鍵暫停,這里有點(diǎn)問題
        timer->stop(); break;
    default:                //其他鍵重啟定時(shí)器
        timer->start(timerspeed);
    }
}

//析構(gòu)
Widget::~Widget()
{
    delete ui;
}

snake.h 蛇類頭文件

#ifndef SNAKE_H
#define SNAKE_H

#include <QWidget>
#include <QVector>      //Qt動(dòng)態(tài)數(shù)組類

class Snake : public QWidget
{
    Q_OBJECT
private:
    //蛇坐標(biāo)結(jié)構(gòu)
    struct  Snakecoor
    {
        int x;
        int y;
    };

public:
    explicit Snake(QWidget *parent = nullptr);

    //蛇坐標(biāo)容器
    QVector<Snakecoor> snakevec;

    //蛇移動(dòng)主要函數(shù)
    void Move(char key);

    //根據(jù)key值確定蛇的移動(dòng)方向
    void DeteDirMove(char key, Snakecoor &nexthead);

    //重置蛇
    void Reset();

signals:

public slots:
};

#endif // SNAKE_H

snake.cpp 蛇類函數(shù)實(shí)現(xiàn)

#include "snake.h"

//構(gòu)造函數(shù)初始化一條蛇
Snake::Snake(QWidget *parent) : QWidget(parent)
{
    Snakecoor snakenode;            //臨時(shí)結(jié)構(gòu)變量用于創(chuàng)建蛇
    for (int i = 5; i >= 0; i--) //從右向左創(chuàng)建5節(jié)蛇身,容器的第一個(gè)元素為蛇頭
    {
        snakenode.x = 25 * 8 + i * 25;//每個(gè)格子寬25像素
        snakenode.y = 25 * 8;
        snakevec.push_back(snakenode);//將蛇節(jié)點(diǎn)插入到數(shù)組中
    }
}

//確定蛇的移動(dòng)方向,確定新蛇頭的坐標(biāo)位置
inline void Snake::DeteDirMove(char key, Snakecoor &nexthead)
{
    switch (key)
    {
    case 'w':
        //新蛇頭坐標(biāo)根據(jù)舊蛇頭坐標(biāo)改變
        nexthead.x = snakevec.front().x;
        nexthead.y = snakevec.front().y - 25;
        break;
    case 's':
        nexthead.x = snakevec.front().x;
        nexthead.y = snakevec.front().y + 25;
        break;
    case 'a':
        nexthead.x = snakevec.front().x - 25;
        nexthead.y = snakevec.front().y;
        break;
    case 'd':
        nexthead.x = snakevec.front().x + 25;
        nexthead.y = snakevec.front().y;
    }
}

//蛇移動(dòng)主要函數(shù)
void Snake::Move(char key)
{
    Snakecoor nexthead;  //創(chuàng)建一個(gè)新的蛇頭

    DeteDirMove(key, nexthead);  //確定新蛇頭的位置

    snakevec.insert(snakevec.begin(), nexthead);    //將新蛇頭插入到容器頭部
}

//重置蛇函數(shù)
void Snake::Reset()
{
    snakevec.clear();   //清空容器

    //初始化蛇
    Snakecoor snakenode;
    for (int i = 5; i >= 0; i--)
    {
        snakenode.x = 25 * 8 + i * 25;
        snakenode.y = 25 * 8;
        snakevec.push_back(snakenode);
    }
}

food.h 食物類頭文件

#ifndef FOOD_H
#define FOOD_H

#include <QWidget>

class Food : public QWidget
{
    Q_OBJECT
public :
    int food_x = 0;     //食物坐標(biāo)
    int food_y = 0;

public:
    explicit Food(QWidget *parent = nullptr);

    void randfood();    //隨機(jī)產(chǎn)生食物坐標(biāo)
    int getfoodX();     //返回食物坐標(biāo)
    int getfoodY();

signals:

public slots:
};

#endif // FOOD_H

food.cpp 食物類函數(shù)實(shí)現(xiàn)

#include "food.h"
#include <ctime>

Food::Food(QWidget *parent) : QWidget(parent)
{
    randfood();     //創(chuàng)建對象時(shí)產(chǎn)生就一個(gè)隨機(jī)坐標(biāo)

}

//隨機(jī)產(chǎn)生食物坐標(biāo)
void Food::randfood()
{
    srand((unsigned)time(NULL));
    food_x = (rand() % 24) * 25;
    food_y = (rand() % 24 )* 25;
}

//獲取食物的坐標(biāo)
int Food::getfoodX()
{
    return food_x;
}

int Food::getfoodY()
{
    return food_y;
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • c++ fstream 文件追加模式示例詳解

    c++ fstream 文件追加模式示例詳解

    本文給大家介紹c++ fstream 文件追加模式示例詳解,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-10-10
  • C++算法學(xué)習(xí)之回溯法的應(yīng)用

    C++算法學(xué)習(xí)之回溯法的應(yīng)用

    這篇文章介紹了C++算法中回溯法的一些應(yīng)用,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • Qt實(shí)現(xiàn)定時(shí)器的兩種方法分享

    Qt實(shí)現(xiàn)定時(shí)器的兩種方法分享

    這篇文章主要為大家詳細(xì)介紹了Qt中實(shí)現(xiàn)定時(shí)器的兩種不同方法,文中的示例代碼講解詳細(xì),對我們了解Qt有一定的幫助,感興趣的可以跟隨小編一起學(xué)習(xí)一下
    2022-11-11
  • C語言指針必備基礎(chǔ)全面覆蓋

    C語言指針必備基礎(chǔ)全面覆蓋

    數(shù)據(jù)對象是指存儲在內(nèi)存中的一個(gè)指定數(shù)據(jù)類型的數(shù)值或字符串,它們都有一個(gè)自己的地址,指針是保存這個(gè)地址的變量,本篇文章帶你掌握C語言指針的用法
    2021-10-10
  • C++中聲明類的class與聲明結(jié)構(gòu)體的struct關(guān)鍵字詳解

    C++中聲明類的class與聲明結(jié)構(gòu)體的struct關(guān)鍵字詳解

    這篇文章主要介紹了C++中聲明類的class與聲明結(jié)構(gòu)體的struct關(guān)鍵字,默認(rèn)情況下結(jié)構(gòu)的所有成員均是公有的,而類的所有成員是私有的,需要的朋友可以參考下
    2016-01-01
  • c++11中關(guān)于std::thread的join的詳解

    c++11中關(guān)于std::thread的join的詳解

    這篇文章主要介紹了c++11中關(guān)于std::thread的join詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • C++簡明分析臨時(shí)對象是什么

    C++簡明分析臨時(shí)對象是什么

    對性能來說,許多的問題都需要和出現(xiàn)頻率及本身執(zhí)行一次的開銷掛鉤,有些問題雖然看似比較開銷較大,但是很少會執(zhí)行到,那也不會對程序有大的影響;同樣一個(gè)很小開銷的函數(shù)執(zhí)行很頻繁,同樣會對程序的執(zhí)行效率有很大影響。本章中作者主要根據(jù)臨時(shí)對象來闡述這樣一個(gè)觀點(diǎn)
    2022-04-04
  • C++?超詳細(xì)分析多態(tài)的原理與實(shí)現(xiàn)

    C++?超詳細(xì)分析多態(tài)的原理與實(shí)現(xiàn)

    這篇文章主要介紹了C++多態(tài)的原理與實(shí)現(xiàn),多態(tài)是一種面向?qū)ο蟮脑O(shè)計(jì)思路,本身和C++不是強(qiáng)綁定的,其他語言當(dāng)中一樣有多態(tài),只不過實(shí)現(xiàn)的方式可能有所不同。下面來一起了解更多詳細(xì)內(nèi)容吧
    2022-03-03
  • C語言數(shù)據(jù)結(jié)構(gòu) 棧的基礎(chǔ)操作

    C語言數(shù)據(jù)結(jié)構(gòu) 棧的基礎(chǔ)操作

    這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu) 棧的基礎(chǔ)操作的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • win10環(huán)境下C++ vs2015編譯opencv249的教程

    win10環(huán)境下C++ vs2015編譯opencv249的教程

    這篇文章主要介紹了win10環(huán)境下C++ vs2015編譯opencv249的教程,本文分步驟給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03

最新評論