栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > C/C++/C#

QT个人项目

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

QT个人项目

目录

贪吃蛇游戏设计思路

具体操作

训练模式

闯关模式

具体代码

main(主函数)

interface.cpp(登录、注册)

interface.h

widget.cpp(训练模式)

widget.h

confirm.cpp(挑战模式)

confirm.h

snake_class.cpp(具体功能)

snake_class.h

总结


贪吃蛇游戏设计思路


整个工程共4个类,各自在不同阶段发挥作用。
1、首先main函数先实例化 interface类,这个类的功能是通过用户输入(注册或登录)进入闯关模式类,或者直接进入训练模式类。
2、两种模式可以分别实例化snake类,并通过snake提供的接口函数实例为该模式的特定对象。同时可以使用信号与槽实现交互。
​

具体操作

meeting_02






进入游戏,可以选择登录注册,进入闯关模式。或者直接进入训练模式。

训练模式



可以根据自己的实力,输入数据改变游戏难度。
界面长度:蛇移动的范围,数值越小范围越小。
界面宽度:蛇移动的范围,数值越小范围越小。
格子边长:数值越大,格子越大。单步步长越大。
蛇移动速度:数值越大,移动越快。
​
注意:必须所有格子都填上数据,才能成功。

闯关模式

分数到达一定数值后会提醒进入下一关,同时格子会自动变大,蛇的移动速度会加快。
同样失败后,会提示游戏失败,再重新开始挑战。

具体代码

main(主函数)
#include "interface.h"
#include 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
​
    interface m;
    m.show();
    return a.exec();
}
​

interface.cpp(登录、注册)
#include "interface.h"
#include
interface::interface(QWidget *parent) : QWidget(parent)
{
    max= new QLabel;
    max->setParent(this);
    QMovie *m = new QMovie(":/xh.gif");
    max->setMovie(m);
    m->start();//开始播放背景标签
​
    QFont ft;
    ft.setPointSize(17);
    this->setMinimumSize(533,300);
    this->setMaximumSize(533,300);
    te1 = new  QLabel   ;
    le1 = new  QLineEdit   ;
    te1->setFont(ft);
    le1->setFont(ft);
    te1->setText("账号");
    le1->setPlaceholderText("账号:");
​
    te1->setGeometry(135,110,50,30);
    le1->setGeometry(185,110,200,30);
    te1->setParent(this);
    le1->setParent(this);
​
    te2 = new  QLabel   ;
    le2 = new  QLineEdit   ;
    te2->setText("密码");
    le2->setPlaceholderText("密码:");
    te2->setFont(ft);
    le2->setFont(ft);
    te2->setGeometry(135,160,50,30);
    le2->setGeometry(185,160,200,30);
    te2->setParent(this);
    le2->setParent(this);
​
    bt1 = new  QPushButton("注册") ;
    bt2 = new  QPushButton ("登录");
​
​
    bt1->setGeometry(190,210,50,30);
    bt2->setGeometry(320,210,50,30);
    bt1->setParent(this);
    bt2->setParent(this);
​
    bt3 = new QPushButton("训练模式");
    bt3->setGeometry(420,210,70,30);
    bt3->setParent(this);
    //创建数据库
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("namepassdb");
    bool ok = db.open();
    qDebug()<hide();
​
    connect(bt1,SIGNAL(clicked(bool)),this,SLOT(registered()));//注册按钮触发
    connect(bt2,SIGNAL(clicked(bool)),this,SLOT(login()));//登录按钮触发
    connect(bt3,SIGNAL(clicked(bool)),this,SLOT(into_training()));//按钮触发进入训练模式
​
​
}
​
​
void interface::registered()
{
    //向入据库中加入一条信息
    qDebug()<<"regis";
    QString  str = QString("insert into nampass values('%0', '%1');").arg(le1->text()).arg(le2->text());
    QSqlQuery query;
    query.exec(str);
    qDebug()<text()).arg(le2->text());
    QSqlQuery query;
    query.exec(str);
​
    qDebug() << "log"<< str;
​
    while(query.next())
    {
        qDebug() << query.value(0).toString();
        qDebug() << query.value(1).toString();
        hide();
        g = new confirm;
        g->show();
        //         w = new Widget;
        //        w->show();
    }
}
​
void  interface::into_training()
{
    hide();
    w = new Widget;
    w->show();
​
}
​

