运用Qt实现贪吃蛇小游戏的具体代码
游戏大厅
hall.h
#ifndef HALL_H
#define HALL_H#include <QWidget>
#include <QPaintEvent>
QT_BEGIN_NAMESPACE
namespace Ui { class Hall; }
QT_END_NAMESPACEclass Hall : public QWidget
{Q_OBJECTpublic:Hall(QWidget *parent = nullptr);~Hall();//重写绘图事件void paintEvent(QPaintEvent *event);private:Ui::Hall *ui;
};
#endif // HALL_H
hall.cpp
#include "hall.h"
#include "ui_hall.h"#include <QPainter>
#include <QPixmap>
#include <QPushButton>
#include <QIcon>
#include <QFont>
#include <QDialog>
#include <QVBoxLayout>
#include <QSound>
#include <QLabel>
#include "game_select.h"
#include "hint.h"
Hall::Hall(QWidget *parent): QWidget(parent), ui(new Ui::Hall)
{ui->setupUi(this);this->setFixedSize(1200,800);//设置窗口初始大小this->setWindowIcon(QIcon(":res/ico.png"));// 窗口图标this->setWindowTitle("贪吃蛇");QFont font("华文隶书",40);QPushButton* start=new QPushButton(this);start->move(440,630);start->setText("开始游戏");start->setFont(font);start->setStyleSheet("QPushButton{border-radius: 10px; background-color: green;}""QPushButton:pressed{background-color: white}");Game_select* gameselect=new Game_select;connect(start,&QPushButton::clicked,[=](){this->close();QSound::play(":res/clicked.wav");gameselect->setGeometry(this->geometry());gameselect->show();});QPushButton* hint=new QPushButton(this);Hint* H_t=new Hint;connect(hint,&QPushButton::clicked,[=](){H_t->show();});hint->move(20,20);hint->setIconSize(QSize(50,50));hint->setText("免责声明");hint->setFont(QFont("宋体",24));hint->setIcon(QIcon(":res/tishi.png"));}Hall::~Hall()
{delete ui;
}void Hall::paintEvent(QPaintEvent *event)
{(void) event;QPainter painter(this);QPixmap pixmap(":res/game_hall.png");painter.drawPixmap(0,0,this->width(),this->height(),pixmap);
}
选关界面
game_select.h
#ifndef GAME_SELECT_H
#define GAME_SELECT_H#include <QWidget>class Game_select : public QWidget
{Q_OBJECT
public:explicit Game_select(QWidget *parent = nullptr);void paintEvent(QPaintEvent *event);signals:};#endif // GAME_SELECT_H
game_select.cpp
#include "game_select.h"
#include "game_room.h"
#include "hall.h"
#include <QIcon>
#include <QPushButton>
#include <QSound>
#include <QPainter>
#include <QPixmap>
#include <QFont>
#include <QTextEdit>
#include <QFile>
#include <QTextStream>
Game_select::Game_select(QWidget *parent) : QWidget(parent)
{this->setFixedSize(800,900);this->setWindowIcon(QIcon(":res/ico.png"));// 窗口图标this->setWindowTitle("关卡选择");QPushButton* ret=new QPushButton(this);ret->resize(80,80);ret->setIcon(QIcon(":res/back.png"));ret->move(this->width()-100,this->height()-100);connect(ret,&QPushButton::clicked,[=](){this->close();Hall* hall=new Hall;hall->show();QSound::play(":res/eatfood.wav");});QFont font("华文隶书",40);Game_room* gameroom=new Game_room;QPushButton* simplebutt=new QPushButton(this);simplebutt->move(350,200);simplebutt->setText("简单模式");simplebutt->setFont(font);connect(simplebutt,&QPushButton::clicked,[=](){this->close();gameroom->setFixedSize(1200,800);gameroom->setWindowIcon(QIcon(":res/ico.png"));// 窗口图标gameroom->setWindowTitle("贪吃蛇: 简单模式");gameroom->show();gameroom->setTimeOut(300);//设置不同难度的速度});QPushButton* normalbutt=new QPushButton(this);normalbutt->move(350,400);normalbutt->setText("普通模式");normalbutt->setFont(font);connect(normalbutt,&QPushButton::clicked,[=](){this->close();gameroom->setFixedSize(1200,800);gameroom->setWindowIcon(QIcon(":res/ico.png"));// 窗口图标gameroom->setWindowTitle("贪吃蛇: 普通模式");gameroom->show();gameroom->setTimeOut(200);//设置不同难度的速度});QPushButton* hardbutt=new QPushButton(this);hardbutt->move(350,600);hardbutt->setText("困难模式");hardbutt->setFont(font);connect(hardbutt,&QPushButton::clicked,[=](){this->close();gameroom->setFixedSize(1200,800);gameroom->setWindowIcon(QIcon(":res/ico.png"));// 窗口图标gameroom->setWindowTitle("贪吃蛇: 困难模式");gameroom->show();gameroom->setTimeOut(100);//设置不同难度的速度});QPushButton* history=new QPushButton(this);history->move(60,80);history->setText("历史记录");history->setFont(font);connect(history,&QPushButton::clicked,[=](){QWidget* widget=new QWidget;widget->setWindowTitle("历史战绩");widget->setFixedSize(500,400);widget->setWindowIcon(QIcon(":res/ico.png"));QTextEdit* edit=new QTextEdit(widget);edit->setFont(QFont("黑体",30));edit->setFixedSize(500,400);QFile file("C:/Users/xcj/Desktop/snake/snake/his.txt");file.open(QIODevice::ReadOnly);QTextStream in(&file);int data=in.readLine().toInt();edit->setText("上一次得分为:");edit->append(QString::number(data));//追加widget->show();});}void Game_select::paintEvent(QPaintEvent *event)
{(void) event;QPainter painter(this);QPixmap pix(":res/game_select.png");painter.drawPixmap(0,0,this->width(),this->height(),pix);
}
游戏界面
game_room
#ifndef GAME_ROOM_H
#define GAME_ROOM_H#include <QWidget>
#include <QSound>
//枚举蛇的移动方向
enum class SnakeDirect
{UP=0,DOWN,LEFT,RIGHT
};class Game_room : public QWidget
{Q_OBJECT
public:explicit Game_room(QWidget *parent = nullptr);void paintEvent(QPaintEvent *event);void moveUp();//向上移动void moveDOWN();//向下移动void moveLEFT();//向左移动void moveRIGHT();//向右移动bool isOver();//检测是否结束void createNewFood();//创建新的食物void setTimeOut(int timeout){moveTimeout =timeout;}private:const int kSnakeNodeWidth =20;//定义蛇节点的宽度const int kSnakeNodeHeight =20;//定义蛇节点的高度const int kDefaultTimeout = 200;//蛇的移动速度QList<QRectF> snakeList; //表示贪吃蛇链表QRectF foodRect; //食物节点SnakeDirect moveDirect=SnakeDirect::UP; //蛇默认移动方向位向上QTimer* timer;//定时器bool isGameStart = false;//是否开始游戏QSound * sound;//bgmint moveTimeout = kDefaultTimeout;};#endif // GAME_ROOM_H
game_room.cpp
#include "game_room.h"
#include <QPushButton>
#include <QPainter>
#include <QPixmap>
#include <QTimer>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include "game_select.h"
Game_room::Game_room(QWidget *parent) : QWidget(parent)
{//初始化蛇snakeList.push_back(QRectF(this->width()*0.5,this->height()*0.5,kSnakeNodeWidth,kSnakeNodeHeight));moveUp();moveUp();//创建食物createNewFood();timer=new QTimer(this);connect(timer,&QTimer::timeout,[=](){int cnt=1;// 通过intersects方法来判断蛇头与食物是否相交if(snakeList.front().intersects(foodRect)){QSound::play(":res/eatfood.wav");createNewFood();cnt++;}while(cnt--){switch (moveDirect){case SnakeDirect::UP:moveUp();break;case SnakeDirect::DOWN:moveDOWN();break;case SnakeDirect::LEFT:moveLEFT();break;case SnakeDirect::RIGHT:moveRIGHT();break;}}snakeList.pop_back();update();//更新链表});//开始与暂停按钮QPushButton* startb=new QPushButton(this);QPushButton* stopb=new QPushButton(this);QFont font("华文隶书",20);startb->move(980,150);stopb->move(980,225);startb->setText("开始游戏");stopb->setText("暂停游戏");startb->setFont(font);stopb->setFont(font);connect(startb,&QPushButton::clicked,[=](){isGameStart=true;timer->start(moveTimeout);sound=new QSound(":res/BGM.wav");sound->play();sound->setLoops(-1);//只要是真就循环播放});connect(stopb,&QPushButton::clicked,[=](){isGameStart=false;timer->stop();sound->stop();});//控制方向QPushButton* up=new QPushButton(this);QPushButton* down=new QPushButton(this);QPushButton* left=new QPushButton(this);QPushButton* right=new QPushButton(this);up->move(1020,372);down->move(1020,440);left->move(952,440);right->move(1088,440);up->setText("↑");down->setText("↓");left->setText("←");right->setText("→");up->setStyleSheet("QPushButton{border-radius: 10px; background-color: green;}""QPushButton:pressed{background-color: white}");down->setStyleSheet("QPushButton{border-radius: 10px; background-color: green;}""QPushButton:pressed{background-color: white}");left->setStyleSheet("QPushButton{border-radius: 10px; background-color: green;}""QPushButton:pressed{background-color: white}");right->setStyleSheet("QPushButton{border-radius: 10px; background-color: green;}""QPushButton:pressed{background-color: white}");up->setShortcut(QKeySequence(Qt::Key_Up));down->setShortcut(QKeySequence(Qt::Key_Down));left->setShortcut(QKeySequence(Qt::Key_Left));right->setShortcut(QKeySequence(Qt::Key_Right));QFont FF("宋体",40);up->setFont(FF);down->setFont(FF);left->setFont(FF);right->setFont(FF);//控制蛇的方向connect(up,&QPushButton::clicked,[=](){if(moveDirect != SnakeDirect::DOWN)moveDirect=SnakeDirect::UP;});connect(down,&QPushButton::clicked,[=](){if(moveDirect != SnakeDirect::UP)moveDirect=SnakeDirect::DOWN;});connect(left,&QPushButton::clicked,[=](){if(moveDirect != SnakeDirect::RIGHT)moveDirect=SnakeDirect::LEFT;});connect(right,&QPushButton::clicked,[=](){if(moveDirect != SnakeDirect::LEFT)moveDirect=SnakeDirect::RIGHT;});//退出游戏QPushButton* exit =new QPushButton(this);exit->move(935,690);exit->setText("退出");exit->setFont(QFont("华文琥珀",15));exit->setStyleSheet("QPushButton{border-radius: 10px;background-color: pink;}""QPushButton:pressed{background-color: blue;}");QMessageBox* msg=new QMessageBox(this);QPushButton* ok=new QPushButton("确认");QPushButton* cancel=new QPushButton("取消");msg->addButton(ok,QMessageBox::AcceptRole);msg->addButton(cancel,QMessageBox::RejectRole);msg->setWindowTitle("退出游戏");msg->setText("是否""退出游戏?");msg->setFont(QFont("隶书",12));msg->setIconPixmap(QPixmap(":res/exit.png"));connect(exit,&QPushButton::clicked,[=](){QSound::play(":res/clicked.wav");msg->show();msg->exec();//事件轮询 等待用户输入Game_select* select=new Game_select;if(msg->clickedButton()==ok){this->close();select->show();}else{msg->close();}});}void Game_room::paintEvent(QPaintEvent *event)
{(void) event;QPainter painter(this);QPixmap pix;pix.load(":res/game_room.png");painter.drawPixmap(0,0,900,this->height(),pix);pix.load(":res/game_room.2.png");painter.drawPixmap(900,0,300,this->height(),pix);//绘制蛇//蛇头if(moveDirect ==SnakeDirect::UP){pix.load(":res/up.png");}else if(moveDirect == SnakeDirect::DOWN){pix.load(":res/down.png");}else if(moveDirect == SnakeDirect::LEFT){pix.load(":res/left.png");}else if(moveDirect == SnakeDirect::RIGHT){pix.load(":res/right.png");}auto snakeHead=snakeList.front();painter.drawPixmap(snakeHead.x(),snakeHead.y(),kSnakeNodeWidth,kSnakeNodeHeight,pix);//绘制身体if(moveDirect ==SnakeDirect::UP){pix.load(":res/bd.png");}else if(moveDirect == SnakeDirect::DOWN){pix.load(":res/bd_D.png");}else if(moveDirect == SnakeDirect::LEFT){pix.load(":res/bd_L.png");}else if(moveDirect == SnakeDirect::RIGHT){pix.load(":res/bd_R.png");}for (int i=1;i<snakeList.size()-1;i++){auto node = snakeList.at(i);painter.drawPixmap(node.x(),node.y(),node.width(),node.height(),pix);}//绘制尾部if(moveDirect ==SnakeDirect::UP){pix.load(":res/tail.png");}else if(moveDirect == SnakeDirect::DOWN){pix.load(":res/tail_D.png");}else if(moveDirect == SnakeDirect::LEFT){pix.load(":res/tail_L.png");}else if(moveDirect == SnakeDirect::RIGHT){pix.load(":res/tail_R.png");}auto snakeTail = snakeList.back();painter.drawPixmap(snakeTail.x(),snakeTail.y(),snakeTail.width(),snakeTail.height(),pix);//绘制食物pix.load(":res/food.png");painter.drawPixmap(foodRect.x(),foodRect.y(),kSnakeNodeWidth,kSnakeNodeHeight,pix);//绘制分数pix.load(":res/scores_bg.png");painter.drawPixmap(920,4,230,150,pix);QPen pen;pen.setColor(Qt::black);painter.setPen(pen);QFont num("方正舒体",30);painter.setFont(num);painter.drawText(1000,95,QString("%1").arg(snakeList.size()));//写入分数;int n=snakeList.size();QFile file("C:/Users/xcj/Desktop/snake/snake/his.txt");if(file.open(QIODevice::WriteOnly)){QTextStream out(&file);int num=n;out<<num;//把num写入文件file.close();}//绘制游戏结束if(isOver()){pen.setColor(Qt::green);painter.setPen(pen);QFont over("华文琥珀",80);painter.setFont(over);painter.drawText(80,this->height()*0.5,QString("GAME OVER!"));timer->stop();QSound::play(":res/gameover.wav");sound->stop();}}void Game_room::moveUp()
{QPointF leftTop;//左上角坐标QPointF rightbutt;//右下角坐标auto snakeNode = snakeList.front();//表示蛇头int headx = snakeNode.x();int heady = snakeNode.y();if(heady<0)//穿墙时{leftTop = QPointF(headx,this->height()-kSnakeNodeHeight);}else{leftTop = QPointF(headx,heady-kSnakeNodeHeight);}rightbutt=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);snakeList.push_front(QRectF(leftTop,rightbutt));
}void Game_room::moveDOWN()
{QPointF leftTop;//左上角坐标QPointF rightbutt;//右下角坐标auto snakeNode = snakeList.front();//表示蛇头int headx = snakeNode.x();int heady = snakeNode.y();if(heady>this->height())//穿墙时{leftTop = QPointF(headx,0);}else{leftTop = snakeNode.bottomLeft();//获取矩形左下角坐标}rightbutt=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);snakeList.push_front(QRectF(leftTop,rightbutt));
}void Game_room::moveLEFT()
{QPointF leftTop;//左上角坐标QPointF rightbutt;//右下角坐标auto snakeNode = snakeList.front();//表示蛇头int headx = snakeNode.x();int heady = snakeNode.y();if(headx<0)//穿墙时{leftTop = QPointF(900-kSnakeNodeWidth,heady);}else{leftTop = QPointF(headx-kSnakeNodeWidth,heady);}rightbutt=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);snakeList.push_front(QRectF(leftTop,rightbutt));
}void Game_room::moveRIGHT()
{QPointF leftTop;//左上角坐标QPointF rightbutt;//右下角坐标auto snakeNode = snakeList.front();//表示蛇头int headx = snakeNode.x();int heady = snakeNode.y();if(headx+kSnakeNodeWidth>880)//穿墙时{leftTop = QPointF(0,heady);}else{leftTop = snakeNode.topRight();}rightbutt=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);snakeList.push_front(QRectF(leftTop,rightbutt));
}bool Game_room::isOver()
{for(int i=0;i<snakeList.size();i++){for(int j=i+1;j<snakeList.size();j++){if(snakeList.at(i) == snakeList.at(j)){return true;}}}return false;
}void Game_room::createNewFood()
{foodRect = QRectF(qrand()%(900/kSnakeNodeWidth)*kSnakeNodeWidth,qrand()%(this->height()/kSnakeNodeHeight)*kSnakeNodeHeight,kSnakeNodeWidth,kSnakeNodeHeight);
}