在好例子网,分享、交流、成长!
您当前所在位置:首页C/C++ 开发实例C/C++游戏开发 → QT 贪吃蛇 小游戏源码

QT 贪吃蛇 小游戏源码

C/C++游戏开发

下载此实例
  • 开发语言:C/C++
  • 实例大小:12.42M
  • 下载次数:94
  • 浏览次数:800
  • 发布时间:2019-03-28
  • 实例类别:C/C++游戏开发
  • 发 布 人:crazycode
  • 文件格式:.rar
  • 所需积分:2
 相关标签: 游戏 贪吃蛇 源码 小游戏 t

实例介绍

【实例简介】请注意 程序下载后 改个目录名,程序所在目录不能有汉字)

【实例截图】

from clipboard


from clipboard

【核心代码】

#include "mywidget.h"
#include "ui_mywidget.h"
#include <QPainter>
#include <Qpen>
#include <QBrush>
#include <QDebug>
#include <QKeyEvent>//键盘事件
#include <QMediaPlayer>
#include <QString>

//全局宏定义
#define Bsize 20//格子的尺寸(像素)
#define startX 50//地图起始x坐标
#define startY 75//地图起始y坐标
#define Cwidth 500//地图宽500px
#define Cheight 420//地图高420px
#define W 25//宽25格
#define H 21//高21格
#define appleW 19//苹果宽19px
#define appleH 22//苹果高22px
#define snakeLen 4//初始蛇长度
#define snakeSpeed 1//蛇速,待定
#define s_up 1
#define s_down 2
#define s_left 3
#define s_right 4//枚举类不知道怎么用,暂时用1、2、3、4代表上下左右,初始向右吧

//全局变量声明
int appleX, appleY;//苹果格子坐标
int posAppleX, posAppleY;//苹果像素坐标
int headX, headY;//蛇头坐标
int score = 0;
QString strScore;
bool isEated = false;//是否吃到了?
bool crashed = false;//是否撞墙或者撞到自己
bool gamePause = false;//游戏是否暂停
bool bg = true;
bool bgm = true;
bool gameStart = false;//需要点击开始才可以玩耍
char op = 'o';//获取操作指令
int Smap[W][H];//地图尺寸,值为信息标记
int direction = s_right;
int Sround = 1;//第一关
int gameStartClickCount = 0;
QMediaPlayer *player = new QMediaPlayer;
QMediaPlayer *player_gg = new QMediaPlayer;
QMediaPlayer *player_eat = new QMediaPlayer;

//这里写全局函数声明
void init();
void createApple();
void goUp();
void goDown();
void goLeft();
void goRight();
void autoRun();
void setRound();//设置关卡
void snakeInit();//初始化蛇身

//类不会用,用结构体实现
struct Point {
    int xvar;
    int yvar;
public:
    Point() {}
    ~Point() {}
    Point(int x, int y) :xvar(x), yvar(y) {}
    int x()const { return xvar; }
    int y()const { return yvar; }
};
struct Snake {//蛇类
    int length = snakeLen;
    int speed = snakeSpeed;
    int direction = s_right;
public:
    Snake() {}
    ~Snake() {}
    int len()const { return length; }
    int sp()const { return speed; }
    int Direction() const {return direction; }
    //std::vector<Point> snakeBody{ Point(3,3),Point(3,4),Point(3,5),Point(3,6) };//蛇身
    std::vector<Point> snakeBody;//蛇身

};
Snake s;

myWidget::myWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::myWidget)
{
    ui->setupUi(this);
    setWindowTitle("贪吃蛇小游戏");
    setWindowIcon(QIcon("../image/apple1.png"));//设置窗口图标
    init();
    qDebug() << s.snakeBody.size();
    timerId = this->startTimer(500);//毫秒为单位,一个叫做timerId的定时器


    connect(player, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64)));
    player->setMedia(QUrl::fromLocalFile("../image/bgm2.mp3"));//游戏背景音乐
    player->setVolume(30);
    player->play();

    connect(player_gg, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64)));
    player_gg->setMedia(QUrl::fromLocalFile("../image/gg.mp3"));//GameOver的声音
    player_gg->setVolume(80);

    connect(player_eat, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64)));
    player_eat->setMedia(QUrl::fromLocalFile("../image/eated.mp3"));//吃到东西的声音
    player_eat->setVolume(80);
}