interface.h
#ifndef INTERFACE_H
#define INTERFACE_H
#include "widget.h"//训练模式
#include "confirm.h"//闯关模式
#include 
#include 
#include 
#include
#include
#include
#include
#include
#include
#include
​
class interface : public QWidget
{
    Q_OBJECT
public:
    explicit interface(QWidget *parent = nullptr);
​
​
signals:
    void login_successed();
​
public slots:
    void registered();
    void login();
    void  into_training();
​
private:
    QPushButton *bt1;//注册按钮
    QPushButton *bt2;//登录按钮 进入挑战模式
    QPushButton  *bt3;//训练模式
    QLineEdit  *le1;//账号
    QLineEdit  *le2;//密码
    QLabel  *te1;//标签
    QLabel  *te2;//标签
    QLabel *max;//背景
    QSqlDatabase db;//数据库
    confirm * g;
    Widget *w;//具体游戏类指针(训练模式)
};
​
#endif // INTERFACE_H
​

widget.cpp(训练模式)
#include "widget.h"
​
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    int w,h,size,speed;
    w =600;
    h=600;
    size = 40;
    speed=450;
​
​
    this->setMinimumSize(1000,700);
    snake =new snake_class(w,h,size,speed);
    snake->setMinimumSize(w+w/5,h+h/5);
    QFont ft;
    ft.setPointSize(23);
    la1 = new QLabel("0");
    la2 = new QLabel("分数: ");
    la1->setFont(ft);
    la2->setFont(ft);
    bt = new QPushButton("确认");
    la1->setMaximumSize(70,70);
    la2->setMaximumSize(70,70);
    la1->setMaximumSize(70,70);
    la2->setMaximumSize(70,70);
​
    connect(snake,SIGNAL(send_scor(int)),la1,SLOT(setNum(int)));
    //rlineEdit->setPlaceholderText(tr("请输入温度"));
​
    le1 = new QLineEdit;
    le1->setPlaceholderText("界面长度(默认600)");
    le2 = new QLineEdit;
    le2->setPlaceholderText("界面宽度(默认600)");
    le3 = new QLineEdit;
    le3->setPlaceholderText("格子边长(建议能整除长、宽,默认40)");
    le4 = new QLineEdit;
    le4->setPlaceholderText("蛇自动移动速度(走一格时间(毫秒,默认450))");
​
    connect(bt,SIGNAL(clicked(bool)),this,SLOT(get_data()));
​
​
    QHBoxLayout *hbox1 = new QHBoxLayout;
    hbox1->addWidget(le1);
    hbox1->addWidget(le2);
    hbox1->addWidget(le3);
    hbox1->addWidget(le4);
​
    QHBoxLayout *hbox = new QHBoxLayout;
    hbox->addWidget(la2);
    hbox->addWidget(la1);
    hbox->setAlignment(Qt::AlignLeft);
    QVBoxLayout *vbox = new QVBoxLayout;
​
    vbox->addWidget(snake);
    vbox->addLayout(hbox);
    vbox->addLayout(hbox1);
    vbox->addWidget(bt);
    setLayout(vbox);
​
}
​
Widget::~Widget()
{
​
}
void Widget::get_data()
{
​
    int m =   le1->text().toInt();
    qDebug()<<" mm "<text().toInt();
    h=  le2->text().toInt();
    size =  le3->text().toInt();
    speed=  le4->text().toInt();
    if((le1->text().isEmpty() )|| (le2->text().isEmpty())||(le3->text().isEmpty())||(le4->text().isEmpty()))
​
    {
        msgbox = new  QMessageBox;
        msgbox->setText("编辑框是否都填了?");
        msgbox->setInformativeText("每个编辑框需要按照要求填写,请再试试。");
        msgbox->setStandardButtons(QMessageBox::Ok |QMessageBox::Cancel);
        msgbox->setDefaultButton(QMessageBox::Save);
        msgbox->exec();
        return ;
    }
​
    if(w <= 0|| h <=0|| size<=0|| speed <=0)
    {
​
        msgbox = new  QMessageBox;
        msgbox->setText("亲爱的老板,能不能正常点。");
        msgbox->setInformativeText("你觉得这些值可以为非正整数吗?,请再试试。");
        msgbox->setStandardButtons(QMessageBox::Ok |QMessageBox::Cancel);
        msgbox->setDefaultButton(QMessageBox::Save);
        msgbox->exec();
        return ;
​
    }
​
​
    snake->set_data(w,h,size,speed);
}
​

