Qt版的贪吃蛇游戏

开发环境:Ubuntu12.04 Qt4.8
项目概述: 用键盘上下左右控制蛇的方向,寻找食物,食物随机出现,蛇路过食物蛇的身体会变长,蛇不能碰墙壁及自己的身体,蛇不能相撞,两条蛇谁先达到一定的分数谁获得胜利
游戏说明:程序运行后,单击鼠标左键开始游戏
蛇一:方向键上下左右,蛇二WASD上下左右

1.main.cpp

#include <QtGui/QApplication>
#include <QTextCodec>
#include "widget.h"

int main(int argc, char *argv[])
{
    //中文乱码处理
    QTextCodec *codec=QTextCodec::codecForName("utf-8");
    QTextCodec::setCodecForLocale(codec);
    QTextCodec::setCodecForCStrings(codec);
    QTextCodec::setCodecForTr(codec);

    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

2.snakeBoday.h

#ifndef SNAKEBODAY_H
#define SNAKEBODAY_H

#include <QLabel>

#define BodySize (40)

class SnakeBoday : public QLabel
{
    Q_OBJECT
public:
    explicit SnakeBoday(QWidget *parent = 0);
    
signals:
    
public slots:
    
};

#endif // SNAKEBODAY_H

3.snakeBoday.cpp

#include "snakeBoday.h"
#include <stdio.h>

SnakeBoday::SnakeBoday(QWidget *parent) :
    QLabel(parent)
{
    // 设置食物的大小
    this->resize(BodySize,BodySize);

    // 随机设置食物的位置
    int x = (rand()%(parent->width()/BodySize))*BodySize;
    int y = (rand()%(parent->height()/BodySize))*BodySize;
    this->move(x,y);

    // 随机设置食物的颜色
    char styleSheet[255];
    sprintf(styleSheet,"background-color: rgb(%d, %d, %d);",
            rand()%256,rand()%256,rand()%256);
    this->setStyleSheet(styleSheet);

    // 显示食物
    this->show();
}

4.widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QList>
#include <QTimer>
#include <QMouseEvent>
#include <QKeyEvent>
#include "snakeBoday.h"

namespace Ui {
class Widget;
}

enum MoveDirection{
    UP,
    Down,
    Left,
    Right
};

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

    // 按下鼠标左键开始游戏
    void mouseReleaseEvent(QMouseEvent *event);

    // 改变运动方向
    void keyReleaseEvent(QKeyEvent *event);

    // 删除身体
    void del_snake_body(QList<SnakeBoday*>& snake);

public slots:
    void snake1_timeout_slot(void);
    void snake2_timeout_slot(void);

private:
    Ui::Widget *ui;
    //分数
    int score1;
    int score2;
    // 食物
    SnakeBoday* food;
    // 定时器
    QTimer* timer1;
    QTimer* timer2;
    // 两条蛇
    QList<SnakeBoday*> snake1;
    QList<SnakeBoday*> snake2;
    // 蛇的运动方向
    MoveDirection snakeDirection1;
    MoveDirection snakeDirection2;
};

#endif // WIDGET_H

5.widget.cpp

#include <QMessageBox>
#include "widget.h"
#include "ui_widget.h"

QString str1;
QString str2;

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    score1=0;
    score2=0;

    // 初始化随机数
    srand(time(NULL));

    // 创建蛇1的蛇头
    SnakeBoday* head1 = new SnakeBoday(this);
    head1->setStyleSheet("background-color: rgb(255, 255, 255);"
                         "border-color: rgb(0, 0, 0);"
                         "border-style:solid;"
                         "border-width:2px;"
                         );
    snake1.push_back(head1);

    // 创建蛇2的蛇头
    SnakeBoday* head2 = new SnakeBoday(this);
    head2->setStyleSheet("background-color: rgb(0, 255, 127);"
                         "border-color: rgb(0, 0, 0);"
                         "border-style:solid;"
                         "border-width:2px;");
    snake2.push_back(head2);

    // 创建定时器
    timer1 = new QTimer;
    timer2 = new QTimer;

    // 连接定时器的信号
    connect(timer1,SIGNAL(timeout()),this,SLOT(snake1_timeout_slot()));
    connect(timer2,SIGNAL(timeout()),this,SLOT(snake2_timeout_slot()));

    // 随机蛇的运动方向
    snakeDirection1 = (MoveDirection)(rand()%4);
    snakeDirection2 = (MoveDirection)(rand()%4);

    // 创建一个食物
    food = new SnakeBoday(this);
}

Widget::~Widget()
{
    del_snake_body(snake1);
    del_snake_body(snake2);
    delete snake1[0];
    delete snake2[0];
    delete food;
    delete ui;
}

void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    // 当鼠标左键按下,启动定时器
    if(event->button() == Qt::LeftButton)
    {
        timer1->start(500);
        timer2->start(500);
    }
}

