Qt製作貪吃蛇(一)

這篇文章內容是參考https://blog.csdn.net/sinan1995/article/details/81671311

 

這篇主要是怎樣實現創建一條蛇,並讓它動起來

首先先創建項目,基類可以是mainWidget或者Widget,這裏使用的是mainWidget

採用面向對象的方式,設計一個Snake類,製作這條蛇

Snake.h

#ifndef SNAKE_H
#define SNAKE_H

#include <QObject>
#include <QList>

class Snake : public QObject
{
    Q_OBJECT
public:
    explicit Snake(QObject *parent = nullptr);
public:
    enum Dir{Up, Down, Left, Right};

public:
    int moveDir = Dir::Up;
    int width=10;
    int height=10;
    QList<QRectF> body;

public:
    //節點個數,初始頭的位置,朝向(默認爲上)
    void initBody(int nodeNum=3,QPointF topLeft=QPointF(400,400),Dir dir=Dir::Up,int nodeWidth=10,int nodeHeight=10);
public:
    void addNodeUp(int);
    void addNodeDown(int);
    void addNodeLeft(int);
    void addNodeRight(int);
    void moveUp(int);
    void moveDown(int);
    void moveRight(int);
    void moveLeft(int);
    void move(int,int); //沿着當前的方向移動

signals:

public slots:
};

#endif // SNAKE_H

這個Snake類也可以不用繼承Object類,普通的類也行。

首先這個類裏有一些屬性,moveDir 表示蛇正在移動的方向,它的值是自定義的一個枚舉值,分別代表上下左右。

width 和 height 分別代表蛇的每個節點的寬和高。

body 是存放每個節點的矩形位置。

Snake.cpp

#include "snake.h"
#include <QPointF>

Snake::Snake(QObject *parent) : QObject(parent)
{
}

void Snake::initBody(int nodeNum, QPointF topLeft, Snake::Dir dir, int nodeWidth, int nodeHeight)
{
    width = nodeWidth;
    height = nodeHeight;
    moveDir = dir;
    if(dir==Dir::Up){
        for(int i=0;i<nodeNum;i++){         //topLeft座標 和 bottomRight座標
            body.append(QRectF(topLeft+QPoint(0,i*height),topLeft+QPoint(0,i*height)+QPointF(width,height)));
        }
    }else if (dir==Dir::Down) {
        for(int i=0;i<nodeNum;i++){
            body.append(QRectF(topLeft-QPoint(0,i*height),topLeft-QPoint(0,i*height)+QPointF(width,height)));
        }
    }else if (dir==Dir::Left) {
        for(int i=0;i<nodeNum;i++){
            body.append(QRectF(topLeft+QPoint(i*width,0),topLeft+QPoint(i*width,0)+QPointF(width,height)));
        }
    }else {
        for(int i=0;i<nodeNum;i++){
            body.append(QRectF(topLeft-QPoint(i*width,0),topLeft-QPoint(i*width,0)+QPointF(width,height)));
        }
    }
}

void Snake::addNodeUp(int windowHeight)
{
    if(body.at(0).y()-height<0){            //當碰到上邊界, 碰到邊界不會死
        body.insert(0,QRectF(QPointF(body.at(0).x(),windowHeight-height),
                             QPointF(body.at(0).x()+width,windowHeight)));
    }else{
        body.insert(0,QRectF(body.at(0).topLeft()+QPointF(0,-height),body.at(0).topRight()));
    }
}
void Snake::addNodeDown(int windowHeight)
{
    if(body.at(0).y()+2*height>windowHeight){       //當碰到下邊界,碰到邊界不會死
        body.insert(0,QRectF(QPointF(body.at(0).x(),height),
                             QPointF(body.at(0).x()+width,0)));
    }else{
        body.insert(0,QRectF(body.at(0).bottomLeft(),body.at(0).bottomRight()+QPointF(0,height)));
    }
}
void Snake::addNodeLeft(int windowWidth)
{
    if(body.at(0).x()-width<0){                     //當碰到左邊界,碰到邊界不會死
        body.insert(0,QRectF(QPointF(windowWidth-width,body.at(0).y()),
                             QPointF(windowWidth,body.at(0).y()+height)));
    }else{
        body.insert(0,QRectF(body.at(0).topLeft()+QPointF(-width,0),body.at(0).bottomLeft()));
    }
}
void Snake::addNodeRight(int windowWidth)
{
    if(body.at(0).x()+2*width>windowWidth){         //當碰到右邊界,碰到邊界不會死
        body.insert(0,QRectF(QPointF(0,body.at(0).y()),
                             QPointF(width,body.at(0).y()+height)));
    }else{
        body.insert(0,QRectF(body.at(0).topRight(),body.at(0).bottomRight()+QPointF(width,0)));
    }
}

void Snake::moveUp(int windowHeight)
{
    if(moveDir != Dir::Down){
        addNodeUp(windowHeight);
        body.removeLast();
        moveDir = Dir::Up;
    }
}
void Snake::moveDown(int windowHeight)
{
    if(moveDir != Dir::Up){
        addNodeDown(windowHeight);
        body.removeLast();
        moveDir = Dir::Down;
    }
}
void Snake::moveLeft(int windowWidth)
{
    if(moveDir != Dir::Right){
        addNodeLeft(windowWidth);
        body.removeLast();
        moveDir = Dir::Left;
    }
}
void Snake::moveRight(int windowWidth)
{
    if(moveDir != Dir::Left){
        addNodeRight(windowWidth);
        body.removeLast();
        moveDir = Dir::Right;
    }
}
void Snake::move(int windowWidth, int windowHeight)
{
    if(moveDir==Dir::Up){
        moveUp(windowHeight);
    }else if (moveDir==Dir::Down) {
        moveDown(windowHeight);
    }else if (moveDir==Dir::Left) {
        moveLeft(windowWidth);
    }else{
        moveRight(windowWidth);
    }
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "snake.h"
#include <QPaintEvent>
#include <QPainter>
#include <QBrush>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

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

public:
    Snake snake;

public:
    QTimer *timer;


private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    resize(480, 500);

    snake.initBody();

//開啓定時器,讓蛇自動走起來
    timer = new QTimer(this);
    timer->setInterval(500); //每500毫秒走一步
    connect(timer,&QTimer::timeout,this,[=]{
        snake.move(this->width(),this->height());
    });
    timer->start();
}

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

void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);  //開啓抗鋸齒

    QPen pen;
    pen.setColor(Qt::black);
    painter.setPen(pen);

    QBrush brush;
    brush.setColor(Qt::green);
    brush.setStyle(Qt::SolidPattern);
    painter.setBrush(brush);

    for(int i=0;i<snake.body.size();i++){
        painter.drawRect(snake.body.at(i));
    }


    update();
}

void MainWindow::keyPressEvent(QKeyEvent *event)
{
    switch (event->key()) {
        case Qt::Key_Up:
            snake.moveUp(this->height());
            break;
        case Qt::Key_Down:
            snake.moveDown(this->height());
            break;
        case Qt::Key_Left:
            snake.moveLeft(this->width());
            break;
        case Qt::Key_Right:
            snake.moveRight(this->width());
            break;
    }
}

運行結果展示

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章