widget.h
#ifndef CONFIRM_H
#define CONFIRM_H
#include "snake_class.h"

#include 
#include
#include
#include
#include

class confirm : public QWidget
{
    Q_OBJECT
public:
    explicit confirm(QWidget *parent = nullptr);
    void set_data();

signals:
    void stop();

public slots:
    void reopen_game();
    void get_data(int);

private:
    snake_class *snake_confirm;
    int w =600 ;
    int h=600;
    int size=15;
    int seep=300;
    int score=0;
    int max = 3;
    int i =1;
    QLabel *la;
    QLabel *la1;
    QMessageBox *mesg;
    QLabel *la3;
     QLabel *la4;

};

#endif // CONFIRM_H

confirm.cpp(挑战模式)
#include "confirm.h"

confirm::confirm(QWidget *parent) : QWidget(parent)
{
    this->setMaximumSize(770,770);
    snake_confirm = new snake_class(w,h,size,seep);
    snake_confirm->setMinimumSize(w+w/5,h+h/5);
    //    snake_confirm->setParent(this);
    //    snake_confirm->show();
    connect(snake_confirm,SIGNAL(send_scor(int)),this,SLOT(get_data(int)));
    connect(snake_confirm,SIGNAL(send_feail()),this,SLOT(reopen_game()));//失败游戏重开

    la = new QLabel;
    la1 = new QLabel;
    la3= new QLabel;
    la4 = new QLabel;
    QFont ft;
    ft.setPointSize(23);
    la->setFont(ft);
    la1->setFont(ft);

    la4->setFont(ft);
    la3->setFont(ft);
    la->setMaximumSize(70,30);
    la1->setMaximumSize(70,30);
    la3->setMaximumSize(70,30);
     la4->setMaximumSize(70,30);
    la->setText(0);
    la1->setText("分数");
    la3->setText("关卡");
    la4->setText("1");
    connect(snake_confirm,SIGNAL(send_scor(int)),la,SLOT(setNum(int)));

    QHBoxLayout *hbox = new QHBoxLayout;
    hbox->addWidget(la1);
    hbox->addWidget(la);
    hbox->addWidget(la3);
    hbox->addWidget(la4);
    hbox->setAlignment(Qt::AlignLeft);

    QVBoxLayout *vbox =new QVBoxLayout;
    vbox->addWidget(snake_confirm);
    vbox->addLayout(hbox);
    setLayout(vbox);
    mesg = new QMessageBox;


}
void confirm::set_data()//设置关卡数据
{
    snake_confirm->set_data(w,h,size,seep);
}
void confirm::get_data(int score)//正常通关
{
    this->score = score;
    if(this->score == max)
    {
        i++;
        max += max*i;
        size += 5;
        seep -= 70;
        snake_confirm->set_data(w,h,size,seep);
        snake_confirm->change_type(-1);

        mesg->setText("即将进入下一关");
        mesg->setStandardButtons(QMessageBox::Ok);
        qDebug() << mesg->exec();
        la4->setNum(i);
        snake_confirm->change_type(1);
    }
}
void confirm::reopen_game()//失败重开(第一关开始)
{
    mesg->setText("闯关失败,游戏重新开始");
    mesg->setStandardButtons(QMessageBox::Ok);
    qDebug() << mesg->exec();
    size=15;
    seep=300;
    max = 3;
    i=1;
   la4->setText("1");
    snake_confirm->set_data(w,h,size,seep);
}

confirm.h
#ifndef CONFIRM_H
#define CONFIRM_H
#include "snake_class.h"

#include 
#include
#include
#include
#include

class confirm : public QWidget
{
    Q_OBJECT
public:
    explicit confirm(QWidget *parent = nullptr);
    void set_data();

signals:
    void stop();

public slots:
    void reopen_game();
    void get_data(int);

private:
    snake_class *snake_confirm;
    int w =600 ;
    int h=600;
    int size=15;
    int seep=300;
    int score=0;
    int max = 3;
    int i =1;
    QLabel *la;
    QLabel *la1;
    QMessageBox *mesg;
    QLabel *la3;
     QLabel *la4;

};

