贪吃蛇(利用QT)

[复制链接]
发表于 2026-2-13 18:28:04 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一.项目先容

贪吃蛇游戏是⼀款休闲益智类游戏。它通过控制蛇头方向吃食品,从而使得蛇变得越来越长。在本游戏中设置了上下左右四个⽅向键来控制蛇的移动方向。⻝物的产⽣是随机⽣成的,当蛇每吃⼀次⻝物就会增长⼀节身材,同时游戏积分也会相应的加⼀。在本游戏的筹划中,蛇的⾝相识越吃越长,身材越长对应的难度就越⼤,由于⼀旦蛇头和⾝体相交游戏就会竣事。
贪吃蛇项目地点

界面一:游戏大厅


   当用户点击 “开始游戏” 按钮之后,就会进⼊到关卡选择界面。
  界面二:关卡选择界面


在关卡选择界面上设置了三个游戏模式按钮,分别是:简单模式、正常模式、困难模式;⼀个 “汗青战绩” 按钮;⼀个返回游戏大厅界⾯的按钮。
界面三:游戏界面


在游戏界⾯,如果想要开始游戏,⾸先点击 “开始” 按钮,此时蛇就会移动而且尚有配景⾳效。如果想要停息游戏,那么点击 “停息” 按钮即可。当我们在游戏时,可以通过右边控制地区的上下左右⽅向键来控制蛇的移动。当蛇每吃⼀次⻝物时,陪同有吃⻝物的⾳效,蛇⾝会增长⼀节⻓度,而且分数
积分也会相应的加⼀。末了在控制地区的右下⻆结构了⼀个 “退出” 按钮,当点击 “退出” 按钮时,就会有⼀个弹窗提⽰,如下

如果我们点击 “Ok” ,则会退出到游戏关卡选择界⾯,此时我们可以重新选择游戏模式。如果点击“Cancel” ,则不会退出游戏,我们还是处在当前游戏房间界⾯。
二.项目实现

2.1 游戏大厅

游戏大厅界面比力简单, 只有⼀个配景图和⼀个按钮

      
  • 配景图片的渲染,通过QT的绘图变乱完成
  1. void GameHall::paintEvent(QPaintEvent *event)
  2. {
  3.    
  4.    
  5.     //实例化画家对象
  6.      QPainter painter(this);
  7.      //实例化绘图设备
  8.      QPixmap pix(":res/game_hall.png");
  9.      //绘画
  10.      painter.drawPixmap(0,0,this->width(),this->height(),pix);
  11. }
复制代码

      
  • 按钮的相应通过QT的信号槽机制完成
  1. GameHall::GameHall(QWidget *parent)
  2.     : QWidget(parent)
  3.     , ui(new Ui::GameHall)
  4. {
  5.    
  6.    
  7.     ui->setupUi(this);
  8.     this->setFixedSize(1500,1000);//设置窗口大小
  9.     this->setWindowTitle(QString("贪吃蛇游戏"));
  10.     this->setWindowIcon(QIcon(":res/ico.png"));//设置窗口图标
  11.     //
  12.     QFont font("华文行楷",20);
  13.     QPushButton * strbutton = new QPushButton(this);
  14.     strbutton->setText("开始游戏");
  15.     strbutton->setFont(font);
  16.     strbutton->move(650,700);
  17.     strbutton->setShortcut(QKeySequence(Qt::Key_Space));
  18.     strbutton->setStyleSheet("QPushButton{border:0px}");//给按钮设置样式  去除边框
  19.     GameSelect *  gameSelect = new GameSelect;
  20.     connect(strbutton,&QPushButton::clicked,[=](){
  21.    
  22.    
  23.         this->close();//当前窗口关闭
  24.         gameSelect->setGeometry(this->geometry());//设置第二个窗口于当前窗口一致
  25.         gameSelect->show();//新的窗口打开
  26.         QSound::play(":res/clicked.wav");
  27.     });
  28. }
复制代码
  
       
  • 这里的Qfound类,利用必要在.pro 的文件中加上 QT += core gui multimedia   
  • 这里利用strbutton->setShortcut(QKeySequence(Qt::Key_Space));给按钮添加了快捷键   
  • 利用strbutton->setStyleSheet("QPushButton{border:0px}");去除按钮边框样式   
  • 通过槽函数跳转到新的窗口 ,在槽函数中利用了Lambda 表达式
    通过QSound创建音频对象,使点击按钮有声音  
  

2.2关卡选择界面