myWidget::~myWidget()
{
    delete ui;
}

void myWidget::timerEvent(QTimerEvent *e){//定时器
    if(e->timerId() == timerId && gamePause){
        if(direction == s_right){
            goRight();
        }else if(direction == s_up){
            goUp();
        }else if(direction == s_down){
            goDown();
        }else if(direction == s_left){
            goLeft();
        }
        //qDebug()<<score;
        if(isEated){
            strScore = QString::number(score);
            ui->label->setText(strScore);
        }
        update();

        if(crashed){
            player->stop();
            player_gg->play();
            Sleep(1000);
            //MessageBox(0, TEXT("不要灰心!继续游戏??"), TEXT("Sorry,defeat!!"), 0);//游戏结束时
            gamePause = !gamePause;
            init();
            strScore = QString::number(score);
            ui->label->setText(strScore);
        }
    }
}

void myWidget::keyPressEvent(QKeyEvent *e){//键盘事件监听
   // qDebug()<<(char)e->key();
    if(gameStart){//游戏开始时才可以手动
        if(e->key() == Qt::Key_W){
            if(direction == s_down) return;//不做处理
            direction = s_up;
            //if(e->isAutoRepeat())//重复按下再快跑会有迟钝效果。。
            goUp();
            if(isEated)
                createApple();//随机产生苹果位置
        }else if(e->key() == Qt::Key_S){
            if(direction == s_up) return;//不做处理
            direction = s_down;
            goDown();
            if(isEated)
                createApple();//随机产生苹果位置
        }else if(e->key() == Qt::Key_A){
            if(direction == s_right) return;//不做处理
            direction = s_left;
            goLeft();
            if(isEated)
                createApple();//随机产生苹果位置
        }else if(e->key() == Qt::Key_D){
            if(direction == s_left) return;//不做处理
            direction = s_right;
            goRight();
            if(isEated)
                createApple();//随机产生苹果位置
        }

        strScore = QString::number(score);
        ui->label->setText(strScore);

        update();
    }

}


