QT实现贪吃蛇

QT实现贪吃蛇

游戏效果
1.Snake类

#define SNAKE_H

#include <mutex>
#include <iostream>
#include <stdlib.h>
#include <list>
#include <QRect>
using namespace std;


class Snake
{
public:
    static Snake* instandite();//顺便做了一个单例
    void setBody(int count){

    }
    void setSpeed(int speed){
        //this->m_speed = speed;
    }
public:
    list<QRect> list_body;//蛇身
    QRect m_head; //蛇头
    int GetLenth();
    int m_direction;//运动方向 1234 上下左右
private:
    Snake();
    Snake(Snake&)=delete;
    Snake &operator= (Snake&)=delete;
    static Snake* p;
    static mutex tex;
private:

    int m_lenth;
    int int_speed;//设置速度,调节难度 1~5,也就是定时器刷新得时间
};

#endif // SNAKE_H
/*************下面是cpp*****************/
#include "snake.h"

mutex Snake::tex;
Snake* Snake::p=nullptr;

Snake::Snake()
{

    m_head = QRect(300,330,10,10);
    list_body.push_back(QRect(300,320,10,10));
    list_body.push_back(QRect(300,310,10,10));
    list_body.push_back(QRect(300,300,10,10));
    m_direction = 2; //初始默认向下运动
}
Snake* Snake::instandite()//顺便做的单例,练练手
{
    if(nullptr == p)
    {
        tex.lock();
        p = new Snake();
        tex.unlock();
    }
    return p;
}

int Snake::GetLenth()
{
    list<QRect>::iterator p = this->list_body.begin();
    int count = 0;
    for(p;p!=this->list_body.end();p++)
    {
        count++;
    }
    return count;
}

MainWindow界面

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPainter>
#include <QMessageBox>
#include <QKeyEvent>
#include <stdlib.h>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    psnake = Snake::instandite();
    ptime = new QTimer;
    connect(ptime,SIGNAL(timeout()),this,SLOT(refresh())); //启动定时器,每秒刷新snake
    randRect = QRect(300,400,10,10);
    srand((unsigned)time(NULL));
    ptime->start(200);
    num = 0;
}

通过定时器实现蛇得运动

void MainWindow::refresh()
{
    list<QRect>::iterator pbegin = psnake->list_body.begin();
    QRect rect;
    QRect temprect = *pbegin;
    QRect temphead = psnake->m_head;
    psnake->list_body.pop_back();//删除最后一节身体
    if(psnake->m_direction == 1)//向上运动
    {
        rect = QRect(psnake->m_head);
        psnake->m_head = QRect(temphead.left(),temphead.top()-10,10,10);
        psnake->list_body.push_front(rect);
    }
    else if(psnake->m_direction == 2)//向下运动
    {
        rect = QRect(psnake->m_head);
        psnake->m_head = QRect(temphead.left(),temphead.top()+10,10,10);
        psnake->list_body.push_front(rect);
    }
    else if(psnake->m_direction == 3)//向左运动
    {
        rect = QRect(psnake->m_head);
        psnake->m_head = QRect(temphead.left()-10,temphead.top(),10,10);
        psnake->list_body.push_front(rect);
    }
    else//向右运动
    {
        rect = QRect(psnake->m_head);
        psnake->m_head = QRect(temphead.left()+10,temphead.top(),10,10);
        psnake->list_body.push_front(rect);
    }
    if(temphead.left()==randRect.left()&&temphead.top()==randRect.top())
    {
        psnake->list_body.push_front(randRect);
        num++;
        QString text =QString("当前得分:%1").arg(num);
        ui->label->setText(text);
        randRect = QRect((rand() % 50)*10,(rand() % 40)*10,10,10);
    }
    if(isLose()==0)
        return;

    update();
}

重写paintevent,绘制蛇身蛇头和奖励点

void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setPen(Qt::black);
    painter.setBrush(Qt::green);
    list<QRect>::iterator p = psnake->list_body.begin();

    painter.drawRect(psnake->m_head);
    for(p;p!=psnake->list_body.end();p++)
    {
        painter.drawRect(*p);
    }

    painter.fillRect(randRect,Qt::red);
}

控制蛇得运动,重写键盘控制事件

void MainWindow::keyPressEvent(QKeyEvent *ev)//键盘按下事件
{
    if(ev->key() == Qt::Key_D)
    {
       if(psnake->m_direction == 3)//判断如果蛇向右运动,那么屏蔽向左得按键
       return ;
       psnake->m_direction = 4;
       return;
    }
    if(ev->key() == Qt::Key_A)
    {
       if(psnake->m_direction == 4)
       return ;
       psnake->m_direction = 3;
       return;
    }
    if(ev->key() == Qt::Key_S)
    {
       if(psnake->m_direction == 1)
       return ;
       psnake->m_direction = 2;
       return;
    }
    if(ev->key() == Qt::Key_W)
    {
       if(psnake->m_direction == 2)
       return ;
       psnake->m_direction = 1;
       return;
    }
}

判断是否游戏失败,1.碰到身体,2.碰到墙壁

int MainWindow::isLose()
{
    QRect rect = psnake->m_head;
    if(rect.left()>600||rect.left()<=-1||rect.bottom()<=-1||rect.bottom()>500)//碰到边界
    {
        ptime->stop();
        QMessageBox::information(NULL,  "Title",  "Game Over", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
        return 0;
    }
    if(isTouchBody())//碰到身体
    {
        ptime->stop();
        QMessageBox::information(NULL,  "Title",  "Game Over", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
        return 0;
    }
    return 1;
}
bool MainWindow::isTouchBody()
{

    list<QRect>::iterator pbegin = psnake->list_body.begin();
    for(pbegin;pbegin!=psnake->list_body.end();pbegin++)
    {
        if(psnake->m_head==*pbegin)
            return true;//碰到身体
    }
    return false;
}

这里得messageBox可以自己重写,失败后可以重新开始游戏,可以用回调函数得思想写messageBox。
写这个得目的主要是为了锻炼面向对象,这里面向对象思想用的不好,很多地方需要改善,只有去练习,才能知道哪里做的不好。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值