关卡选择界⾯包罗⼀个配景图和五个按钮,配景图的绘制和游戏⼤厅配景图绘制⼀样,同样利用的是Qt中的绘图变乱,下面依次先容。

      
  • 配景图片的渲染,通过QT的绘图变乱完成
  1. void GameHall::paintEvent(QPaintEvent *event)
  2. {
  3.    
  4.    
  5.     //实例化画家对象
  6.      QPainter painter(this);
  7.      //实例化绘图设备
  8.      QPixmap pix(":res/game_hall.png");
  9.      //绘画
  10.      painter.drawPixmap(0,0,this->width(),this->height(),pix);
  11. }
复制代码

      
  • 按钮的相应通过QT的信号和槽机制完成
  1. #include "gameselect.h"
  2. #include"gameroom.h"
  3. #include<QIcon>
  4. #include<QPushButton>
  5. #include"gamehall.h"
  6. #include<QSound>
  7. #include<QPainter>
  8. GameSelect::GameSelect(QWidget *parent) : QWidget(parent)
  9. {
  10.    
  11.    
  12.     this->setFixedSize(1500,1000);//设置窗口大小
  13.     this->setWindowIcon(QIcon(":res/ico.png"));
  14.     this->setWindowTitle("游戏关卡选择");
  15.     QPushButton* backBtn = new QPushButton(this);//返回按钮
  16.     backBtn->move(1400,900);
  17.     backBtn->setIcon(QIcon(":res/back.png"));
  18.     backBtn->setShortcut(QKeySequence(Qt::Key_Escape));
  19.     connect(backBtn,&QPushButton::clicked,[=](){
  20.    
  21.    
  22.          this->close();
  23.         GameHall * gameHall = new GameHall;
  24.         gameHall->show();
  25.         QSound::play(":res/clicked.wav");
  26.     });
  27.     QFont font("华文行楷",20);
  28.     gameroom*gameRoom = new gameroom;
  29.     QPushButton* simpleBtn = new QPushButton(this);
  30.     simpleBtn->move(650,300);
  31.     simpleBtn->setFont(font);
  32.     simpleBtn->setText("简单模式");
  33.     connect(simpleBtn,&QPushButton::clicked,[=](){
  34.    
  35.    
  36.         this->close();
  37.         gameRoom->setGeometry(this->geometry());
  38.         gameRoom->show();
  39.     });
  40.     QPushButton*normalBtn = new QPushButton(this);
  41.     normalBtn->move(650,400);
  42.     normalBtn->setFont(font);
  43.     normalBtn->setText("正常模式");
  44.     connect(normalBtn,&QPushButton::clicked,[=](){
  45.    
  46.    
  47.         this->close();
  48.         gameRoom->setGeometry(this->geometry());
  49.         gameRoom->show();
  50.     });
  51.     QPushButton*hardBtn = new QPushButton(this);
  52.     hardBtn->move(650,500);
  53.     hardBtn->setFont(font);
  54.     hardBtn->setText("困难模式");
  55.     connect(hardBtn,&QPushButton::clicked,[=]{
  56.    
  57.    
  58.         this->close();
  59.         gameRoom->setGeometry(this->geometry());
  60.         gameRoom->show();
  61.     });
  62.     QPushButton*hisBtn = new QPushButton(this);
  63.     hisBtn->move(650,600);
  64.     hisBtn->setFont(font);
  65.     hisBtn->setText("历史战绩");
  66. }
  67. void GameSelect::paintEvent(QPaintEvent *event)
  68. {
  69.    
  70.    
  71.     QPainter painter(this);//实例化画家对象
  72.     QPixmap pix(":res/game_select.png");
  73.     painter.drawPixmap(0,0,this->width(),this->height(),pix);
  74. }
复制代码
   connect(hardBtn,&QPushButton::clicked,[=]{ this->close(); gameRoom->setGeometry(this->geometry()); gameRoom->show(); });
通过关联信号槽,使得可以选择游戏模式,起首把当前窗口关闭,然后体现新的窗口,在设置与当前窗口的巨细一样
  2.3 游戏房间

