一、项目功能演示:
- 开始界面可以点击进入游戏。
- 点击进入游戏之后,切换到选项界面,该界面可以选择游戏难度,回退,以及查询最近一次游戏得分。
- 游戏具体界面如下。贴图啥的可以自己换,本人审美不咋行,随便找的贴图。
二、文件展示:
三、项目代码:
1.打开窗口实现:
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QPushButton> #include <QLabel> #include <QFont> #include <QSound> #include "gameselect.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { //初始化窗口,标题,图标,窗口大小 ui->setupUi(this); this->setWindowTitle("贪吃蛇"); this->setWindowIcon(QIcon(":/image/pix.png")); this->setFixedSize(600,400); //窗口背景设置,将图片设置自动拉伸 QLabel* label=new QLabel(this); label->setGeometry(0,0,this->width(),this->height()); label->setPixmap(QPixmap(":/image/enter.jpg")); label->setScaledContents(true); //设置进入按钮 QPushButton* enter_but=new QPushButton(this); enter_but->move(250,250); enter_but->setText("进入游戏"); enter_but->setStyleSheet("QPushButton{border:0px;color:red;}"); //按钮文本设置 QFont font("华文行楷",18); enter_but->setFont(font); //创建选项页面,设置点击音效,打开新窗口,关闭旧窗口 GameSelect* gameSelect=new GameSelect; connect(enter_but,&QPushButton::clicked,[=]() { gameSelect->setGeometry(this->geometry()); QSound::play(":/image/6.wav"); gameSelect->show(); this->close(); }); } MainWindow::~MainWindow() { delete ui; }
2.选项窗口实现:
#include "gameselect.h" #include <QIcon> #include <QLabel> #include <QDebug> #include <QVBoxLayout> #include <QPushButton> #include <QFont> #include "mainwindow.h" #include <QSound> #include "gameroom.h" #include <QFile> GameSelect::GameSelect(QWidget *parent) : QWidget(parent) { //窗口大小固定,设置图标,标题 this->setFixedSize(600,400); this->setWindowTitle("关卡选择"); this->setWindowIcon(QIcon(":/image/pix.png")); //加载背景 QLabel* label=new QLabel(this); label->setGeometry(this->geometry()); label->setPixmap(QPixmap(":/image/load.jpg")); //创建一个widget对象存放布局管理器,管理选项按钮 QWidget* widget=new QWidget(this); widget->setGeometry(150,100,300,250); //创建布局管理器,并将它设置到widget对象 QVBoxLayout* layout=new QVBoxLayout; widget->setLayout(layout); //选项按钮创建 QPushButton* but_easy=new QPushButton("简单模式"); QPushButton* but_normal=new QPushButton("正常模式"); QPushButton* but_diff=new QPushButton("困难模式"); QPushButton* but_grades=new QPushButton("战绩查询"); QPushButton* but_ret=new QPushButton("返回上页"); //按钮添加到布局管理器 layout->addWidget(but_easy); layout->addWidget(but_normal); layout->addWidget(but_diff); layout->addWidget(but_grades); layout->addWidget(but_ret); //设置按钮的拉伸策略,是的可以占满整个布局管理器 but_easy->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); but_normal->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); but_diff->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); but_grades->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); but_ret->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); QFont font("华文行楷",25); widget->setFont(font); //设置按钮无边框,文本显示颜色为蓝色 but_easy->setStyleSheet("QPushButton{border: 0px;color:blue;}"); but_normal->setStyleSheet("QPushButton{border: 0px;color:blue;}"); but_diff->setStyleSheet("QPushButton{border: 0px;color:blue;}"); but_grades->setStyleSheet("QPushButton{border: 0px;color:blue;}"); but_ret->setStyleSheet("QPushButton{border: 0px;color:blue;}"); //连接按钮和槽函数,直接使用lambda表达式 connect(but_ret,&QPushButton::clicked,[=]() { MainWindow* mainwindow=new MainWindow; QSound::play(":/image/6.wav"); mainwindow->show(); this->close(); }); GameRoom* room=new GameRoom; connect(but_easy,&QPushButton::clicked,[=]() { room->setGeometry(this->geometry()); QSound::play(":/image/6.wav"); room->show(); this->close(); room->setMoveTimeout(300); }); connect(but_normal,&QPushButton::clicked,[=]() { room->setGeometry(this->geometry()); QSound::play(":/image/6.wav"); room->show(); this->close(); room->setMoveTimeout(200); }); connect(but_diff,&QPushButton::clicked,[=]() { room->setGeometry(this->geometry()); QSound::play(":/image/6.wav"); room->show(); this->close(); room->setMoveTimeout(100); }); connect(but_grades, &QPushButton::clicked, [=]() { QSound::play(":/image/6.wav"); QWidget* widget = new QWidget; widget->setWindowTitle("历史分数"); widget->setWindowIcon(QIcon(":/image/pix.png")); widget->setFixedSize(400, 200); QLabel* label=new QLabel(widget); label->setGeometry(0,0,400,200); QFile file("C:/Users/86133/Desktop/Qt-tmp.txt"); file.open(QIODevice::ReadOnly); QTextStream in(&file); QString grade=in.readLine(); QFont font("行书",30); label->setFont(font); label->setText("最近得分:"+ grade); widget->show(); }); }
3.游戏窗口实现
#include "gameroom.h" #include <QIcon> #include <QPainter> #include <QTimer> #include <QPushButton> #include <QMessageBox> #include "gameselect.h" #include <QFile> #include <QTextStream> #include <QShortcut> GameRoom::GameRoom(QWidget *parent) : QWidget(parent) { //初始化窗口,标题,图标,大小 this->setWindowTitle("游戏房间"); this->setWindowIcon(QIcon(":/image/pix.png")); this->setFixedSize(600,400); //尾插一个节点作为头节点 snakeList.push_back(QRectF(160,220,kSnakeNodeWidth,kSnakeNodeHeight)); moveUp(); moveUp(); //创建食物 createFood(); //定时器设置 timer=new QTimer(this); connect(timer,&QTimer::timeout,[=]() { //如果吃到食物,重新生成食物 int cnt=1; if(snakeList.front().intersects(foodRect)) { createFood(); 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* sta_but=new QPushButton("开始游戏",this); QPushButton* stop_but=new QPushButton("暂停游戏",this); sta_but->move(450,100); stop_but->move(450,150); QFont font("楷体",15); sta_but->setFont(font); stop_but->setFont(font); //开始功能实现,音乐播放,音乐持续播放设置 connect(sta_but,&QPushButton::clicked,[=]() { isGameStart=true; timer->start(moveTimeout); sound=new QSound(":/image/2.wav"); sound->play(); sound->setLoops(-1); }); connect(stop_but,&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(480,230); down->move(480,270); left->move(440,250); right->move(520,250); up->setStyleSheet("QPushButton{border:0px}"); down->setStyleSheet("QPushButton{border:0px}"); left->setStyleSheet("QPushButton{border:0px}"); right->setStyleSheet("QPushButton{border:0px}"); QFont ft("楷体",25); up->setFont(ft); down->setFont(ft); left->setFont(ft); right->setFont(ft); QShortcut* s1=new QShortcut(QKeySequence("W"),up); QShortcut* s2=new QShortcut(QKeySequence("S"),down); QShortcut* s3=new QShortcut(QKeySequence("A"),left); QShortcut* s4=new QShortcut(QKeySequence("D"),right); QObject::connect(s1,&QShortcut::activated,up,&QPushButton::click); QObject::connect(s2,&QShortcut::activated,down,&QPushButton::click); QObject::connect(s3,&QShortcut::activated,left,&QPushButton::click); QObject::connect(s4,&QShortcut::activated,right,&QPushButton::click); 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_but=new QPushButton("退出游戏",this); exit_but->move(450,350); exit_but->setFont(font); QMessageBox* msg=new QMessageBox(this); QPushButton* ok=new QPushButton("ok"); QPushButton* cancel=new QPushButton("cancel"); msg->addButton(ok,QMessageBox::AcceptRole); msg->addButton(cancel,QMessageBox::RejectRole); msg->setWindowTitle("退出"); msg->setText("是否确定退出?"); connect(exit_but,&QPushButton::clicked,[=]() { msg->exec(); QSound::play(":/image/6.wav"); if(msg->clickedButton()==ok) { GameSelect* gameselect=new GameSelect; gameselect->show(); this->close(); } else { msg->close(); } }); } void GameRoom::paintEvent(QPaintEvent *event) { QPainter painter(this); QPixmap pix; pix.load(":/image/main.jpg"); painter.drawPixmap(0,0,400,400,pix); pix.load(":/image/control.jpg"); painter.drawPixmap(400,0,200,400,pix); //绘制蛇头 if(moveDirect==SnakeDirect::UP) pix.load(":/image/up.png"); else if(moveDirect==SnakeDirect::DOWN) pix.load(":/image/down.png"); else if(moveDirect==SnakeDirect::LEFT) pix.load(":/image/left.png"); else pix.load(":/image/right.png"); auto snakeHead=snakeList.front(); painter.drawPixmap(snakeHead.x(),snakeHead.y(),snakeHead.width(),snakeHead.height(),pix); //绘制蛇身 pix.load(":/image/circle.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); } //绘制蛇尾 auto snakeTail=snakeList.back(); painter.drawPixmap(snakeTail.x(),snakeTail.y(),snakeTail.width(),snakeTail.height(),pix); //绘制食物 pix.load(":/image/Hamburg.png"); painter.drawPixmap(foodRect.x(),foodRect.y(),kSnakeNodeWidth,kSnakeNodeHeight,pix); //将分数绘制到界面 QPen pen; pen.setColor(Qt::black); painter.setPen(pen); QFont font("楷体",15); painter.setFont(font); painter.drawText(430,30,"当前等分:"); painter.drawText(530,30,QString("%1").arg(snakeList.size()-3)); //绘制失败效果 if(checkFail()) { pen.setColor(Qt::red); QFont font("楷体",30); painter.setPen(pen); painter.setFont(font); painter.drawText(100,180,"Game Over"); timer->stop(); sound->stop(); } //将当前分数保存到文件中 int c=snakeList.size()-3; QFile file("C:/Users/86133/Desktop/Qt-tmp.txt"); if(file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&file); int num=c; out<<num; file.close(); } } void GameRoom::moveUp() { QPointF leftTop; QPointF rightBottom; auto snakeHead=snakeList.front(); int headX=snakeHead.x(); int headY=snakeHead.y(); if(headY<20) { leftTop=QPointF(headX,this->height()-kSnakeNodeHeight); } else { leftTop=QPointF(headX,headY-kSnakeNodeHeight); } rightBottom=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight); snakeList.push_front(QRectF(leftTop,rightBottom)); } void GameRoom::moveDown() { QPointF leftTop; QPointF rightBottom; auto snakeHead=snakeList.front(); int headX=snakeHead.x(); int headY=snakeHead.y(); if(headY>this->height()-40) { leftTop=QPointF(headX,0); } else { leftTop=snakeHead.bottomLeft(); } rightBottom=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight); snakeList.push_front(QRectF(leftTop,rightBottom)); } void GameRoom::moveLeft() { QPointF leftTop; QPointF rightBottom; auto snakeHead=snakeList.front(); int headX=snakeHead.x(); int headY=snakeHead.y(); if(headX<20) { leftTop=QPointF(400-kSnakeNodeWidth,headY); } else { leftTop=QPointF(headX-kSnakeNodeWidth,headY); } rightBottom=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight); snakeList.push_front(QRectF(leftTop,rightBottom)); } void GameRoom::moveRight() { QPointF leftTop; QPointF rightBottom; auto snakeHead=snakeList.front(); int headX=snakeHead.x(); int headY=snakeHead.y(); if(headX>360) { leftTop=QPointF(0,headY); } else { leftTop=snakeHead.topRight(); } rightBottom=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight); snakeList.push_front(QRectF(leftTop,rightBottom)); } bool GameRoom::checkFail() { 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 GameRoom::createFood() { foodRect=QRectF(qrand()%(400/kSnakeNodeWidth)*kSnakeNodeWidth, qrand()%(400/kSnakeNodeHeight)*kSnakeNodeHeight,kSnakeNodeWidth,kSnakeNodeHeight); }