| 
#include "MainWindow.h"
#include "ui_widget.h"
#include <QLabel>
#include <QPushButton>
//主窗口构造函数
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);      //初始化出.ui界面
    //一个格子宽高25像素,地图宽高600像素,每行有24个格子
    //设置固定窗口大小
    setFixedSize(1000,600);
    //设置得分标签控件的属性
    ui->label->setFont(QFont("黑体", 20, QFont::Bold, false));
    //设置游戏速度标签内容
    ui->label_2->setFont(QFont("楷体", 16, QFont::Bold, false));
    ui->label_2->setText("游戏速度:");
    //滑动条控件,这里将数值按一定比例放大缩小
    ui->horizontalSlider->setValue(200 >> 2);
    //监听滑动条控件滑动时,改变定时器速度为滑动条的值
    connect(ui->horizontalSlider,QSlider::valueChanged,[=]()
    {
        timerspeed = ui->horizontalSlider->value() << 2;
    });
    //设置重新开始按钮属性和内容
    ui->pushButton_3->setFont(QFont("黑体",12));
    ui->pushButton_3->setText("重新开始");
    //监听重新开始按钮
    connect(ui->pushButton_3,QPushButton::clicked,[=]()
    {
        snake.Reset();      //重置蛇
        score = 0;          //得分清0
        key = 'd';          //key值向右
        timerspeed = 200 << 2;//重置游戏速度
        timer->start(timerspeed);//重置定时器
        ui->horizontalSlider->setValue(200 >> 2);//重置滑动条
        gameflag = false;   //重置游戏结束标志
    });
    //开启定时器
    timer->start(timerspeed);
    //监听定时器的信号,执行表达式内容
    connect(timer,&QTimer::timeout,[=]()
    {
        timer->start(timerspeed); //调整定时器的速度
        snake.Move(key);    //蛇移动函数
        //吃到食物的情况
        (food.getfoodX() == snake.snakevec.at(0).x && food.getfoodY() == snake.snakevec.at(0).y) ?
        score++, food.randfood():    //得分+1,随机产生一个食物坐标
        snake.snakevec.pop_back();   //删除蛇尾
        GameOver();    //游戏失败的情况
        update();      //调用绘图函数
        //更新标签控件的文本内容
        ui->label->setText(QString("得分:%1").arg(score));
    });
}
//游戏失败情况
void Widget::GameOver()
{
    //撞墙失败
    if(snake.snakevec.at(0).x >= 24 * 25 || snake.snakevec.at(0).x < 0 ||
       snake.snakevec.at(0).y < 0 || snake.snakevec.at(0).y >= 24 * 25)
    {
        gameflag = true;
        timer->stop();      //暂停定时器
        return;
    }
    //撞自己失败
    for(int i = 1; i < snake.snakevec.size(); i++)
    {
        if(snake.snakevec.at(0).x == snake.snakevec.at(i).x &&
           snake.snakevec.at(0).y == snake.snakevec.at(i).y)
            gameflag = true, timer->stop();
    }
}
//绘图事件
void Widget::paintEvent(QPaintEvent *)
{
    //创建画家对象,指定绘图设备为this主窗口
    QPainter painter(this);
    //设置画刷为红色
    QBrush brush1(Qt::red);
    //让画家使用画刷
    painter.setBrush(brush1);
    //画食物
    painter.drawRect(QRect(food.getfoodX(),food.getfoodY(),25,25));
    //设置画刷为黑色
    QBrush brush2(Qt::blue);
    painter.setBrush(brush2);
    //遍历蛇坐标容器,画出代表蛇身的矩形
    for(auto snakenodei : snake.snakevec)
        //蛇头画圆形
        (snakenodei.x == snake.snakevec.at(0).x &&
         snakenodei.y == snake.snakevec.at(0).y) ?
        //蛇头画圆形
        painter.setRenderHint(QPainter::Antialiasing),  //用抗锯齿画圆
        painter.drawEllipse(QPoint(snakenodei.x + 12,snakenodei.y + 12),12,12):
        //蛇身画矩形
        painter.drawRect(QRect(snakenodei.x,snakenodei.y,25,25));
    bugflag = false;    //在画出蛇之后将标志设为假
    //设置画刷为黑色
    QBrush brush3(QColor(128, 64, 0));
    painter.setBrush(brush3);
    //画出墙壁
    for(int i = 0; i < 24; i++)
          painter.drawRect(QRect(25 * 25, i * 25, 25, 25));
    //游戏结束时的绘图
    if(gameflag)
    {   //设置文字属性
        QFont font("楷体", 80, QFont::Bold, false);
        painter.setFont(font);      //使用字体
        painter.drawText(QRect(240, 200, 1000, 500), "游戏结束");   //画出游戏结束文字
    }
}
//键盘事件,改变贪吃蛇移动方向
void Widget::keyPressEvent(QKeyEvent *ev)
{
    if(bugflag)     //bug标志为真直接返回
        return;
    switch (ev->key())
    {
    case Qt::Key_W:
        if(key == 's') break;   //按下与当前方向相反按键时break
        key = 'w';
        bugflag = true; break;        //按键之后将标志设为真
    case Qt::Key_S:
        if(key == 'w') break;
        key = 's';
        bugflag = true; break;
    case Qt::Key_A:
        if(key == 'd') break;
        key = 'a';
        bugflag = true; break;
    case Qt::Key_D:
        if(key == 'a') break;
        key = 'd';
        bugflag = true; break;
    case Qt::Key_Space:     //空格键暂停,这里有点问题
        timer->stop(); break;
    default:                //其他键重启定时器
        timer->start(timerspeed);
    }
}
//析构
Widget::~Widget()
{
    delete ui;
} |