#endif // CONFIRM_H

snake_class.cpp(具体功能)
#include "snake_class.h"

snake_class::snake_class(int w=500,int h=500,int size=20,int speed =300 , QWidget *parent)
    :w(w),h(h),size(size),speed(speed) ,QWidget(parent)
{
    score =0 ;//初始分数
    m_speech=new QTextToSpeech;
    m_speech->pitchChanged(1023);


    heand_point  = new QPoint(my_rand()*size+size/2,my_rand()*size+size/2);//蛇头初始值随机
    ponit =new QPoint(my_rand()*(size)+size/2,my_rand()*(size)+size/2);//食物初始值随机

    //ponit =new QPoint(size+size/2,size+size/2);
    ver.append(heand_point);//蛇头加入数组
    pen.setWidth(size);//设置笔宽
    colr1.setRgb(rand() %255,rand()%255,rand()%255);
    pen.setColor(colr1);//设置笔的

    timeid = new int;
    *timeid = startTimer(speed);//定时器开始
    setFocusPolicy(Qt::StrongFocus);//键盘可以获取输入

}
void snake_class::paintEvent(QPaintEvent *event)//重绘事件
{

    QPainter per(this);//申请一个画家
    per.setPen(pen);//把笔给画家
    per.drawPixmap(ver[0]->x()-size/2,ver[0]->y()-size/2,size,size,QPixmap(":/20.png"));//画蛇头
    //    qDebug()<<"tou"<<*ver[0];
    for(int i =1 ; i< ver.length();i++)//画蛇
    {
        str2 = QString(":/%1.png").arg(qrand()%20+21);
        per.drawPixmap(ver[i]->x()-size/2,ver[i]->y()-size/2,size,size,QPixmap(str2));//画蛇身
    }
    per.drawPixmap(ponit->x()-size/2,ponit->y()-size/2,size,size,QPixmap(str));//画食物
    //    qDebug()<<"to"<<*ponit;

    QPainter per2(this);//画家2
    colr2.setRgb(rand() %255,rand()%255,rand()%255);
    pen2.setColor(colr2);//设置笔的
    per2.setPen(pen2);//把笔给画家
    for(int i = 0;i<= w/size;i++)//画竖线
    {        per2.drawLine(QPoint(i*size,0),QPoint(i*size,h));}
    for(int i = 0;i<= h/size;i++)//画横线
    { per2.drawLine(QPoint(0,i*size),QPoint(w,i*size));    }

    if((heand_point->x() >= w || heand_point->x() < 0) ||(heand_point->y() >= h || heand_point->y() < 0 ))
    {//判断越界
        ver.clear();
        heand_point->setX(my_rand()*size+size/2);
        heand_point->setY(my_rand()*size+size/2);
        ver.append(heand_point);
        score=0;
        key =0;
        m_speech->say("喔嚯");
        *ponit = QPoint(my_rand()*(size)+size/2,my_rand()*(size)+size/2);//食物初始值随机
        emit send_scor(score);
        emit send_feail();
    }



    if(((heand_point->x()) == ponit->x() ) && ((heand_point->y()) == ponit->y() ))
    {//判断是否吃到食物
        QPoint *po = new QPoint(0,0);
        m_speech->say("加油");
        str = QString(":/%1.png").arg(qrand()%12);
        ver.append(po);
        ponit->setX(my_rand()*size+size/2);
        ponit->setY(my_rand()*size+size/2);
        emit send_scor(++score);

    }
}


