项目二 贪吃蛇的设计

本文详细描述了如何在QT和C++环境中实现贪吃蛇游戏,包括基础功能如蛇的移动、食物生成、分数计算,以及交互界面设计、键盘控制和游戏结束条件。
摘要由CSDN通过智能技术生成

一.实验内容: 
1)实现贪吃蛇游戏基本功能,屏幕上随机出现一个“食物”,称为豆子。玩家能利用WASD键控制“蛇”的移动,“蛇”吃到“豆子”后“蛇”身体加长一节,得分增加,“蛇”碰到边界或蛇头与蛇身相撞,“蛇”死亡,游戏结束。

2)进行交互界面的设计,要有开始键、暂停键和停止退出的选项,能够控制游戏进程。对蛇吃到豆子进行分值计算,可以设置游戏速度拓展元素。

二.实验环境

QT和C++环境下实现

三.代码实现

1.开始界面的实现

页面的跳转,通过信号与槽的的方式来实现

头文件

#ifndef START_H
#define START_H

#include <QDialog>

namespace Ui {
class start;
}

class start : public QDialog
{
    Q_OBJECT

public:
    explicit start(QWidget *parent = nullptr);
    ~start();
    int getspeed();

private:
    Ui::start *ui;
};

#endif // START_H

源文件:

#include "start.h"
#include "ui_start.h"
#include <QDebug>

start::start(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::start)
{
    ui->setupUi(this);
    this->setFixedSize(this->size());
}

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

int start::getspeed()
{
    int n=ui->comboBox->currentIndex();
    if(n==0)return 20;
    if(n==1)return 10;
    if(n==2)return 5;
}


2.绘制食物和蛇身,以及判断是否吃到食物

随机生成数且设置srand
生成随机数randy randx
判断xy是否在游戏界限内,若在游戏界限内生成食物的坐标
用一个循根据坐标数组绘制食物的点
设置画笔的颜色和宽度
用painter对象绘制食物

body用坐标数组来表示,用painter,来画点
判断蛇头是否在食物的范围内,如果在这个范围内,就吃掉食物,并且更新长度。

//绘制函数,负责绘制食物和蛇
void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setPen(QPen(QColor(Qt::yellow)));
    painter.setBrush(QBrush(QColor(Qt::white)));
    //游戏边框线
    painter.drawRect(rectangle);


    //随机生成食物
    if(!eatflag)
    {
        eatflag = 1;
        srand(QTime::currentTime().msec()*rand()*rand()*rand());
        while(1)
        {
            //按照界面的大小生成的数
            randx = rand() % (this->width());
            randy = rand() % (this->height());
            //判断一下是否在游戏界限内,在界内才会生成
            if(randx >= 15 && randy >= 45)
            {
                if(randx <= (this->width()-15) && randy <= (this->height()-15))
                {
                    food_point.setX(randx);
                    food_point.setY(randy);
                    break;
                }
            }
        }

    }

    QPen pen;
    pen.setWidth(10);

    pen.setColor(Qt::green);//设置食物的颜色
    painter.setPen(pen);
    painter.drawPoint(food_point);//画食物
    //len越大,画的越长
    for(int j= 0;j < len;j++)
    {
        pen.setColor(Qt::black);
        painter.setPen(pen);
        painter.drawPoint(body[j]);//画蛇,按照这个坐标数组去画点
    }
    //判断是否吃到食物
    if((head_point.y() < (food_point.y()+5))&&(head_point.y() > (food_point.y()-5)))
    {
        if((head_point.x()<(food_point.x()+5))&&(head_point.x()>(food_point.x()-5)))
        {
            len += 5;
            score += 1;
            eatflag = 0;
//            qDebug() << "eat!!";
        }
    }
}

3.键盘响应实现移动

从键盘传入参数,当direction为0的时候,将头部坐标y值减一,将头部坐标赋给后面的body(0),将后面的坐标依次向前移动一个位置

 switch (direction)
    {
    case 0:

        point = body[0];
        head_point.setY(head_point.y()-1);
        body[0] = head_point;
        for(i = 1; i < len; i++)
        {
            buf = body[i];
            body[i] = point;
            point = buf;
        }

        break;
    case 1:

        point = body[0];
        head_point.setY(head_point.y()+1);
        body[0] = head_point;
        for(i = 1; i < len; i++)
        {
            buf = body[i];
            body[i] = point;
            point = buf;
        }
        break;
    case 2:

        point = body[0];
        head_point.setX(head_point.x()-1);
        body[0] = head_point;
        for(i = 1; i < len; i++)
        {
            buf = body[i];
            body[i] = point;
            point = buf;
        }
        break;
    case 3:

        point = body[0];
        head_point.setX(head_point.x()+1);
        body[0] = head_point;
        for(i = 1; i < len; i++)
        {
            buf = body[i];
            body[i] = point;
            point = buf;
        }
        break;
    default:
        break;
    }
    //update()时,调用paintEvent(QPaintEvent*)
    update();
}

void Widget::keyPressEvent(QKeyEvent *event)
{
    //点击按键会给direction赋值,但如果是向上走就不能往下  上下左右0123
    switch (event->key())
    {
    case Qt::Key_W:
        if(direction == 1)
            break;
        direction = 0;
        break;
    case Qt::Key_S:
        if(direction == 0)
           break;
        direction = 1;
        break;
    case Qt::Key_A:
        if(direction == 3)
            break;
        direction = 2;
        break;
    case Qt::Key_D:
        if(direction == 2)
            break;
        direction = 3;
        break;
    default:
        break;
    }
}

4.游戏结束的条件

撞到墙或者头撞到身体

void Widget::timerEvent(QTimerEvent *event)
{
    static int i = 0;
    //update score
    QString text = QString("你的得分:%1").arg(score);
    ui->label_2->setText(text);

    /***********游戏结束条件********************/

    //撞到身体了
    for(i = 1;i<len;i++)
    {
        if(head_point == body[i])
        {
            killTimer(timeid);
            QMessageBox::about(this,"游戏结束",text);
        }
    }

    //撞墙
    if(head_point.x() <= 15 || head_point.y() <= 45)
    {
        killTimer(timeid);
        QMessageBox::about(this,"游戏结束",text);
    }
    else if(head_point.x() >= (this->width()-15) || head_point.y() >= (this->height()-15))
    {
        killTimer(timeid);
        QMessageBox::about(this,"游戏结束",text);
    }

四.实际演示

1.开始界面

可以选者蛇身的速度

2.开始游戏

3.游戏结束

项目界面

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值