void myWidget::paintEvent(QPaintEvent *)
{
    //QPainter p(this);
    QPainter p;//创建画家对象
    p.begin(this);//指定当前窗口为绘图设备
    //绘图操作
    //p.drawPixmap(0,0,width(),height(),QPixmap("../image/bg.jpg"));//背景图
    if(bg)
        p.drawPixmap(rect(),QPixmap("../image/bg.jpg"));//背景图
    else{
        p.drawPixmap(rect(),QPixmap("../image/bg.png"));//背景图
    }

    //定义画笔
    QPen pen;
    pen.setWidth(6);
    pen.setColor(RGB(60,60,60));
    p.setPen(pen);//把画笔交给画家

   // p.drawRect(startX,startY,Cwidth,Cheight);//画出游戏边界

    for(int i=-1;i<=W;i  ){//画出游戏边界
        p.drawPixmap(i*Bsize startX,-1*Bsize startY,Bsize,Bsize,QPixmap("../image/shitou.png"));
        p.drawPixmap(i*Bsize startX,21*Bsize startY,Bsize,Bsize,QPixmap("../image/shitou.png"));
    }
    for(int j=0;j<H;j  ){//画出游戏边界
        p.drawPixmap(-1*Bsize startX,j*Bsize startY,Bsize,Bsize,QPixmap("../image/shitou.png"));
        p.drawPixmap(25*Bsize startX,j*Bsize startY,Bsize,Bsize,QPixmap("../image/shitou.png"));
    }

    if(Sround == 1){//画出第一关障碍物
        for(int i=4;i<=8;i  ){
            p.drawPixmap(6*Bsize startX,i*Bsize startY,Bsize,Bsize,QPixmap("../image/wall.png"));
            p.drawPixmap(18*Bsize startX,i*Bsize startY,Bsize,Bsize,QPixmap("../image/wall.png"));
        }
        for(int i=11;i<=15;i  ){
            p.drawPixmap(6*Bsize startX,i*Bsize startY,Bsize,Bsize,QPixmap("../image/wall.png"));
            p.drawPixmap(18*Bsize startX,i*Bsize startY,Bsize,Bsize,QPixmap("../image/wall.png"));
        }
        for(int i=7;i<=10;i  ){
            p.drawPixmap(i*Bsize startX,4*Bsize startY,Bsize,Bsize,QPixmap("../image/wall.png"));
            p.drawPixmap(i*Bsize startX,15*Bsize startY,Bsize,Bsize,QPixmap("../image/wall.png"));
        }
        for(int i=14;i<=17;i  ){
            p.drawPixmap(i*Bsize startX,4*Bsize startY,Bsize,Bsize,QPixmap("../image/wall.png"));
            p.drawPixmap(i*Bsize startX,15*Bsize startY,Bsize,Bsize,QPixmap("../image/wall.png"));
        }
    }

    /*pen.setWidth(1);//重新设置画笔宽度
    p.setPen(pen);//把画笔交给画家
    for(int i=startX,j=startY;j<startY Cheight;j =Bsize){//画格子辅助线
       p.drawLine(i,j,i Cwidth,j);
    }
    for(int i=startX,j=startY;i<startX Cwidth;i =Bsize){
        p.drawLine(i,j,i,j Cheight);
    }*/

    strScore = QString::number(score);//刷新分数
    ui->label->setText(strScore);

    if(appleX%2==0)//画苹果
        p.drawPixmap(posAppleX,posAppleY-2,appleW,appleH,QPixmap("../image/apple1.png"));
    else//画月饼
        p.drawPixmap(posAppleX,posAppleY,Bsize,Bsize,QPixmap("../image/shead.png"));
    if(isEated){
        createApple();//随机产生苹果位置
        update();
    }

    for(std::vector<Point>::iterator it=s.snakeBody.begin();it!=s.snakeBody.end();it  ){//遍历蛇身,画蛇
        Smap[(*it).x()][(*it).y()] = 1;
        if(it == s.snakeBody.end()-1){//vector数组尾作为蛇头,红点
            headX = (*it).x();//蛇头坐标
            headY = (*it).y();//蛇头坐标
            int posHeadX = headX*Bsize startX;//蛇头像素位置
            int posHeadY = headY*Bsize startY;//蛇头像素位置
            if(direction == s_up){
                p.drawPixmap(posHeadX-10,posHeadY-15,2*Bsize,2*Bsize,QPixmap("../image/shead_up.png"));
            }else if(direction == s_down){
                p.drawPixmap(posHeadX-10,posHeadY-5,2*Bsize,2*Bsize,QPixmap("../image/shead_down.png"));
            }else if(direction == s_left){
                p.drawPixmap(posHeadX-15,posHeadY-10,2*Bsize,2*Bsize,QPixmap("../image/shead_left.png"));
            }else if(direction == s_right){
                p.drawPixmap(posHeadX-5,posHeadY-10,2*Bsize,2*Bsize,QPixmap("../image/shead_right.png"));
            }
        }else{//蛇身黑点
            int xx=(*it).x()*Bsize startX;
            int yy=(*it).y()*Bsize startY;
            p.drawPixmap(xx,yy,Bsize,Bsize,QPixmap("../image/snake1.png"));
        }
        if (headX == appleX && headY == appleY){//吃到了!
            isEated = true;
        }
    }


    p.end();
}