int snake_class::my_rand()//随机数
{
    //    int x=     qrand()%((wkey();
    key = event->key();
    QPoint f(*heand_point);
    QPoint f1;
    if(event->key() == 16777235){heand_point->setY(heand_point->y()-size);}
    if(event->key() == 16777237){heand_point->setY(heand_point->y()+size);}
    if(event->key() == 16777234){heand_point->setX(heand_point->x()-size);}
    if(event->key() == 16777236){heand_point->setX(heand_point->x()+size);}

    for(int i =1 ; i< ver.length();i++)//吃到自己的身体
    {
        if((ver[i]->x() == heand_point->x()) && (ver[i]->y() == heand_point->y()))
        {
            ver.clear();
            heand_point->setX(my_rand()*size+size/2);
            heand_point->setY(my_rand()*size+size/2);
            ver.append(heand_point);
            score=0;
            key =0;
            m_speech->say("喔嚯");
            *ponit = QPoint(my_rand()*(size)+size/2,my_rand()*(size)+size/2);//食物初始值随机
            emit send_scor(score);
            emit send_feail();
        }
    }


    for(int i =1;i< ver.length();i++)//蛇身每个节点跟上头
    {
        f1 = *ver[i];
        *ver[i] = f;
        f = f1;
    }

    colr1.setRgb(rand() %255,rand()%255,rand()%255);
    pen.setColor(colr1);//设置笔的
    //    qDebug()<< key;

    update();
    if(type ==1)
    {
        *timeid = startTimer(speed);
        type =0;
    }


}
void  snake_class::timerEvent(QTimerEvent *event)//随着时间,蛇朝一个方向运动
{

    QPoint f(*heand_point);
    if(key == 16777235){heand_point->setY(heand_point->y()-size);}
    if(key == 16777237){heand_point->setY(heand_point->y()+size);}
    if(key == 16777234){heand_point->setX(heand_point->x()-size);}
    if(key == 16777236){heand_point->setX(heand_point->x()+size);}

    for(int i =1 ; i< ver.length();i++)//吃到自己的身体
    {
        if((ver[i]->x() == heand_point->x()) && (ver[i]->y() == heand_point->y()))
        {
            ver.clear();
            heand_point->setX(my_rand()*size+size/2);
            heand_point->setY(my_rand()*size+size/2);
            ver.append(heand_point);
            score=0;
            key =0;
            m_speech->say("喔嚯");
            *ponit = QPoint(my_rand()*(size)+size/2,my_rand()*(size)+size/2);//食物初始值随机
            emit send_scor(score);
            emit send_feail();
        }
    }



    QPoint f1;
    for(int i =1;i< ver.length();i++)
    {
        f1 = *ver[i];
        *ver[i] = f;
        f = f1;
    }
    update();
    if(type == -1)
    {
        killTimer(*timeid);
        type =0;
    }
}
void snake_class::set_data(int w,int h, int size, int speed)
{

    this->w=  w;
    this->h=  h;
    this->size =  size;
    this->speed=  speed;

    *heand_point = QPoint(my_rand()*size+size/2,my_rand()*size+size/2);//蛇头初始值随机
    *ponit = QPoint(my_rand()*(size)+size/2,my_rand()*(size)+size/2);//食物初始值随机
}

void snake_class::change_type(int type)
{
    this->type = type;
    qDebug()<type;
}

snake_class.h
#ifndef SNAKE_CLASS_H
#define SNAKE_CLASS_H
//#include "snake_class.h"

//#include "confirm.h"

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

class snake_class : public QWidget
{
    Q_OBJECT
public:
    explicit snake_class(int w,int h,int size,int speed ,QWidget *parent = nullptr);
    void keyPressEvent(QKeyEvent *event);
    void timerEvent(QTimerEvent *event);
    void paintEvent(QPaintEvent *event);
    void set_data(int w,int h, int size, int speed);
    int my_rand();
    void change_type(int);
signals:
    send_scor(int);
    send_feail();

public slots:
private:
    QPoint *heand_point;//蛇头
    QVector ver;//蛇身
    int score;//分数
    QPoint *ponit;//食物
    int w;//长
    int h;//宽
    QTextToSpeech *m_speech;//声音
    QColor colr1;//颜色
    QPen pen;//笔
    QPen pen2;//笔
    QColor colr2;//颜色
    int size;
    int key;//键盘值
    QString str =":/0.png";//图片地址.食物
    QString str2 = ":/20.png";//图片地址,蛇
    int speed;//蛇自动移动速度
    int type =0;
    int *timeid;
//    confirm * com;

};

#endif // SNAKE_CLASS_H

总结
优点:
1、贪吃蛇功能全部实现,包括方向控制、自动移动、越界、咬到自身等。
2、实现不同模式,训练与挑战模式。
3、封装了不同的类,具有一定代码复用性。

缺点:
1、界面ui迫切需要优化。
2、代码逻辑性不高,可以将几个大类划分为更小的类。比如将具体功能类划分为:蛇类、食物类。这样代码复用性、移植性更高。


展望新版本:
1、可以编写服务器与客户端,实现多蛇共舞。

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1038776.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号