程序员开发实例大全宝库

网站首页 > 编程文章 正文

Qt 贪吃蛇制作(含源码)(qt编写贪吃蛇详细代码)

zazugpt 2024-09-04 22:23:46 编程文章 21 ℃ 0 评论

这次给大家分享我制作的贪吃蛇——

首先,利用qt creator新建一个工程(不带ui界面)。如何创建一个工程,在上一篇文章已介绍,这里不再赘述。

1.添加资源文件

在工程里面新建一个名为res的文件夹,将所需要的图片资源拷贝过来。然后,右键点击工程名->添加新文件 -> Qt -> Qt ResourceFile->输入名称->完成。

接着,点击“添加”->"添加前缀”->“添加”->“添加文件”,打开所有的资源文件,再“保存所有文件”即可。

这时,我们可以看到多了如下这些文件——

2、设置标题、背景以及图标以及窗口大小等

在mainwindow.cpp的构造函数中添加如下代码:

this->setFixedSize(800, 480);
    setWindowIcon(QIcon(":/new/prefix1/res/bitbug_favicon.ico"));
    setWindowTitle("贪吃蛇");
    this->setStyleSheet("QMainWindow{border-image: url(:/new/prefix1/res/page2.jpg);}");

测试运行,效果如下:

3、添加“点心”

接着,先给大蛇添加美味的“点心”。该“点心”可在界面任意空闲的位置出现。实现过程如下:

实现添加一个新类——Dessert。右击项目名称->添加新文件->C++ -> C++Class ,定义类名,最后“完成”。

完成之后,我们可以看到,项目中多了两个文件——dessert.h和dessert.cpp。然后我们在dessert.h添加如下代码:

    int x;     //点心的x轴坐标
    int y;    //点心的y轴坐标
    QPushButton *btn;      //用作设置背景
    void makeDessert(Snake *h);     //制造点心       Snake是我们大蛇链表的头节点,在后面才实现它

在dessert.cpp的构造函数中实现如下代码:

    x = 0;
    y = 0;
    btn = new QPushButton(parent);
    btn->setFixedSize(20, 20);     //点心图片的大小
    btn->setStyleSheet("border-image: url(:/new/prefix1/res/eat.ico);");   //添加图片
    srand((unsigned)time(NULL));        //为了产生随机数

在后面还要实现makeDessert函数:

void Dessert::makeDessert(Snake *h)
{
    bool circle = false;
    Snake *p = NULL;
    while(1)
    {
        x = rand()%38+1;      //产生随机值   不能与周围的“墙壁”重合
        y = rand()%22+1;
        btn->move(x * 20, y * 20);
        p = h->next;
        while (p != NULL)
        {
            if(p->x == x && p->y == y)       //不能与大蛇本身冲突
            {
                circle = true;
                break;
            }
            p = p->next;
        }
        if(!circle)  break;
    }
}

然后,在mainwindow.h中添加它的头文件#include "dessert.h",并在类中定义它的一个对象:

Dessert *dessert;

之后,在mainwindow.cpp中的构造函数里实现它的初始化:

dessert = new Dessert(this);
dessert->makeDessert(head);

完成之后,我们可以先注释掉与Snake有关的代码,运行测试以下:

void Dessert::makeDessert()
//void Dessert::makeDessert(Snack *h)
{
    bool circle = false;
//    Snack *p = NULL;
//    while(1)
    {
        x = rand()%38+1;
        y = rand()%22+1;
        btn->move(x * 20, y * 20);
/*
        p = h->next;
        while (p != NULL)
        {
            if(p->x == x && p->y == y)
            {
                circle = true;
                break;
            }
            p = p->next;
        }
        if(!circle)  break;
*/
    }
}

可以看到,界面中多了一个红色的东西。然后我们再将刚才的注释取消。

4、初始化大蛇

首先,我们像刚才添加“点心”一样,添加两个文件——snake.cpp和snake.h(前面已有详细描述,这里不再赘述)。

然后,我们再snake.h实现如下代码:

#ifndef SNACK_H
#define SNACK_H
#include <QRect>
#include <QPushButton>
#include <QPixmap>
#include <QMainWindow>
#define SIZE 20
enum Director
{
    UP,
    DOWN,
    LEFT,
    RIGHT,
};
class Snake
{
public:
    Snake(QMainWindow *parent);
    ~Snake();
    int x;
    int y;      //表示节点的坐标
    QPushButton *btn;   //用来设置设置背景
     Snake *next;       //用来指向下一个节点
};
#endif // SNACK_H