void init() {//每次游戏开始的数据初始化
    for (int i = 0; i < W; i  )
        for (int j = 0; j < H; j  )
                Smap[i][j] = 0;
    s.snakeBody.clear();
    direction = s_right;
    crashed = false;
    gameStart = false;
    score = 0;
    gameStartClickCount = 0;
    snakeInit();//初始化蛇身
    setRound();//设置第几关
    createApple();//随机产生苹果位置
}
void createApple() {//随机产生苹果位置
    if (isEated){
        player_eat->play();//吃到音效
        score  = 10;
    }
    while (true) {
        srand((int)time(NULL));
        int row = rand() % 21;//产生0~24的随机数
        int col = rand() % 25;
        if (Smap[col][row] == 0) {
            //Smap[row][col] = 1;
            appleX = col;
            appleY = row;
            posAppleX = appleX*Bsize startX;//像素位置与坐标转换
            posAppleY = appleY*Bsize startY;
            break;
        }
    }
    isEated = false;//刚产生的苹果吃不到!
}
void goUp() {    //五种情况①撞墙;②撞苹果;③撞自己;④都不撞;⑤撞障碍物
    direction = s_up;
    if (!((headX == appleX) && (headY - 1 == appleY)) && (headY - 1 >= 0) && (Smap[headX][headY - 1] == 0)) {//都不撞(头插一点,尾删一点)
        s.snakeBody.push_back(Point(headX, headY - 1));//头插一点
        //Smap[headX][headY - 1] = 1;
        std::vector<Point>::iterator it = s.snakeBody.begin();//找到第一个点(尾部)
        Smap[(*it).x()][(*it).y()] = 0;
        s.snakeBody.erase(it);//尾删一点
    }
    else if ((headX == appleX) && (headY - 1 == appleY)) {//撞苹果,吃到(头插一点,尾不删)
        s.snakeBody.push_back(Point(headX, headY - 1));//头插一点
        //Smap[headX][headY - 1] = 1;
        isEated = true;
    }else if(Smap[headX][headY - 1]==1){
        crashed = true;
        return;
    }
    else if (headY - 1 < 0) {//不是撞苹果->撞墙:GameOver
        crashed = true;
        return;
    }
    else{//撞自己
        crashed = true;
        return;
    }
}
void goDown() {    //五种情况①撞墙;②撞苹果;③撞自己;④都不撞
    direction = s_down;
    if (!((headX == appleX) && (headY   1 == appleY)) && (headY   1 < H) && (Smap[headX][headY   1] == 0)) {//都不撞(头插一点,尾删一点)
        s.snakeBody.push_back(Point(headX, headY   1));//头插一点
        //Smap[headX][headY   1] = 1;
        std::vector<Point>::iterator it = s.snakeBody.begin();//找到第一个点(尾部)
        Smap[(*it).x()][(*it).y()] = 0;
        s.snakeBody.erase(it);//尾删一点
    }
    else if ((headX == appleX) && (headY   1 == appleY)) {//撞苹果,吃到(头插一点,尾不删)
        s.snakeBody.push_back(Point(headX, headY   1));//头插一点
        //Smap[headX][headY   1] = 1;
        isEated = true;
    }
    else if(Smap[headX][headY - 1]==1){
            crashed = true;
            return;
    }
    else if (headY   1 >= H) {//撞墙:GameOver
        crashed = true;
        return;
    }
    else{//撞自己
        crashed = true;
        return;
    }
}
void goLeft() {    //五种情况①撞墙;②撞苹果;③撞自己;④都不撞; ⑤撞障碍物
    direction = s_left;
    if (!((headX - 1 == appleX) && (headY == appleY)) && (headX - 1 >= 0) && (Smap[headX - 1][headY] == 0)) {//都不撞(头插一点,尾删一点)
        s.snakeBody.push_back(Point(headX - 1, headY));//头插一点
        //Smap[headX - 1][headY] = 1;
        std::vector<Point>::iterator it = s.snakeBody.begin();//找到第一个点(尾部)
        Smap[(*it).x()][(*it).y()] = 0;
        s.snakeBody.erase(it);//尾删一点
    }
    else if ((headX - 1 == appleX) && (headY == appleY)) {//撞苹果,吃到(头插一点,尾不删)
        s.snakeBody.push_back(Point(headX - 1, headY));//头插一点
        //Smap[headX - 1][headY] = 1;
        isEated = true;
    }
    else if(Smap[headX - 1][headY]==1){
        crashed = true;
        return;
    }
    else if (headX - 1 < 0) {//撞墙:GameOver
        crashed = true;
        return;
    }
    else{//撞自己
        crashed = true;
        return;
    }
}
void goRight() {    //五种情况①撞墙;②撞苹果;③撞自己;④都不撞; ⑤撞障碍物
    direction = s_right;
    if (!((headX   1 == appleX) && (headY == appleY)) && (headX   1 < W) && (Smap[headX   1][headY] == 0)) {//都不撞(头插一点,尾删一点)
        s.snakeBody.push_back(Point(headX   1, headY));//头插一点
        //Smap[headX   1][headY] = 1;
        std::vector<Point>::iterator it = s.snakeBody.begin();//找到第一个点(尾部)
        Smap[(*it).x()][(*it).y()] = 0;
        s.snakeBody.erase(it);//尾删一点
    }
    else if ((headX   1 == appleX) && (headY == appleY)) {//撞苹果,吃到(头插一点,尾不删)
        s.snakeBody.push_back(Point(headX   1, headY));//头插一点
        //Smap[headX   1][headY] = 1;
        isEated = true;
    }
    else if(Smap[headX][headY - 1]==1){
            crashed = true;
            return;
    }
    else if (headX   1 >= W) {//撞墙:GameOver
        crashed = true;
        return;
    }
    else{//撞自己
        crashed = true;
        return;
    }
}

