资讯专栏INFORMATION COLUMN

C++Qt开发-单线程实现生命游戏

szysky / 2339人阅读

摘要:生命游戏规则生命游戏中,对于任意细胞每个细胞有两种状态存活或死亡。每个细胞与以自身为中心的周围八格细胞产生互动。繁衍函数死亡函数生存和死亡函数,由函数调用。

生命游戏规则:

生命游戏中,对于任意细胞:
   每个细胞有两种状态:存活或死亡。每个细胞与以自身为中心的周围八格细胞产生互动。

1.当前细胞为存活状态时,当周围的活细胞低于2个时, 该细胞因孤独而死亡;
   2.当前细胞为存活状态时,当周围有2个或3个活细胞时, 该细胞保持原样;
   3.当前细胞为存活状态时,当周围有3个以上活细胞时,该细胞因资源匮乏而死亡;

4.当前细胞为死亡状态时,当周围有3个活细胞时,该细胞变成存活状态(模拟繁殖)。

活细胞的周围只能有2个或3个细胞,否则死亡。
死细胞的周围如果有3个活细胞,复活。
否则不变。
黑格代表活细胞,白格代表死细胞

QT代码实现:

0.实现思路

设置widget主页面的长宽,确定像素范围。
选取像素宽度,画线
通过随机数生成随机细胞,使用矩形填充代表细胞,因为矩形有四个点,我们以左上角的点为枢纽点
确定像素位置关系后,填充
实现生命游戏算法函数
使用定时器,定时调用函数,刷新widget,自动调用painterEvent事件,完成下一次绘画

1.因为要画图,使用widget类

2.widget.h

#ifndef WIDGET_H#define WIDGET_H#include #include #include #include #include #include #include #include  //取整函数#include  //随机数函数#include  //调式用#include #include  // 定时器#include #define SIZE 800 //6400个细胞面板,640000个像素点,数组保存的是像素面板,不要改#define TIME 100 //定时器事件间隔,可以改#define Cells 3000 //总共有6400个方格,首先随机生成活细胞,可以改QT_BEGIN_NAMESPACEnamespace Ui { class Widget; }QT_END_NAMESPACEclass Widget : public QWidget{    Q_OBJECTpublic:    Widget(QWidget *parent = nullptr);    ~Widget();private:    int TimerId; //定时器ID    QVector<QLineF> Lines; //保存线,用于画方格    QVector<QPair<int,int>> CellsPoint; //保存每个细胞的坐标,用于遍历时减少循环,用于绘图    QVector<QPair<int,int>> NextCellsPoint; //用于存放下一次细胞矩阵的坐标,用于绘图    int LiveCells[SIZE][SIZE]; //用于保存活细胞的方格,1代表活,0代表死,用于算法    int NextLiveCells[SIZE][SIZE];//用于存放下一次细胞矩阵的容器    //int (* LiveCells)[SIZE] = new int[SIZE][SIZE];    //int (* NextLiveCells)[SIZE] = new int[SIZE][SIZE];    Ui::Widget *ui;protected:    //TopLeft    int TopLeft(int x,int y);    //TopRight    int TopRight(int x,int y);    //BottomRight    int BottomRight(int x,int y);    //BottomLeft    int BottomLeft(int x,int y);    //BottomSide    int BottomSide(int x,int y);    //TopSide    int TopSide(int x,int y);    //RightSide    int RightSide(int x,int y);    //LeftSide    int LeftSide(int x,int y);    //Mid    int Mid(int x,int y);    //面板更新和坐标容器更新    void UpData();    //生命游戏算法-生成下一次活细胞图    void NextCells();    //繁衍函数    void Multiply();    //死亡函数    bool Death(QPair<int,int> Point);    //遍历四周细胞函数    int Around(QPair<int,int> Point);    //保存画线的像素点    void LinesPoint();    //随机生成细胞函数    void RandomCells();    //重载绘画事件    //qt里所有的重载函数都是受保护的函数    void paintEvent(QPaintEvent *event);    //重载定时器事件    void timerEvent(QTimerEvent *event);private slots:    void on_pushButton_Random_clicked();    void on_pushButton_Start_clicked();    void on_pushButton_Stop_clicked();};#endif // WIDGET_H

函数功能分析

    //TopLeft    int TopLeft(int x,int y);    //TopRight    int TopRight(int x,int y);    //BottomRight    int BottomRight(int x,int y);    //BottomLeft    int BottomLeft(int x,int y);    //BottomSide    int BottomSide(int x,int y);    //TopSide    int TopSide(int x,int y);    //RightSide    int RightSide(int x,int y);    //LeftSide    int LeftSide(int x,int y);    //Mid    int Mid(int x,int y);

实现判断(x,y)处的细胞周围的细胞数,这些函数由Around函数调用实现。

    //繁衍函数    void Multiply();    //死亡函数    bool Death(QPair<int,int> Point);

生存和死亡函数,由NextCells函数调用。

    //面板更新和坐标容器更新    void UpData();

更新函数,完成必要容器和数组的更新重置

    //保存画线的像素点    void LinesPoint();

保存线的点集合

widget.cpp

