美文网首页
qt开发简单贪吃蛇游戏

qt开发简单贪吃蛇游戏

作者: 一路向后 | 来源:发表于2022-04-06 22:47 被阅读0次

1.snake.pro

QT += core gui network widgets

TEMPATE = app
TARGET = snake
DEPENDPATH += .
INCLUDEPATH += .

HEADERS += mainwindow.h snake.h
SOURCES += main.cpp mainwindow.cpp snake.cpp
2.main.cpp
#include <QApplication>
#include <QTextCodec>
#include "mainwindow.h"

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    QTextCodec::setCodecForLocale(QTextCodec::codecForName("utf-8"));

    QWidget *pWidget = new MainWindow();

    pWidget->setFixedSize(440, 320);
    pWidget->show();

    return app.exec();
}

3.mainwindow.h

#ifndef _SNAKE_MAIN_WINDOW_H_
#define _SNAKE_MAIN_WINDOW_H_

#include <QtGlobal>
#include <QApplication>
#include <QDesktopWidget>
#include <QMainWindow>
#include <QWidget>
#include <QKeyEvent>
#include <QLabel>
#include <QPushButton>
#include <QSlider>
#include <QPainter>
#include <QTimer>
#include <QTime>
#include <QDebug>
#include "snake.h"

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

public slots:
    void changeScore(int score);

signals:
    void sig_snake_key_press(int key);
    void sig_snake_restart();
    void sig_snake_start_or_pause();
    void sig_snake_speed(int);

protected:
    void keyPressEvent(QKeyEvent *event);

private slots:
    void restartGame();
    void startGame();
    void setSpeed(int value);

private:
    void align();

    Snake *snake;
    QWidget *header;
    QPushButton *restart;
    QPushButton *start;
    QLabel *lab[3];
    QSlider *speed;

    bool pause;
};

#endif

4.mainwindow.cpp

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    QFont font;

    font.setPointSize(12);

    align();

    pause = true;

    header = new QWidget(this);
    snake = new Snake(this);

    restart = new QPushButton(header);
    start = new QPushButton(header);
    lab[0] = new QLabel(header);
    lab[1] = new QLabel(header);
    lab[2] = new QLabel(header);
    speed = new QSlider(Qt::Horizontal, header);

    speed->setValue(10);

    restart->setFocusPolicy(Qt::ClickFocus);
    start->setFocusPolicy(Qt::ClickFocus);
    speed->setFocusPolicy(Qt::ClickFocus);

    setFocusPolicy(Qt::ClickFocus);

    setFocus();

    header->setFixedSize(460, 60);

    restart->setText("重新开始");
    restart->resize(80, 30);
    restart->move(20, 20);
    restart->setFont(font);

    lab[0]->setFont(font);
    lab[0]->setText("速度: ");
    lab[0]->resize(40, 30);
    lab[0]->move(160, 20);
    lab[1]->setFont(font);
    lab[1]->setText("得分: ");
    lab[1]->resize(40, 30);
    lab[1]->move(350, 20);
    lab[2]->setFont(font);
    lab[2]->setText("0");
    lab[2]->resize(40, 30);
    lab[2]->move(395, 20);

    speed->setMinimum(0);
    speed->setMaximum(100);

    if(pause)
    {
        start->setText("开始");
    }
    else
    {
        start->setText("暂停");
    }

    start->resize(40, 30);
    start->move(110, 20);
    start->setFont(font);

    speed->move(205, 27);

    snake->move(0, 60);

    connect(restart, SIGNAL(clicked()), this, SLOT(restartGame()));
    connect(start, SIGNAL(clicked()), this, SLOT(startGame()));
    connect(speed, SIGNAL(valueChanged(int)), this, SLOT(setSpeed(int)));
    connect(this, SIGNAL(sig_snake_key_press(int)), snake, SLOT(keyPress(int)));
    connect(this, SIGNAL(sig_snake_restart()), snake, SLOT(restart()));
    connect(this, SIGNAL(sig_snake_start_or_pause()), snake, SLOT(startorpause()));
    connect(this, SIGNAL(sig_snake_speed(int)), snake, SLOT(setSpeed(int)));
    connect(snake, SIGNAL(sig_change_score(int)), this, SLOT(changeScore(int)));
}

MainWindow::~MainWindow()
{

}

void MainWindow::restartGame()
{
    setFocus();

    pause = false;

    if(pause)
    {
        start->setText("开始");
    }
    else
    {
        start->setText("暂停");
    }

    emit sig_snake_restart();
}

