一、新建一個Qt項目
新建Qt Widgets Application,項目名稱為HappySnake,基類選擇QWidget,類名默認
二、添加要用到的頭文件
1
2
3
4
5
6
7
8
|
#include <QKeyEvent> #include <QRectF> #include <QPainter> #include <QPen> #include <QBrush> #include <QDebug> #include <QTimer> #include <QTime> |
三、寫類聲明信息
- 貪吃蛇的本體使用小方框來代替
- 使用QList類來保存貪吃蛇的本體
- 使用定時器來設定刷新的時間
- 使用隨機函數生成獎勵的節點
- 使用paintEvent來進行繪圖
- keyPressEvent來監測按鍵的按下,控制貪吃蛇的移動
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
class Widget : public QWidget { Q_OBJECT public : explicit Widget(QWidget *parent = 0); ~Widget(); protected : void paintEvent(QPaintEvent *); void keyPressEvent(QKeyEvent *); private : void addTopRectF(); void addDownRectF(); void addLeftRectF(); void addRightRectF(); void deleteLastRectF(); bool snakeStrike(); enum Move{Left,Right,Up,Down}; protected slots: void timeOut(); void rewardTimeOut(); private : Ui::Widget *ui; QList<QRectF> snake; //貪吃蛇本體 int snakeNodeWidth = 10; int snakeNodeHeight = 10; QTimer *timer; QTimer *rewardTimer; int time = 100; int moveFlage = Up; bool gameOver = false ; bool gameStart = false ; QList<QRectF> rewardNode; //獎勵節點 }; |
四、對類函數的實現
構造函數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
Widget::Widget(QWidget *parent) : QWidget(parent), ui( new Ui::Widget) { ui->setupUi( this ); resize(480,500); //設置窗體背景色為黑色 setStyleSheet( "QWidget{background:black}" ); setWindowOpacity(0.8); //設置窗口的透明度 snake.append(QRectF(200,500,snakeNodeWidth,snakeNodeHeight)); addTopRectF(); addTopRectF(); //首先生成一個獎勵節點 rewardNode.append(QRectF(100,100,snakeNodeWidth,snakeNodeWidth)); timer = new QTimer; connect(timer, SIGNAL(timeout()), this ,SLOT(timeOut())); //timer->start(time); rewardTimer = new QTimer; connect(rewardTimer,SIGNAL(timeout()), this ,SLOT(rewardTimeOut())); //rewardTimer->start(time*30); } Widget::~Widget() { delete ui; } |
界面刷新
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
void Widget::timeOut() { int flage = 1; for ( int i=0; i<rewardNode.length(); i++){ if (rewardNode.at(i).contains(snake.at(0).topLeft()+QPointF(snakeNodeWidth/2,snakeNodeHeight/2))){ //if(snake.at(0).contains(rewardNode.at(i).x()+rewardNode.at(i).width()/2,rewardNode.at(i).y()+rewardNode.at(i).height()/2)){ if (rewardNode.at(i).width()>snakeNodeWidth){ //額外獎勵 flage += 2; } flage++; //正常獎勵 rewardNode.removeAt(i); break ; } } while (flage--){ switch (moveFlage) { case Up: addTopRectF(); break ; case Down: addDownRectF(); break ; case Right: addRightRectF(); break ; case Left: addLeftRectF(); break ; default : break ; } } deleteLastRectF(); update(); } |
隨機獎勵的生成
1
2
3
4
5
6
7
8
9
10
11
12
|
//隨機獎勵 void Widget::rewardTimeOut() { qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); if (rewardNode.length() > 5){ rewardNode.removeAt(qrand()%5); } rewardNode.append(QRectF(qrand()%( this ->width()/20)*20,qrand()%( this ->height()/20)*20,snakeNodeWidth,snakeNodeWidth)); if (qrand()%5 == 3){ rewardNode.append(QRectF(qrand()%( this ->width()/20)*20-5,qrand()%( this ->height()/20)*20-5,snakeNodeWidth*2,snakeNodeWidth*2)); } } |
移動
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
//向上移動 void Widget::addTopRectF() { if (snake.at(0).y()-snakeNodeHeight < 0){ snake.insert(0,QRectF(QPointF(snake.at(0).x(), this ->height()-snakeNodeHeight), QPointF(snake.at(0).x()+snakeNodeWidth, this ->height()))); } else { snake.insert(0,QRectF(snake.at(0).topLeft()+QPointF(0,-snakeNodeHeight),snake.at(0).topRight())); } } //向下移動 void Widget::addDownRectF() { if (snake.at(0).y()+snakeNodeHeight*2 > this ->height()){ snake.insert(0,QRectF(QPointF(snake.at(0).x(),snakeNodeHeight), QPointF(snake.at(0).x()+snakeNodeWidth,0))); } else { snake.insert(0,QRectF(snake.at(0).bottomLeft(),snake.at(0).bottomRight()+QPointF(0,snakeNodeHeight))); } } //向左移動 void Widget::addLeftRectF() { if (snake.at(0).x()-snakeNodeWidth < 0){ snake.insert(0,QRectF(QPointF( this ->width()-snakeNodeWidth,snake.at(0).y()), QPointF( this ->width(),snake.at(0).y()+snakeNodeHeight))); } else { snake.insert(0,QRectF(snake.at(0).topLeft()+QPointF(-snakeNodeWidth,0),snake.at(0).bottomLeft())); } } //向右移動 void Widget::addRightRectF() { if (snake.at(0).x()+snakeNodeWidth*2 > this ->width()){ snake.insert(0,QRectF(QPointF(0,snake.at(0).y()), QPointF(snakeNodeWidth,snake.at(0).y()+snakeNodeHeight))); } else { snake.insert(0,QRectF(snake.at(0).topRight(),snake.at(0).bottomRight()+QPointF(snakeNodeWidth,0))); } } //刪除結尾數據 void Widget::deleteLastRectF() { snake.removeLast(); } |
繪圖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
//繪圖 void Widget::paintEvent(QPaintEvent *event) { QPainter painter( this ); QPen pen; QBrush brush; QFont font( "方正舒體" ,12,QFont::ExtraLight, false ); //反鋸齒 painter.setRenderHint(QPainter::Antialiasing); pen.setColor(Qt::black); brush.setColor(Qt::green); brush.setStyle(Qt::SolidPattern); painter.setPen(pen); painter.setBrush(brush); for ( int i=0; i<snake.length(); i++){ painter.drawRect(snake.at(i)); } brush.setColor(Qt::red); painter.setBrush(brush); for ( int i=0; i<rewardNode.length(); i++){ painter.drawEllipse(rewardNode.at(i)); } pen.setColor(Qt::white); painter.setPen(pen); painter.setFont(font); painter.drawText(20,20,QString( "當前得分:" )+QString( "%1" ).arg(snake.length())); if (snakeStrike()){ QFont font( "方正舒體" ,30,QFont::ExtraLight, false ); painter.setFont(font); painter.drawText(( this ->width()-300)/2,( this ->height()-30)/2,QString( "GAME OVER!" )); timer->stop(); rewardTimer->stop(); gameOver = true ; } QWidget::paintEvent(event); } |
按鍵事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
void Widget::keyPressEvent(QKeyEvent *event) { switch (event->key()){ case Qt::Key_Up: if (moveFlage != Down){ moveFlage = Up; } break ; case Qt::Key_Down: if (moveFlage != Up){ moveFlage = Down; } break ; case Qt::Key_Right: if (moveFlage != Left){ moveFlage = Right; } break ; case Qt::Key_Left: if (moveFlage != Right){ moveFlage = Left; } break ; case Qt::Key_Enter: case Qt::Key_Return: if (gameOver){ snake.clear(); rewardNode.clear(); moveFlage = Up; snake.append(QRectF(200,500,snakeNodeWidth,snakeNodeHeight)); addTopRectF(); addTopRectF(); //首先生成一個獎勵節點 rewardNode.append(QRectF(100,100,snakeNodeWidth,snakeNodeWidth)); timer->start( time ); rewardTimer->start( time *30); gameOver = false ; } break ; case Qt::Key_Space: if (gameStart && !gameOver){ timer->start( time ); rewardTimer->start( time *30); gameStart = false ; } else if (!gameStart && !gameOver){ timer->stop(); rewardTimer->stop(); gameStart = true ; } break ; default : break ; } } |
判斷蛇身是否相撞
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//判斷蛇頭是否和蛇身相撞 bool Widget::snakeStrike() { for ( int i=0; i<snake.length(); i++){ for ( int j=i+1; j<snake.length(); j++){ if (snake.at(i) == snake.at(j)){ return true ; } } } return false ; } |
五、結束
實現的效果:
總結:
只是簡單的使用了paintevent進行繪圖,基本都是簡單的對Qt的一些常用類的使用,對面向對象的編程應用的不是很好,更偏向于面向過程,所以完全可以改成C語言在Linux下實現,思路都是相同的。
到此這篇關于QT實現貪吃蛇游戲代碼詳解的文章就介紹到這了,更多相關QT內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/sinan1995/article/details/81671311