#include "widget.h"#include "ui_widget.h"Widget::Widget(QWidget *parent)    : QWidget(parent)    , ui(new Ui::Widget){    ui->setupUi(this);}Widget::~Widget(){    delete ui;}int Widget::TopLeft(int x,int y){    int around = 0;    if(LiveCells[x+10][y] == 1)    {        around++;    }    if(LiveCells[x][y+10] == 1)    {        around++;    }    if(LiveCells[x+10][y+10] == 1)    {        around++; //TopLeft    }    return around;}int Widget::TopSide(int x,int y){    int around = 0;    if(LiveCells[x-10][y] == 1)    {        around++;    }    if(LiveCells[x+10][y] == 1)    {        around++;    }    if(LiveCells[x-10][y+10] == 1)    {        around++;    }    if(LiveCells[x][y+10] == 1)    {        around++;    }    if(LiveCells[x+10][y+10] == 1)    {        around++;    }    return around;}int Widget::TopRight(int x,int y){    int around = 0;    if(LiveCells[x-10][y] == 1)    {        around++;    }    if(LiveCells[x-10][y+10] == 1)    {        around++;    }    if(LiveCells[x][y+10] == 1)    {        around++;    }    return around;}int Widget::RightSide(int x,int y){    int around = 0;    if(LiveCells[x][y-10] == 1)    {        around++;    }    if(LiveCells[x-10][y-10] == 1)    {        around++;    }    if(LiveCells[x-10][y] == 1)    {        around++;    }    if(LiveCells[x-10][y+10] == 1)    {        around++;    }    if(LiveCells[x][y+10] == 1)    {        around++;    }    return around;}int Widget::LeftSide(int x,int y){    int around = 0;    if(LiveCells[x][y-10] == 1)    {        around++;    }    if(LiveCells[x+10][y-10] == 1)    {        around++;    }    if(LiveCells[x+10][y] == 1)    {        around++;    }    if(LiveCells[x+10][y+10] == 1)    {        around++;    }    if(LiveCells[x][y+10] == 1)    {        around++;    }    return around;}int Widget::Mid(int x,int y){    int around = 0;    if(LiveCells[x-10][y-10] == 1)    {        around++; //TopLeft    }    if(LiveCells[x][y-10] == 1)    {        around++; //TopMid    }    if(LiveCells[x+10][y-10] == 1)    {        around++; //TopRight    }    if(LiveCells[x-10][y] == 1)    {        around++; //Left    }    if(LiveCells[x+10][y] == 1)    {        around++; //Left    }    if(LiveCells[x-10][y+10] == 1)    {        around++; //BottomLeft    }    if(LiveCells[x][y+10] == 1)    {        around++; //BottomMid    }    if(LiveCells[x+10][y+10] == 1)    {        around++; //BottomRight    }    return around;}int Widget::BottomLeft(int x,int y){    int around = 0;    if(LiveCells[x][y-10] == 1)    {        around++;    }    if(LiveCells[x+10][y-10] == 1)    {        around++;    }    if(LiveCells[x+10][y] == 1)    {        around++;    }    return around;}int Widget::BottomSide(int x,int y){    int around = 0;    if(LiveCells[x-10][y] == 1)    {        around++;    }    if(LiveCells[x-10][y-10] == 1)    {        around++;    }    if(LiveCells[x][y-10] == 1)    {        around++;    }    if(LiveCells[x+10][y-10] == 1)    {        around++;    }    if(LiveCells[x+10][y] == 1)    {        around++;    }    return around;}int Widget::BottomRight(int x,int y){    int around = 0;    if(LiveCells[x][y-10] == 1)    {        around++;    }    if(LiveCells[x-10][y-10] == 1)    {        around++;    }    if(LiveCells[x-10][y] == 1)    {        around++;    }    return around;}//面板更新和坐标容器更新void Widget::UpData(){    CellsPoint.clear();    CellsPoint = NextCellsPoint; // 将下一次细胞坐标赋值给CellsPoint    NextCellsPoint.clear(); //清空    for(int i =0;i<SIZE;i++)    {        for(int j =0;j<SIZE;j++)        {            LiveCells[i][j] = NextLiveCells[i][j];        }    }    memset(NextLiveCells, 0, SIZE*SIZE*4); //清空}//生命游戏算法-生成下一次活细胞坐标容器void Widget::NextCells(){    //模拟繁殖,死亡,不变    Multiply();    //面板赋值和坐标赋值    UpData();    return;}//模拟繁殖,死亡,不变void Widget::Multiply(){    for(int i=0; i<SIZE; i+=10)    {        for(int j=0; j<SIZE; j+=10)        {            if(LiveCells[i][j] == 0)            {                QPair<int,int> Point(i,j);                int around = Around(Point);                if(around == 3)                {                    //复活该细胞                    NextCellsPoint.push_back(Point); //复活坐标容器                    NextL           
               
                                           
                       
                 

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/122335.html

相关文章

  • 游戏开发

    摘要:工欲善其事必先利其器游戏环境对比发表算法在游戏上超过人类之后,游戏研究迅速成为了研究热点。当然这不是网络游戏服务器架构概述一架构模型现代电子游戏,基本上都会使用一定的网络功能。 每个程序员都需要知道一些游戏网络知识 本文主要针对游戏的网络设计,在文章中目前主流的网络游戏实现方案都有讲解。从Peer-to-Peer 帧同步,客户端/服务器(c/s架构),客户端预测(Client-Side...

    Enlightenment 评论0 收藏0
  • [原创]nim与rust的特点比较

    摘要:与的特点比较这两个目前都是小众语言做了些时间的研究写了点东西有了点心得相似点有卫生宏区别与的不卫生宏在类或定义体之外定义函数代码没有分成头与实现体例如的头与实现的与定义的接口定义与实现定义是分开的而与是不分开的运用函数式编程高阶函数目前是新 nim与rust的特点比较 这两个目前都是小众语言,做了些时间的研究,写了点东西有了点心得 相似点: 有卫生宏.区别与C++的(不卫生)宏 在类...

    DevTalking 评论0 收藏0

发表评论

0条评论

szysky

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<