在snake.cpp中实现如下代码:

#include "snake.h"
snake::snake(QMainWindow *parent)
{
}
snake::~snake()
{
}

之后,在mainwindow.h添加它的头文件#include "snack.h",并定义一个它的对象和初始化函数:

Snack *head;      //大蛇链表的头结点
void Snake_Init(int size);  

接着,在mainwindow.cpp的构造函数中实现调用Snack_Init函数实现大蛇的初始化:

Snake_Init(5);    //参数5代表大蛇的长度

注意:Snake_Init函数必须在“点心”的初始化之前调用。

之后,实现Snake_Init函数:

void MainWindow::Snack_Init(int size)
{
    head = new Snack(this);
    head->x = 400;
    head->y = 240;
    head->next = NULL;
    Snack *p = NULL;
    while(size--)
    {
        p = head;
        while(p->next != NULL)
        {
            p = p->next;
        }
        Snack *node = new Snack(this);
        node->x = p->x - SIZE;
        node->y = p->y;
        node->btn = new QPushButton(this);
        node->btn->setFixedSize(SIZE, SIZE);
        node->btn->move(node->x, node->y);
        p->next = node;
        node->next = NULL;
    }
    //snack head
    p = head->next;
    p->btn->setStyleSheet("border-image: url(:/new/prefix1/res/right.png);");
    //snack body
    while(p->next->next != NULL)
    {
        p = p->next;
        p->btn->setStyleSheet("border-image: url(:/new/prefix1/res/she.png);");
    }
    //snack tail
    p->next->btn->setStyleSheet("border-image: url(:/new/prefix1/res/tou_left.png);");
}

5、实现大蛇移动

接下来,我们我们将要用到一个定时器,实现大蛇的移动。

在mainwindow.h的类中实现添加如下代码:

