夏日已末 发表于 2018-1-16 23:47

QT实现两条贪吃蛇

最终效果图
https://www.52pojie.cn/forum.php?mod=image&aid=1033033&size=300x300&key=720d8214ad8b7c09&nocache=yes&type=fixnone

刚学qt两个礼拜,代码编的比较差,望各位看官海涵。
代码如下:
02_Snake.pro
#-------------------------------------------------#
# Project created by QtCreator 2017-12-11T22:59:40
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = 02_Snake
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += main.cpp\
      widget.cpp \
    mythread.cpp

HEADERS+= widget.h \
    mythread.h \
    allparameter.h

FORMS    += widget.ui

CONFIG +=C++11


allparameter.h
#ifndef ALLPARAMETER_H
#define ALLPARAMETER_H


extern QVector<QRect>rects; //存放第一条蛇
extern QVector<QRect>rectsfight;//存放第二条蛇
extern QRect newrect;//存放食物
//两条蛇的方向状态标志
extern int state,statefight;
extern int begin;
//方框长度和高度,列数,行数
extern int g_length,g_width,g_lines,g_rows;



#endif // ALLPARAMETER_H


mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QObject>
#include<QImage>

class MyThread : public QObject
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = 0);
    void DrawImage();

signals:
    void UpdateImage(QImage temp);
    void Touch();

public slots:

private:
    QImage image;

};

#endif // MYTHREAD_H


widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QThread>
#include<QTimer>
#include"mythread.h"
#include<QPaintEvent>
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

protected:
    void paintEvent(QPaintEvent *event);
    void dealUpdateImage(QImage);
    void closeThread();

    void keyPressEvent(QKeyEvent *event);
    void Paint();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

private:

    Ui::Widget *ui;
    MyThread *MyT;
    QThread *thread;
    QTimer *time_1;
    QImage image;
    int timeset;

};

#endif // WIDGET_H


main.cpp
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}


mythread.cpp
#include "mythread.h"
#include<QPainter>
#include<allparameter.h>
#include<QBrush>
#include<QPen>


MyThread::MyThread(QObject *parent) : QObject(parent)
{

}