void MainWindow::startGame()
{
    if(pause)
    {
        start->setText("暂停");
        pause = false;
    }
    else
    {
        start->setText("开始");
        pause = true;
    }

    setFocus();

    emit sig_snake_start_or_pause();
}

void MainWindow::setSpeed(int value)
{
    emit sig_snake_speed(value);
}

void MainWindow::align()
{
    this->move((QApplication::desktop()->width()-this->width())/2, (QApplication::desktop()->height()-this->height())/2);
}

void MainWindow::keyPressEvent(QKeyEvent *event)
{
    emit sig_snake_key_press(event->key());
}

void MainWindow::changeScore(int score)
{
    //qDebug() << "change score";

    lab[2]->setText(QString::number(score));
    lab[2]->repaint();
}

5.snake.h

#ifndef _SNAKE_GAME_WINDOW_H_
#define _SNAKE_GAME_WINDOW_H_

#include <QtGlobal>
#include <QApplication>
#include <QDesktopWidget>
#include <QMainWindow>
#include <QWidget>
#include <QKeyEvent>
#include <QLabel>
#include <QPushButton>
#include <QPainter>
#include <QTimer>
#include <QTime>
#include <QDebug>

class Snake : public QWidget
{
    Q_OBJECT

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

signals:
    void sig_change_score(int);

public slots:
    void restart();
    void startorpause();
    void setSpeed(int speed);
    void keyPress(int key);

protected:
    void paintEvent(QPaintEvent *);
    void keyPressEvent(QKeyEvent *event);

private slots:
    void updateFrame();

private:
    void align();
    void generateSnake();
    void generateFood();
    bool verifyinbody(const QPoint &pos);
    bool verifyheadinbody();
    bool verifyboundary(const QPoint &pos);

    bool gameover;
    bool pause;
    int score;
    int interval;

    QTimer *timer;
    QVector<QPoint> snake;
    QPoint food;
    QPoint lastDirect;
    QPoint keyDirect;
};

#endif

6.snake.cpp

#include "snake.h"

Snake::Snake(QWidget *parent) : QWidget(parent)
{
    setFixedSize(440, 260);

    qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); 

    interval = 1000;

    //align();

    score = 0;

    generateSnake();

    //qDebug() << "generate snake success";

    gameover = false;

    generateFood();

    timer = new QTimer(this);

    timer->setInterval(interval);

    pause = true;

    if(pause == false)
    {
        timer->start();
    }

    connect(timer, SIGNAL(timeout()), this, SLOT(updateFrame()));
}

Snake::~Snake()
{

}

void Snake::generateSnake()
{
    QPoint pos;
    int x, y, z;
    int i;
    int j = 0;

redo:
    j = 0;

    snake.clear();

    x = qrand()%(20);
    y = qrand()%(11);

    pos = QPoint(x, y);

    snake.push_back(pos);

    for(i=0; i<8; i++)
    {
        do
        {
            z = qrand() % 4;

            if(z % 4 == 0)
            {
                x = -1;
                y = 0;
            }
            else if(z % 4 == 1)
            {
                x = 1;
                y = 0;
            }
            else if(z % 4 == 2)
            {
                x = 0;
                y = -1;
            }
            else if(z % 4 == 3)
            {
                x = 0;
                y = 1;
            }

            pos = snake[i] + QPoint(x, y);

            j++;

            if(j > 100)
                goto redo;
        }
        while(verifyinbody(pos) || verifyboundary(pos));

        snake.push_back(pos);
    }

    do
    {
        z = qrand() % 4;

        if(z % 4 == 0)
        {
            x = -1;
            y = 0;
        }
        else if(z % 4 == 1)
        {
            x = 1;
            y = 0;
        }
        else if(z % 4 == 2)
        {
            x = 0;
            y = -1;
        }
        else if(z % 4 == 3)
        {
            x = 0;
            y = 1;
        }

        pos = snake[0] + QPoint(x, y);

        j++;

        if(j > 100)
            goto redo;
    }
    while(verifyinbody(pos) || verifyboundary(pos));

    lastDirect = QPoint(x, y);
    keyDirect = lastDirect;
}

bool Snake::verifyinbody(const QPoint &pos)
{
    for(int i=0; i<snake.size(); i++)
    {
        if(snake[i] == pos)
        {
            return true;
        }
    }

    return false;
}