//槽函数
void myWidget::on_pushButton_clicked()
{
    gameStart = true;
    player->play();
    gameStartClickCount  ;
    if(gameStartClickCount<2)//每次游戏开始按钮只有第一次生效,避免和暂停按钮发生冲突
        gamePause = true;
    update();
}

void myWidget::on_pushButton_2_clicked()
{
    if(gameStartClickCount){//大于1生效,避免和开始按钮发生冲突
        gamePause = !gamePause;//取反实现toggle开关
        if(gamePause){
            ui->pushButton_2->setText("暂停");
        }else{
            ui->pushButton_2->setText("继续");
        }
        update();
    }
}
void snakeInit(){
    s.snakeBody.push_back(Point(3,2));
    s.snakeBody.push_back(Point(4,2));
    s.snakeBody.push_back(Point(5,2));
    s.snakeBody.push_back(Point(6,2));//初始化蛇身从左上角出发
    Smap[3][2] = 1,Smap[4][2] = 1,Smap[5][2] = 1,Smap[6][2] = 1;
}

void setRound(){//设置关卡
    if(score>=500){//满500分进入下一关
        Sround  ;
        //message:恭喜进入下一关
    }
    if(Sround == 1){
        Smap[6][4]=Smap[6][5]=Smap[6][6]=Smap[6][7]=Smap[6][8]=1;
        Smap[6][11]=Smap[6][12]=Smap[6][13]=Smap[6][14]=Smap[6][15]=1;
        Smap[18][4]=Smap[18][5]=Smap[18][6]=Smap[18][7]=Smap[18][8]=1;
        Smap[18][11]=Smap[18][12]=Smap[18][13]=Smap[18][14]=Smap[18][15]=1;

        Smap[7][4]=Smap[8][4]=Smap[9][4]=Smap[10][4]=1;
        Smap[14][4]=Smap[15][4]=Smap[16][4]=Smap[17][4]=1;
        Smap[7][15]=Smap[8][15]=Smap[9][15]=Smap[10][15]=1;
        Smap[14][15]=Smap[15][15]=Smap[16][15]=Smap[17][15]=1;
    }else if(Sround == 2){
        //第二关待定
    }
}


void myWidget::on_pushButton_4_clicked()
{
    bg=!bg;//背景切换
    update();
}

void myWidget::on_pushButton_5_clicked()
{
    if(bgm){
        player->stop();
    }else{
        player->play();
    }
    bgm = !bgm;
}

实例下载地址

QT 贪吃蛇 小游戏源码

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警