QT实现贪吃蛇游戏代码详解

目录
  • 一、新建一个Qt项目
  • 二、添加要用到的头文件
  • 三、写类声明信息
  • 四、对类函数的实现
    • 构造函数
    • 界面刷新
    • 随机奖励的生成
    • 移动
    • 绘图
    • 按键事件
    • 判断蛇身是否相撞
  • 五、结束

一、新建一个Qt项目

新建Qt Widgets Application,项目名称为HappySnake,基类选择QWidget,类名默认

二、添加要用到的头文件

#include <QKeyEvent>
#include <QRectF>
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QDebug>
#include <QTimer>
#include <QTime>

三、写类声明信息

  • 贪吃蛇的本体使用小方框来代替
  • 使用QList类来保存贪吃蛇的本体
  • 使用定时器来设定刷新的时间
  • 使用随机函数生成奖励的节点
  • 使用paintEvent来进行绘图
  • keyPressEvent来监测按键的按下,控制贪吃蛇的移动
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;//奖励节点

};

四、对类函数的实现

构造函数

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    resize(480,500);
    //设置窗体背景色为黑色
    setStyleSheet("QWidget{background:black}");
    setWindowOpacity(0.8);//设置窗口的透明度

    snake.append(QRectF(200,500,snakeNodeWidth,snakeNodeHeight));
    addTopRectF();
    addTopRectF();
    //首先生成一个奖励节点
    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)));
    }
}
//删除结尾数据
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();
            //首先生成一个奖励节点
            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;

}

五、结束

实现的效果:

总结:

只是简单的使用了paintevent进行绘图,基本都是简单的对Qt的一些常用类的使用,对面向对象的编程应用的不是很好,更偏向于面向过程,所以完全可以改成C语言在Linux下实现,思路都是相同的。