bool Snake::verifyheadinbody()
{
    for(int i=1; i<snake.size(); i++)
    {
        if(snake[i] == snake[0])
        {
            return true;
        }
    }

    return false;
}

bool Snake::verifyboundary(const QPoint &pos)
{
    if(pos.x() > 19 || pos.x() < 0 || pos.y() > 10 || pos.y() < 0)
        return true;
    else
        return false;
}

void Snake::generateFood()
{
    QPoint pos;

    do
    {
        int x = qrand()%(20);
        int y = qrand()%(11);

        pos = QPoint(x, y);
    }
    while(verifyinbody(pos));

    food = pos;
}

void Snake::align()
{
    this->move((QApplication::desktop()->width()-this->width())/2, (QApplication::desktop()->height()-this->height())/2);
}

void Snake::updateFrame()
{
    if(gameover)
        return;

    if(snake[0] + keyDirect == snake[1])
    {
        keyDirect = lastDirect;
    }
    else
    {
        lastDirect = keyDirect;
    }

    if(snake[0] + lastDirect != food)
    {
        QPoint pos = snake[snake.size()-1];

        for(int i=snake.size()-1; i>0; i--)
        {
            snake[i] = snake[i-1];
        }

        snake[0] = snake[0] + lastDirect;

        for(int i=0; i<snake.size(); i++)
        {
            if(verifyboundary(snake[i]) || verifyheadinbody())
            {
                gameover = true;

                for(int i=0; i<snake.size()-1; i++)
                {
                    snake[i] = snake[i+1];
                }

                snake[snake.size()-1] = pos;

                timer->stop();

                return;
            }
        }
    }
    else
    {
        snake.push_back(QPoint(0, 0));

        for(int i=snake.size(); i>0; i--)
        {
            snake[i] = snake[i-1];
        }

        snake[0] = food;

        score += 10;

        emit sig_change_score(score);

        generateFood();
    }

    repaint();
}

void Snake::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QBrush brush(QColor(0, 255, 0, 255));
    QBrush brush2(QColor(255, 0, 0, 255));
    QBrush brush3(QColor(255, 255, 0, 255));

    painter.drawRect(20, 20, 400, 220);

    painter.setBrush(brush3);

    painter.drawRect(20+snake[0].x()*20, 20+snake[0].y()*20, 20, 20);

    //qDebug() << "size: " << snake.size();
    painter.setBrush(brush);

    for(int i=1; i<snake.size(); i++)
    {
        painter.drawRect(20+snake[i].x()*20, 20+snake[i].y()*20, 20, 20);
    }

    painter.setBrush(brush2);

    painter.drawRect(20+food.x()*20, 20+food.y()*20, 20, 20);
}

void Snake::keyPressEvent(QKeyEvent *event)
{
    switch(event->key())
    {
        case Qt::Key_Down:
            keyDirect = QPoint(0, 1);
            break;

        case Qt::Key_Up:
            keyDirect = QPoint(0, -1);
            break;

        case Qt::Key_Left:
            keyDirect = QPoint(-1, 0);
            break;

        case Qt::Key_Right:
            keyDirect = QPoint(1, 0);
            break;
    }
}

void Snake::keyPress(int key)
{
    switch(key)
    {
        case Qt::Key_Down:
            keyDirect = QPoint(0, 1);
            break;

        case Qt::Key_Up:
            keyDirect = QPoint(0, -1);
            break;

        case Qt::Key_Left:
            keyDirect = QPoint(-1, 0);
            break;

        case Qt::Key_Right:
            keyDirect = QPoint(1, 0);
            break;
    }
}

void Snake::restart()
{
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); 

    //align();

    generateSnake();

    //qDebug() << "generate snake success";

    pause = false;
    gameover = false;

    score = 0;

    emit sig_change_score(score);

    generateFood();

    //timer->clearInterval();
    timer->setInterval(interval);

    timer->start();
}

void Snake::startorpause()
{
    if(pause == true)
    {
        timer->start();
        pause = false;
    }
    else
    {
        timer->stop();
        pause = true;
    }
}

void Snake::setSpeed(int speed)
{
    interval = 10000 / speed;
}

7.编译源码

$ qmake
$ make

8.界面效果

snake.png

相关文章

网友评论

      本文标题:qt开发简单贪吃蛇游戏

      本文链接:https://www.haomeiwen.com/subject/itgdsrtx.html