QTimer *my_timer;    //定时器
Director dir;     //大蛇移动的方向void setBackground();

    void keyPressEvent(QKeyEvent *e
void setBackground();   //设置大蛇背景
    void keyPressEvent(QKeyEvent *e)  //键盘按键事件
public slots:
    void snake_run();   //定时器超时函数

在mainwindow.cpp的构建函数实现相关初始化:

my_timer = new QTimer(this);
connect(my_timer, &QTimer::timeout, this, &MainWindow::snake_run);  //将snack_run槽函数连接定时器的超时信号
my_timer->start(500);   //设置定时器的超时时间,并启动定时器
dir = RIGHT;    //大蛇初始向右移动

实现槽函数snake_run,实现大蛇移动。它的原理是:删除链表最后一个节点,在头结点后插入新节点——

void MainWindow::snack_run()
{
    switch (dir)
    {
        case UP:
        {
            Snake *node = new Snack(this);
            node->x = head->next->x;
            node->y = head->next->y - 20;
            node->btn = new QPushButton(this);
            node->btn->setFixedSize(20, 20);
            node->btn->move(node->x, node->y);
            node->next = head->next;
            head->next = node;
            break;
        }
        case RIGHT:
        {
            Snake *node = new Snack(this);
            node->x = head->next->x + 20;
            node->y = head->next->y;
            node->btn = new QPushButton(this);
            node->btn->setFixedSize(20, 20);
            node->btn->move(node->x, node->y);
            node->next = head->next;
            head->next = node;
            break;
        }
        case DOWN:
        {
            Snake *node = new Snack(this);
            node->x = head->next->x;
            node->y = head->next->y + 20;
            node->btn = new QPushButton(this);
            node->btn->setFixedSize(20, 20);
            node->btn->move(node->x, node->y);
            node->next = head->next;
            head->next = node;
            break;
        }
        case LEFT:
        {
            Snake *node = new Snack(this);
            node->x = head->next->x - 20;
            node->y = head->next->y;
            node->btn = new QPushButton(this);
            node->btn->setFixedSize(20, 20);
            node->btn->move(node->x, node->y);
            node->next = head->next;
            head->next = node;
            break;
        }
        default:
        break;
    }
    if(head->next->x < 20 || head->next->x >= 780 || head->next->y < 20 || head->next->y >= 460 || snake_crash())   //大蛇碰到周围的“墙壁”或撞到自己
    {
        my_timer->stop();   //停止定时器
        this->setStyleSheet("QMainWindow{border-image: url(:/new/prefix1/res/gameover.png);}");
        return ;
    }
    else if(head->next->x == dessert->x*20 && head->next->y == dessert->y*20)    //吃到美味“点心”
    {
        dessert->makeDessert(head);
    }
    else
    {
        Snack *p = head;
        while(p->next->next != NULL)
        {
            p = p->next;
        }
        delete(p->next->btn);
        delete(p->next);
        p->next = NULL;
    }
    setBackground();   //设置背景
}

实现setBackground函数,设置大蛇的背景:

void MainWindow::setBackground()
{
    switch (dir)
    {
        case UP:
        {
            head->next->btn->setStyleSheet("border-image: url(:/new/prefix1/res/up.png);");
            break;
        }
        case RIGHT:
        {
            head->next->btn->setStyleSheet("border-image: url(:/new/prefix1/res/right.png);");
            break;
        }
        case LEFT:
        {
            head->next->btn->setStyleSheet("border-image: url(:/new/prefix1/res/left.png);");
            break;
        }
        case DOWN:
        {
            head->next->btn->setStyleSheet("border-image: url(:/new/prefix1/res/down.png);");
            break;
        }
        default:
            break;
    }
    head->next->btn->show();
    Snack *pre = head->next;
    Snack *current = pre->next;
    Snack *next = current->next;
    while(next != NULL)
    {
        if(((pre->x<current->x) && (pre->y==current->y) && (current->x==next->x)&&(current->y>next->y))\
           || (next->x<current->x && current->y==next->y && pre->x==current->x && pre->y<current->y))
        {
            current->btn->setStyleSheet("border-image: url(:/new/prefix1/res/up_left.png);");
        }
        else if((pre->x<current->x && pre->y==current->y && current->x==next->x && current->y<next->y)\
           || (next->x<current->x && current->y==next->y && pre->x==current->x && pre->y>current->y))
        {
            current->btn->setStyleSheet("border-image: url(:/new/prefix1/res/left_down.png);");
        }
        else if((pre->x==current->x && pre->y>current->y && current->x<next->x && current->y==next->y)\
           || (next->x==current->x && current->y<next->y && pre->x>current->x && pre->y==current->y))
        {
            current->btn->setStyleSheet("border-image: url(:/new/prefix1/res/right_down.png);");
        }
        else if((pre->x==current->x && pre->y<current->y &¤t->x<next->x && current->y==next->y)\
           || (next->x==current->x && current->y>next->y && pre->x>current->x && pre->y==current->y))
        {
            current->btn->setStyleSheet("border-image: url(:/new/prefix1/res/up_right.png);");
        }
        else
        {
            current->btn->setStyleSheet("border-image: url(:/new/prefix1/res/she.png);");
        }
        current->btn->show();
        pre = pre->next;
        current = current->next;
        next = next->next;
    }
    if((pre->x<current->x) && (pre->y==current->y))
    {
        current->btn->setStyleSheet("border-image: url(:/new/prefix1/res/tou_right.png);");
    }
    else if(pre->x>current->x && pre->y==current->y)
    {
        current->btn->setStyleSheet("border-image: url(:/new/prefix1/res/tou_left.png);");
    }
    else if(pre->x==current->x && pre->y>current->y)
    {
        current->btn->setStyleSheet("border-image: url(:/new/prefix1/res/tou_up.png);");
    }
    else if(pre->x==current->x && pre->y<current->y)
    {
        current->btn->setStyleSheet("border-image: url(:/new/prefix1/res/tou_down.png);");
    }
    current->btn->show();
}

实现keyPressEvent函数,控制大蛇的方向(w、a、s、d分别对应上、左、下、右):

void MainWindow::keyPressEvent(QKeyEvent *e)
{
    switch (e->key())
    {
        case Qt::Key_W:
        {
            if(dir != DOWN) dir = UP;
            break;
        }
        case Qt::Key_A:
        {
            if(dir != RIGHT) dir = LEFT;
            break;
        }
        case Qt::Key_D:
        {
            if(dir != LEFT) dir = RIGHT;
            break;
        }
        case Qt::Key_S:
        {
            if(dir != UP) dir = DOWN;
            break;
        }
        default:
            break;
    }
}

实现snake_crash函数,检测大蛇有没有”吃"到自己:

bool MainWindow::snake_crash()
{
    Snake *h = head->next;
    Snack *p = h->next;
    while (p != NULL)
    {
        if(h->x == p->x && h->y == p->y)
        {
            return true;
        }
        p = p->next;
    }
    return false;
}

至此,“贪吃蛇”游戏已制作完成,大家可运行测试,自己玩以下自己亲手制作的游戏。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表