游戏房间界面包罗下面几个部分:

      
  • 配景的绘制  
  • 蛇的绘制,蛇的移动,判定蛇是否会撞到自己  
  • 积分的累加和绘制
   怎么让蛇动起来?
  
       
  • 我们可以⽤⼀个链表表现贪吃蛇,⼀个小方块表现蛇的⼀个节点, 我们设置蛇的默认⻓度为3;   
  • 向上移动的逻辑就是在蛇的上方加⼊⼀个小方块, 然后把末了⼀个小⽅块删除即可   
  • 必要用到定时器Qtimer 每100 - 200ms 重新渲染  
  怎么判定蛇有没有吃到食品?
  
       
  • 判定蛇头和食品的坐标是否相交,  
  怎么控制蛇的移动?
  
       
  • 借助QT的实践机制实现, 重写keyPressEvent即可, 在函数中监控监控想要的键盘变乱即可   
  • 通过绘制四个按钮,使⽤信号和槽的机制控制蛇的上、下、左、右移动方向  
  2.3.1 封装贪吃蛇数据结构

  1. #ifndef GAMEROOM_H
  2. #define GAMEROOM_H
  3. #include <QWidget>
  4. #include<QSound>
  5. enum class SnakeDirect
  6. {
  7.    
  8.    
  9.     UP=0,
  10.     DOWN,
  11.     LEFT,
  12.     RIGHT
  13. };
  14. class gameroom : public QWidget
  15. {
  16.    
  17.    
  18.     Q_OBJECT
  19. public:
  20.     explicit gameroom(QWidget *parent = nullptr);
  21.     //重写绘图事件
  22.     void paintEvent(QPaintEvent *event);
  23.     void moveUp();
  24.     void moveDown();
  25.     void moveLeft();
  26.     void moveRight();
  27.     bool checkFail();
  28.     void createNewFood();
  29.     void  setTimeout(int timeout){
  30.    
  31.    moveTime=timeout;}
  32. private:
  33.     const int KSnakeNodeWidth = 20;
  34.     const int KSnakeNodeHeight = 20;
  35.     const int KDefaultTimeout = 200;//移动速度
  36.     QList<QRectF> snakeList;//表示链表
  37.     QRectF foodRect;//食物
  38.     SnakeDirect  moveDirect = SnakeDirect::UP;//默认移动方向
  39.     QTimer *timer;//定时器
  40.     bool  isGameStart = false;//游戏的开始
  41.     QSound *sound;
  42.     int moveTime = KDefaultTimeout;
  43. };
  44. #endif // GAMEROOM_H
复制代码
2.3.2 初始化游戏房间界面

设置窗口巨细、标题、图标等
  1. gameroom::gameroom(QWidget *parent) : QWidget(parent)
  2. {
  3.    
  4.    
  5.     this->setFixedSize(1500,1000);
  6.     this->setWindowIcon(QIcon(":res/ico.png"));
  7.     this->setWindowTitle("游戏房间");
  8. }
复制代码
2.3.3 蛇的移动

蛇的移动方向为:上、下、左、右。通过在游戏房间中结构四个按钮来控制蛇的移动方向。
· 留意: 这里贪吃蛇不答应直接掉头, 比如当前是向上的, 不能直接修改为向下。
  1. QPushButton*up= new QPushButton(this);
  2.     QPushButton*down= new QPushButton(this);
  3.     QPushButton*left= new QPushButton(this);
  4.     QPushButton*right= new QPushButton(this);
  5.     up->move(1320,750);
  6.     down->move(1320,900);
  7.     left->move(1220,825);
  8.     right->move(1420,825);
  9.     up->setText("↑");
  10. //    up->setShortcut(QKeySequence(Qt::Key_W));
  11.     down->setText("↓");
  12. //    down->setShortcut(QKeySequence(Qt::Key_S));
  13.     left->setText("←");
  14. //    left->setShortcut(QKeySequence(Qt::Key_A));
  15.     right->setText("→");
  16. //    left->setShortcut(QKeySequence(Qt::Key_D));
  17.     up->setStyleSheet("QPushButton{border:0px}");
  18.     down->setStyleSheet("QPushButton{border:0px}");
  19.     left->setStyleSheet("QPushButton{border:0px}");
  20.     right->setStyleSheet("QPushButton{border:0px}");
  21.     QFont ft("宋体",36);
  22.     up->setFont(ft);
  23.     down->setFont(ft);
  24.     right->setFont(ft);
  25.     left->setFont(ft);
  26.     connect(up,&QPushButton::clicked,[=](){
  27.    
  28.    
  29.         if(moveDirect!= SnakeDirect::DOWN)
  30.         {
  31.    
  32.    
  33.             moveDirect = SnakeDirect::UP;
  34.         }
  35.     });
  36.     connect(down,&QPushButton::clicked,[=](){
  37.    
  38.    <
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表