void Widget::keyReleaseEvent(QKeyEvent *event)
{
    // 改变运动方向
    switch(event->key())
    {
    case Qt::Key_Up:    snakeDirection1 = UP; break;
    case Qt::Key_Down:  snakeDirection1 = Down; break;
    case Qt::Key_Left:  snakeDirection1 = Left; break;
    case Qt::Key_Right: snakeDirection1 = Right; break;
    case Qt::Key_W: snakeDirection2 = UP; break;
    case Qt::Key_S: snakeDirection2 = Down; break;
    case Qt::Key_A: snakeDirection2 = Left; break;
    case Qt::Key_D: snakeDirection2 = Right; break;
    }
}

void Widget::snake1_timeout_slot(void)
{
    // 先移动蛇身
    for(int i=snake1.size()-1; i>0; i--)
    {
        snake1[i]->move(snake1[i-1]->x(),snake1[i-1]->y());
    }

    // 获取蛇头位置
    int x = snake1[0]->x() , y = snake1[0]->y();

    // 移动蛇头
    switch(snakeDirection1)
    {
    case UP: y -= BodySize; break;
    case Down: y += BodySize; break;
    case Left: x -= BodySize; break;
    case Right: x += BodySize; break;
    }
    snake1[0]->move(x,y);

    // 判断是否撞墙
    if(x < 0 || y < 0 || x > width() || y > height())
    {
        del_snake_body(snake1);
        score1=0;
        //显示分数
        str1.setNum(score1);
        ui->label_3->setText(str1);

        timer1->start(500);

    }

    // 是否与对方相撞
    for(int i=0; i<snake2.size(); i++)
    {
        if(x == snake2[i]->x() && y == snake2[i]->y())
        {
            del_snake_body(snake1);
            //显示分数
            score1=0;
            str1.setNum(score1);
            ui->label_3->setText(str1);

            timer1->start(500);
        }
    }


    // 判断蛇头是否与食物相遇
    if(food->x() == x && food->y() == y)
    {
        // 食物加入蛇身
        snake1.push_back(food);

        score1+=1;
        //显示分数
        str1.setNum(score1);//显示数字
        ui->label_3->setText(str1);

        // 创建新的食物
        food = new SnakeBoday(this);

        // 根据蛇身长度调整速度
        switch(snake1.size())
        {
        case 2: timer1->start(450); break;
        case 4: timer1->start(400); break;
        case 8: timer1->start(350); break;
        case 16: timer1->start(300); break;
        case 32: timer1->start(250); break;
        case 64: timer1->start(200); break;
        case 128: timer1->start(150); break;
        case 256: timer1->start(100); break;
        }
        if(score1 == 10)
        {
            QMessageBox::warning(this,"胜利弹窗","恭喜蛇一玩家获得胜利");
        }
    }

}

void Widget::snake2_timeout_slot(void)
{
    for(int i=snake2.size()-1; i>0; i--)
    {
        snake2[i]->move(snake2[i-1]->x(),snake2[i-1]->y());
    }

    int x = snake2[0]->x() , y = snake2[0]->y();
    switch(snakeDirection2)
    {
    case UP: y -= BodySize; break;
    case Down: y += BodySize; break;
    case Left: x -= BodySize; break;
    case Right: x += BodySize; break;
    }
    snake2[0]->move(x,y);

    // 判断是否撞墙
    if(x < 0 || y < 0 || x > width() || y > height())
    {
        del_snake_body(snake2);
        score2=0;
        str2.setNum(score2);
        ui->label_4->setText(str2);
        timer2->start(500);

    }

    // 是否与对方相撞
    for(int i=0; i<snake1.size(); i++)
    {
        if(x == snake1[i]->x() && y == snake1[i]->y())
        {
            del_snake_body(snake2);
            score2=0;
            str2.setNum(score2);
            ui->label_4->setText(str2);
            timer2->start(500);
        }
    }

    if(food->x() == x && food->y() == y)
    {
        snake2.push_back(food);
        score2+=1;
        str2.setNum(score2);
        ui->label_4->setText(str2);
        food = new SnakeBoday(this);
        switch(snake2.size())
        {
        case 2: timer2->start(450); break;
        case 4: timer2->start(400); break;
        case 8: timer2->start(350); break;
        case 16: timer2->start(300); break;
        case 32: timer2->start(250); break;
        case 64: timer2->start(200); break;
        case 128: timer2->start(150); break;
        case 256: timer2->start(100); break;
        }
        if(score2 == 10)
        {
            QMessageBox::warning(this,"胜利弹窗","恭喜蛇二玩家获得胜利");
        }
    }
}

// 删除身体
void Widget::del_snake_body(QList<SnakeBoday*>& snake)
{
    while(snake.size()>1)
    {
        delete snake.back();
        snake.pop_back();
    }

    // 随机设置食物的位置
    int x = (rand()%(width()/BodySize))*BodySize;
    int y = (rand()%(height()/BodySize))*BodySize;
    snake[0]->move(x,y);
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值