QT實現(xiàn)貪吃蛇游戲代碼詳解
一、新建一個Qt項目
新建Qt Widgets Application,項目名稱為HappySnake,基類選擇QWidget,類名默認
二、添加要用到的頭文件
#include <QKeyEvent> #include <QRectF> #include <QPainter> #include <QPen> #include <QBrush> #include <QDebug> #include <QTimer> #include <QTime>
三、寫類聲明信息
- 貪吃蛇的本體使用小方框來代替
- 使用QList類來保存貪吃蛇的本體
- 使用定時器來設(shè)定刷新的時間
- 使用隨機函數(shù)生成獎勵的節(jié)點
- 使用paintEvent來進行繪圖
- keyPressEvent來監(jiān)測按鍵的按下,控制貪吃蛇的移動
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;//獎勵節(jié)點 };
四、對類函數(shù)的實現(xiàn)
構(gòu)造函數(shù)
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); resize(480,500); //設(shè)置窗體背景色為黑色 setStyleSheet("QWidget{background:black}"); setWindowOpacity(0.8);//設(shè)置窗口的透明度 snake.append(QRectF(200,500,snakeNodeWidth,snakeNodeHeight)); addTopRectF(); addTopRectF(); //首先生成一個獎勵節(jié)點 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; }
界面刷新
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(); }
隨機獎勵的生成
//隨機獎勵 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)); } }
移動
//向上移動 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))); } } //刪除結(jié)尾數(shù)據(jù) void Widget::deleteLastRectF() { snake.removeLast(); }
繪圖
//繪圖 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); }
按鍵事件
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(); //首先生成一個獎勵節(jié)點 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; } }
判斷蛇身是否相撞
//判斷蛇頭是否和蛇身相撞 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; }
五、結(jié)束
實現(xiàn)的效果:
總結(jié):
只是簡單的使用了paintevent進行繪圖,基本都是簡單的對Qt的一些常用類的使用,對面向?qū)ο蟮木幊虘?yīng)用的不是很好,更偏向于面向過程,所以完全可以改成C語言在Linux下實現(xiàn),思路都是相同的。
到此這篇關(guān)于QT實現(xiàn)貪吃蛇游戲代碼詳解的文章就介紹到這了,更多相關(guān)QT內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
VC外部符號錯誤_main,_WinMain@16,__beginthreadex解決方法
這篇文章主要介紹了VC外部符號錯誤_main,_WinMain@16,__beginthreadex解決方法,實例分析了比較典型的錯誤及對應(yīng)的解決方法,需要的朋友可以參考下2015-05-05C++調(diào)用libcurl開源庫實現(xiàn)郵件的發(fā)送功能流程詳解
libcurl是一個免費開源的網(wǎng)絡(luò)傳輸庫,支持ftp、ftps、tftp,http、https、telnet、ldap、pop3、smtp等多種協(xié)議,接下來讓我們一起來了解吧2021-11-11C++ 內(nèi)聯(lián)函數(shù)inline案例詳解
這篇文章主要介紹了C++ 內(nèi)聯(lián)函數(shù)inline案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-09-09C語言實現(xiàn)輸入一個字符串后打印出該字符串中字符的所有排列
這篇文章主要介紹了C語言實現(xiàn)輸入一個字符串后打印出該字符串中字符的所有排列的方法,是數(shù)學(xué)中非常實用的排列算法,需要的朋友可以參考下2014-09-09