void MyThread::DrawImage()
{


    switch(state)
    {
    //贪吃蛇往上边吃
    case 0:
      if(((rects).left()==newrect.left())&&(rects.top()-g_width==newrect.top()))
            {

                   //吃掉食物
                   rects.push_back(newrect);
                  // 产生不与蛇重叠的新食物
                   bool con=1;
                  int a,b;
                   while(con)
                   {
                     a=rand()%(g_rows);
                      b=rand()%(g_lines);
                      if(!(rects.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width)))&&!(rectsfight.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width))))
                        con=0;
                   }
                  newrect=QRect(begin+g_length*a,begin+g_width*b,g_length,g_width);
         }
      else
      {
            rects.push_back(QRect((rects.left()),(rects.top())-g_width,g_length,g_width));
            rects.removeAt(0);
      }

      break;
   //往左吃
    case 1:
      if(((rects).left()-g_length==newrect.left())&&(rects.top()==newrect.top()))
            {

         rects.push_back(newrect);
         bool con=1;
            int a,b;
         while(con)
         {
               a=rand()%(g_rows);
            b=rand()%(g_lines);
               if(!(rects.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width)))&&!(rectsfight.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width))))
                  con=0;
         }
               newrect=QRect(begin+g_length*a,begin+g_width*b,g_length,g_width);
         }
      else
      {
            rects.push_back(QRect((rects.left())-g_length,(rects.top()),g_length,g_width));
            rects.removeAt(0);
      }

      break;
    //往下吃
    case 2:
      if(((rects).left()==newrect.left())&&(rects.top()+g_width==newrect.top()))
            {

         rects.push_back(newrect);
         bool con=1;
            int a,b;
         while(con)
         {
               a=rand()%(g_rows);
            b=rand()%(g_lines);
            if(!(rects.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width)))&&!(rectsfight.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width))))
                  con=0;
         }
               newrect=QRect(begin+g_length*a,begin+g_width*b,g_length,g_width);
         }
      else
      {
            rects.push_back(QRect((rects.left()),(rects.top())+g_width,g_length,g_width));
                rects.removeAt(0);
      }

      break;
      //往右吃
    case 3:
      if(((rects).left()+g_length==newrect.left())&&(rects.top()==newrect.top()))
            {

         rects.push_back(newrect);
         bool con=1;
            int a,b;
         while(con)
         {
               a=rand()%(g_rows);
            b=rand()%(g_lines);
            if(!(rects.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width)))&&!(rectsfight.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width))))
                  con=0;
         }
               newrect=QRect(begin+g_length*a,begin+g_width*b,g_length,g_width);
         }
      else
      {
            rects.push_back(QRect((rects.left())+g_length,(rects.top()),g_length,g_width));
                rects.removeAt(0);
      }

      break;
   }
    //将第一位删除
   // rects.removeAt(0);


    //判断另一条蛇
    switch(statefight)
         {
      //往下吃
         case 0:
             if(((rectsfight).left()==newrect.left())&&(rectsfight.top()-g_width==newrect.top()))
               {

                rectsfight.push_back(newrect);
                bool con=1;
               int a,b;
                while(con)
                {
                  a=rand()%(g_rows);
                   b=rand()%(g_lines);
                   if(!(rectsfight.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width)))&&!(rectsfight.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width))))
                     con=0;
                }
                      newrect=QRect(begin+g_length*a,begin+g_width*b,g_length,g_width);
                }
             else
             {
               rectsfight.push_back(QRect((rectsfight.left()),(rectsfight.top())-g_width,g_length,g_width));
               rectsfight.removeAt(0);
             }

             break;
             //往往左吃
         case 1:
             if(((rectsfight).left()-g_length==newrect.left())&&(rectsfight.top()==newrect.top()))
               {

                rectsfight.push_back(newrect);
                bool con=1;
               int a,b;
                while(con)
                {
                  a=rand()%(g_rows);
                   b=rand()%(g_lines);
                  if(!(rectsfight.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width)))&&!(rectsfight.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width))))
                     con=0;
                }
                      newrect=QRect(begin+g_length*a,begin+g_width*b,g_length,g_width);
                }
             else
             {
               rectsfight.push_back(QRect((rectsfight.left())-g_length,(rectsfight.top()),g_length,g_width));
               rectsfight.removeAt(0);
             }

             break;
             //往上吃
         case 2:
             if(((rectsfight).left()==newrect.left())&&(rectsfight.top()+g_width==newrect.top()))
               {

                rectsfight.push_back(newrect);
                bool con=1;
               int a,b;
                while(con)
                {
                  a=rand()%(g_rows);
                   b=rand()%(g_lines);
                   if(!(rectsfight.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width)))&&!(rectsfight.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width))))
                     con=0;
                }
                      newrect=QRect(begin+g_length*a,begin+g_width*b,g_length,g_width);
                }
             else
             {
                rectsfight.push_back(QRect((rectsfight.left()),(rectsfight.top())+g_width,g_length,g_width));
                rectsfight.removeAt(0);
             }

             break;
             //往右吃
         case 3:
             if(((rectsfight).left()+g_length==newrect.left())&&(rectsfight.top()==newrect.top()))
               {

                        rectsfight.push_back(newrect);
                        bool con=1;
                         int a,b;
                        while(con)
                            {
                              a=rand()%(g_rows);
                               b=rand()%(g_lines);
                               if(!(rectsfight.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width)))&&!(rectsfight.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width))))
                                 con=0;
                            }
                              newrect=QRect(begin+g_length*a,begin+g_width*b,g_length,g_width);
                }
             else
             {
               rectsfight.push_back(QRect((rectsfight.left())+g_length,(rectsfight.top()),g_length,g_width));
               rectsfight.removeAt(0);
             }

             break;
          }



    //判断碰撞
   if(
            //第一条
            ((rects).left()<=begin-g_length)//碰到左边
            ||((rects).left()>=(begin+g_rows*g_length)) //碰到右边
            ||((rects).top()<=begin-g_width)//碰到上边
            ||((rects).top()>=(begin+g_width*g_lines)) //碰到下边
            //第二条
            ||((rectsfight).left()<=begin-g_length)
            ||((rectsfight).left()>=(begin+g_rows*g_length))
            ||((rectsfight).top()<=begin-g_width)
            ||((rectsfight).top()>=(begin+g_width*g_lines))
         )
    {

      //发出碰撞信号
       emit Touch();
      //清除两条蛇
      rects.clear();
      rectsfight.clear();
      //生成新的地图
      rects.push_back(QRect(begin+g_length*(g_rows/4),begin+g_width*(g_lines/4),g_length,g_width));
      rectsfight.push_back(QRect(begin+g_length*(g_rows*3/4),begin+g_width*(g_lines*3/4),g_length,g_width));

      bool con=1;
         int a,b;
      while(con)
      {
            a=rand()%(g_rows);
         b=rand()%(g_lines);
         if(!(rects.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width))))
               con=0;
      }
         newrect=QRect(begin+g_length*a,begin+g_width*b,g_length,g_width);
   }
    //重新生成地图
    image=QImage(begin*2+g_length*g_rows,begin+(g_width+3)*g_lines,QImage::Format_ARGB32);
    QPainter p(&image);
    QPen pen;
    p.setPen(pen);
    QVector<QLine>lines;
    for(int i=0;i<=g_lines;i++)
      {
      lines.push_back(QLine(begin,begin+g_width*i,begin+g_rows*g_length,begin+g_width*i));
    }
    for(int i=0;i<=g_rows;i++)
      {
      lines.push_back(QLine(begin+g_length*i,begin,begin+g_length*i,begin+g_width*g_lines));
      }
    p.drawLines(lines);
    QBrush brush;
    brush.setColor(Qt::black);
    brush.setStyle(Qt::SolidPattern);
    p.setBrush(brush);
    p.drawRects(rects);
    brush.setColor(Qt::yellow);
    p.setBrush(brush);
    p.drawRects(rectsfight);
    brush.setColor(Qt::red);
    p.setBrush(brush);
    p.drawRect(newrect);
    //触发更新地图信号
    emit UpdateImage(image);

}


widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include<QPainter>
#include<QPen>
#include<QBrush>
#include<allparameter.h>
#include<QMessageBox>

QVector<QRect>rects;
QVector<QRect>rectsfight;
QRect newrect;

int state=0,statefight=0;
int begin={20,20};
int g_length=20,g_width=20,g_lines=21,g_rows=21;


Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    //界面初始化
    ui->setupUi(this);
    //调整界面尺寸
    resize(begin*2+g_length*g_rows,begin+(g_width+3)*g_lines);
    //调整控件位置
    ui->pushButton->move((begin+g_length*(g_rows/2-1))-ui->pushButton->width()-ui->label->width(),begin+(g_width+1)*g_lines);
    ui->label->move((begin+g_length*(g_rows/2))-ui->label->width()-2,begin+(g_width+1)*g_lines);
    ui->lineEdit->move((begin+g_length*(g_rows/2)),begin+(g_width+1)*g_lines+2);
    ui->pushButton_2->move((begin+g_length*(g_rows/2+1))+ui->lineEdit->width(),begin+(g_width+1)*g_lines);
    //设置编辑框内容和大小
    ui->lineEdit->setText("300");
    ui->lineEdit->resize(40,20);
    //获取编辑框中的时间,将时间初始化
    timeset=ui->lineEdit->text().toInt();
    //初始化随机数
    srand((unsigned)time(NULL));
    //设置窗口无边框
    setWindowFlags(Qt::FramelessWindowHint|windowFlags());
    //添加两条蛇
    rects.push_back(QRect(begin+g_length*(g_rows/4),begin+g_width*(g_lines/4),g_length,g_width));
    rectsfight.push_back(QRect(begin+g_length*(g_rows*3/4),begin+g_width*(g_lines*3/4),g_length,g_width));
    //随机生成食物
    bool con=1;
   int a,b;
    while(con)
    {
      a=rand()%(g_rows);
       b=rand()%(g_lines);
       if(!(rects.contains(QRect(begin+g_length*a,begin+g_width*b,g_length,g_width))))
         con=0;
    }
   newrect=QRect(begin+g_length*a,begin+g_width*b,g_length,g_width);
    //初始化定时器
    time_1=new QTimer(this);
    //初始化线程
    MyT=new MyThread;
    thread=new QThread(this);
    MyT->moveToThread(thread);
    thread->start();
    //定时器时间到了之后,线程处理图像
    connect(time_1,&QTimer::timeout,MyT,&MyThread::DrawImage);
    //线程中发出更新图片后,主窗口更新画面
    connect(MyT,&MyThread::UpdateImage,this,&Widget::dealUpdateImage);
    //关闭窗口时,关闭线程
    connect(this,&Widget::destroyed,this,&Widget::closeThread);
    //当线程发出碰撞信号后,发出提示
    connect(MyT,&MyThread::Touch,this,
                        [=]()
                        {
                              time_1->stop();
                              QMessageBox message;
                              message.information(this,"提示","你输了");
                        }
                  );

    Paint();



}
//析构函数
Widget::~Widget()
{
    delete ui;
}
//关闭线程
void Widget::closeThread()
{
    thread->quit();
    thread->wait();
}
//按键事件
void Widget::on_pushButton_clicked()
{
    //读取时间
    timeset=ui->lineEdit->text().toInt();
    //打开或关闭定时器
    if(time_1->isActive()==false)
    {

      time_1->start(timeset);

    }
    else
    {
      time_1->stop();
    }
}
//画图事件
void Widget::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    p.drawImage(0,0,image);

}
//更新画面
void Widget::dealUpdateImage(QImage temp)
{
    image=temp;
    update();
}
//按键判断   wasd   ijkl
void Widget::keyPressEvent(QKeyEvent *event)
{
    switch(event->key())
    {
    case 87: state=0;break;
    case 65: state=1;break;
    case 83: state=2;break;
    case 68: state=3;break;
    case 73: statefight=0;break;
    case 74: statefight=1;break;
    case 75: statefight=2;break;
    case 76: statefight=3;break;
    }
}
//退出按钮
void Widget::on_pushButton_2_clicked()
{
    closeThread();
    close();
}
//画背景
void Widget::Paint()
{
    image=QImage(500,500,QImage::Format_ARGB32);
    QPainter p(&image);
    QPen pen;
    p.setPen(pen);
    QVector<QLine>lines;
    for(int i=0;i<=g_lines;i++)
      {
      lines.push_back(QLine(begin,begin+g_width*i,begin+g_rows*g_length,begin+g_width*i));
    }
    for(int i=0;i<=g_rows;i++)
      {
      lines.push_back(QLine(begin+g_length*i,begin,begin+g_length*i,begin+g_width*g_lines));
    }

    p.drawLines(lines);
    QBrush brush;
    brush.setColor(Qt::black);
    brush.setStyle(Qt::SolidPattern);
    p.setBrush(brush);
    p.drawRects(rects);
    brush.setColor(Qt::yellow);
    p.setBrush(brush);
    p.drawRects(rectsfight);
    brush.setColor(Qt::red);
    p.setBrush(brush);
    p.drawRect(newrect);
    update();
}


界面文件
https://images2017.cnblogs.com/blog/1300117/201801/1300117-20180112231423769-1357513827.png





Yang|阳 发表于 2018-1-17 00:19

应该是有不错的C++基础的

吊名想三天 发表于 2018-1-17 00:53

牛逼了老铁

wax126 发表于 2018-1-17 01:51

高手在民间啊

szhy007 发表于 2018-1-17 02:03

厉害大神

kingswb 发表于 2018-1-17 06:51

不错,不错

aila852 发表于 2018-1-17 11:33

两条要怎么操作啊、

夏日已末 发表于 2018-1-17 16:47

aila852 发表于 2018-1-17 11:33
两条要怎么操作啊、

wasd 和 ijkl
页: [1]
查看完整版本: QT实现两条贪吃蛇