到此这篇关于QT实现贪吃蛇游戏代码详解的文章就介绍到这了,更多相关QT内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++的QT项目打包成独立可执行和发布的exe文件(项目构建过程)

    目录 一.通过release方式构建项目 二.使用windeployqt工具添加依赖项 三.使用Enigma Virtual Box打包 四.附一个修改软件图标的简易方法 以Demo项目为例,使用Qt creator构建,使用Enigma Virtual Box打包 一.通过release方式构建项目 构建套件中选择release选项后,重新run一遍项目 即可在原项目目录下找到构建项目的文件夹 进入release文件夹就可以看到exe文件,这个就是代码打包出来的文件,但是缺少QT对应的依赖,所

  • Qt实现炫酷启动图动态进度条效果

    目录 一.简述 二.动效进度条 1.光效进度条 2.延迟到达进度条 3.接口说明 三.启动图 1.实现思路 2.背景图切换 四.测试 1.构造启动图 2.背景图 3.其他信息 4.事件循环 五.源码 一.简述 最近接到一个新需求,让做一个动效进度条. 由于我们的产品比较大,在软件启动的时候会消耗比较长的时间,原生的进度条已经不能满足我们的需求,这里我们就需要一个会动的进度条,效果如下图所示. 光效进度条主要是做了一个进度动画,在已完成的部分上进行快速的迭代渲染,给用户一种直观感受,我们的软件一直

  • C语言实现贪吃蛇游戏演示

    本文实例为大家分享了C语言实现贪吃蛇游戏的具体代码,供大家参考,具体内容如下 IDE用的是 VS2019 先看效果 代码全览 game.h #pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <time.h> #define PLATFORM 1 //运行的系统 1为win 0为lin

  • 利用C/C++实现贪吃蛇游戏

    利用C/C++实现贪吃蛇 (注意:本文章仅供参考,第一次写博客还请多多指教.理解本文章需要easyx和c++等基础知识,并且需要了解贪吃蛇游戏机制) 贪吃蛇机制介绍 相信绝大多数人都曾玩过或者了解过贪吃蛇这款经典的游戏.贪吃蛇顾名思义,就是让蛇尽可能的吃食物.玩家可通过方向键或自定义键来控制蛇头的方向,使它吃到地图出现的随机食物.蛇每吃到一个食物,自身便会增长.当蛇碰到地图的边界或是蛇碰到自身,蛇便会死亡,游戏便结束. 机制大概了解过后,我们将考虑如何实现这类游戏. 设计与分析 首先,我们分析游

  • QT实现贪吃蛇游戏代码详解

    目录 一.新建一个Qt项目 二.添加要用到的头文件 三.写类声明信息 四.对类函数的实现 构造函数 界面刷新 随机奖励的生成 移动 绘图 按键事件 判断蛇身是否相撞 五.结束 一.新建一个Qt项目 新建Qt Widgets Application,项目名称为HappySnake,基类选择QWidget,类名默认 二.添加要用到的头文件 #include <QKeyEvent> #include <QRectF> #include <QPainter> #include

  • JS实现的贪吃蛇游戏案例详解

    本文实例讲述了JS实现的贪吃蛇游戏.分享给大家供大家参考,具体如下: github项目地址:https://github.com/LEERTRT/Snake 在<script></script>中,文档加载完毕后调用: $(function () { var game = new Game("canvas"); game.init(); }); 其中构造函数Game()接收canvas的id作为参数,实例化对象以后,调用init()函数,init()函数里面有三

  • python贪吃蛇游戏代码

    本文实例为大家分享了python贪吃蛇游戏的具体代码,供大家参考,具体内容如下 贪吃蛇游戏截图: 首先安装pygame,可以使用pip安装pygame: pip install pygame 运行以下代码即可: #!/usr/bin/env python import pygame,sys,time,random from pygame.locals import * # 定义颜色变量 redColour = pygame.Color(255,0,0) blackColour = pygame.

  • java实现贪吃蛇游戏代码(附完整源码)

    先给大家分享源码,喜欢的朋友点此处下载. 游戏界面 GUI界面 java实现贪吃蛇游戏需要创建一个桌面窗口出来,此时就需要使用java中的swing控件 创建一个新窗口 JFrame frame = new JFrame("贪吃蛇游戏"); //设置大小 frame.setBounds(10, 10, 900, 720); 向窗口中添加控件 可以直接用add方法往窗口中添加控件 这里我创建GamePanel类继承自Panel,最后使用add方法添加GamePanel 加载图片 图片加载

  • QT实现贪吃蛇游戏

    为了熟悉QT的相关知识,我用了大约8个小时的时间用QT再次写了一遍贪吃蛇. 因为QT的机制和平时写的程序流程不同,所以程序中可能没有遵守代码规范. 运行效果: 程序内除了实现贪吃蛇的基本功能外,还添加了记录得分.调节游戏速度.重新开始游戏等功能. 游戏内容使用QPainter类进行绘制. 编译环境: Windows Qt 5.9.0 Qt Creator 4.3.0 思路: 数组存储蛇节点坐标的贪吃蛇游戏思路. 因为编写过程中使用了分文件编写,且QT框架的其他部分较多,这里仅展示程序实现主要代码

  • C语言实现贪吃蛇游戏代码

    本文实例为大家分享了C语言实现贪吃蛇游戏的具体代码,供大家参考,具体内容如下 //------------------------------------------problm区------------------------------ //①思考typedef 定义的变量如何利用fwrite进行存储 //②典型可利用sleep()语句类实现控制移动速度 //③BOOL PlaySoundW(LPCWSTR, HMODULE, DWORD)": 无法将参数 1 从"const ch

  • 基于C语言实现的贪吃蛇游戏完整实例代码

    本文以实例的形式讲述了基于C语言实现的贪吃蛇游戏代码,这是一个比较常见的游戏,代码备有比较详细的注释,对于读者理解有一定的帮助. 贪吃蛇完整实现代码如下: #include <graphics.h> #include <conio.h> #include <stdlib.h> #include <dos.h> #define NULL 0 #define UP 18432 #define DOWN 20480 #define LEFT 19200 #defi

  • 用纯C语言实现贪吃蛇游戏

    本文实例为大家分享了C语言实现贪吃蛇游戏的具体代码,供大家参考,具体内容如下 在读大学生一枚,五一期间用四天时间写一个小游戏. 本贪吃蛇游戏代码共计531行,开发环境是VS,游戏分为两种模式,标准模式和超大地图模式,详细看以下源代码,并进入游戏体验具体内容. //贪吃蛇 #include<stdio.h> #include<windows.h> #include<time.h> #include<conio.h> //游戏窗口 #define FrameX

  • Java使用GUI实现贪吃蛇游戏详解

    最近在学GUI,然后又有读者希望我写一下相关的实战.刚好我又在B站上找到了一个关于GUI的学习视频,然后里面又刚好有这个实战,我便写了下来.注:代码来源为B站的一个up主:狂神. 游戏主启动类: import javax.swing.*; //游戏主启动类 public class startGame { public static void main(String[] args) { JFrame frame=new JFrame(); frame.setBounds(10,10,900,72

  • java贪吃蛇游戏编写代码

    本文实例为大家分享了java贪吃蛇游戏展示的具体代码,供大家参考,具体内容如下 1.采用MVC(model.view.control)框架模式 2.包和类的关系树形图为: 3.源码: package com.huai; import Java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.util.HashSet; import java.util.LinkedList; import java.u

随机推荐