這篇文章內容是參考https://blog.csdn.net/sinan1995/article/details/81671311
這篇文章主要怎樣產生食物,並可以被蛇遲到
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:
void createFood();
bool hasEatFood(); //是否吃到食物
public:
QTimer *snakeMoveTimer;
QTimer *createFoodTimer;
QTimer *listenningTimer; //監聽器,高頻率判斷某事件是否發生,頻率越高可能比較消耗性能
void initTimer(); //初始化計時器,將計時器的創建放入這個函數中
public:
Snake snake;
QList<QRectF> food;
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
定義了一個食物屬性,還有一個創建食物的函數。定時器createFoodTimer用於間隔固定的時間創建一個食物,即執行createFood函數。當時調試的時候,發現如果蛇跑了很快(按住方向鍵不鬆手),有的時候吃不到食物,爲止我又加了一個定時器listenningTimer,我把它取名叫做監聽器,監聽某個時候是否吃到食物,將時間縮的更短,但性能消耗更大。
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTimer>
#include <QTime>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
resize(480, 500);
snake.initBody();
snake.move(this->width(),this->height()); //程序一啓動就要走一步,然後每隔固定時間走一步
createFood(); //程序一啓動就創建一個food
initTimer();
}
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));
}
brush.setColor(Qt::red);
painter.setBrush(brush);
for(int i=0;i<food.size();i++){
painter.drawEllipse(food.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;
}
}
void MainWindow::createFood()
{
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
// if(food.size()>5){ //可以選擇消除存在的食物,以至於讓界面上同時存在的食物不會那麼多
// food.removeAt(qrand()%5);
// }
food.append(QRectF(qrand()%(this->width()/20)*20,qrand()%(this->height()/20)*20,snake.width,snake.height));
if(qrand()%5==3){
food.append(QRectF(qrand()%(this->width()/20)*20-5,qrand()%(this->height()/20)*20-5,2*snake.width,2*snake.height));
}
}
bool MainWindow::hasEatFood()
{
for(int i=0;i<food.size();i++){
if(food.at(i).contains(snake.body.at(0).topLeft()+QPointF(snake.width/2,snake.height/2))){
food.removeAt(i);
snake.addNode(this->width(),this->height());
qDebug()<<"eat food";
return true;
}
}
return false;
}
void MainWindow::initTimer()
{
//開啓定時器,讓蛇自動走起來,並監聽吃食物
snakeMoveTimer = new QTimer(this);
snakeMoveTimer->setInterval(500); //每200毫秒走一步
connect(snakeMoveTimer,&QTimer::timeout,this,[=]{
snake.move(this->width(),this->height());
});
snakeMoveTimer->start();
//每隔一定時間創建出一個food
createFoodTimer = new QTimer(this);
createFoodTimer->setInterval(1000);
connect(createFoodTimer,&QTimer::timeout,this,[=]{
createFood();
});
createFoodTimer->start();
//創建一個監聽器
listenningTimer = new QTimer(this);
listenningTimer->setInterval(20); //0.02s監聽一次
connect(listenningTimer,&QTimer::timeout,this,[=]{
hasEatFood();
});
listenningTimer->start();
}
運行效果
Snake類變動
我在snake多加了一個函數addNode,用於當遲到了食物就長度就增加1
#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);
private:
void addNodeUp(int);
void addNodeDown(int);
void addNodeLeft(int);
void addNodeRight(int);
public:
void moveUp(int);
void moveDown(int);
void moveRight(int);
void moveLeft(int);
void move(int,int); //沿着當前的方向移動
void addNode(int,int);
signals:
public slots:
};
#endif // SNAKE_H
void Snake::addNode(int windowWidth,int windowHeight)
{
switch (moveDir) {
case Dir::Up:
addNodeUp(windowHeight);
break;
case Dir::Down:
addNodeDown(windowHeight);
break;
case Dir::Left:
addNodeLeft(windowWidth);
break;
case Dir::Right:
addNodeRight(windowWidth);
break;
}
}
可以改進的地方
關於產生食物,可以不讓食物產生的地方在蛇身上,也不要出現在已經有食物的地方