栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

生命游戏规则:

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

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_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:

    int TimerId; //定时器ID
    QVector Lines; //保存线,用于画方格
    QVector> CellsPoint; //保存每个细胞的坐标,用于遍历时减少循环,用于绘图
    QVector> 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 Point);

    //遍历四周细胞函数
    int Around(QPair 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 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 Point(i,j);
                int around = Around(Point);
                if(around == 3)
                {
                    //复活该细胞
                    NextCellsPoint.push_back(Point); //复活坐标容器
                    NextLiveCells[i][j] = 1;
                }
                else
                {
                    NextLiveCells[i][j] = 0;
                }
            }
            if(LiveCells[i][j] == 1)
            {
                //孤独或者饥饿而死
                QPair Point(i,j);
                int around = Around(Point);
                if(around > 3 || around < 2)
                {
                    NextLiveCells[i][j] = 0;
                }
                else
                {
                    NextCellsPoint.push_back(Point); //复活坐标容器
                    NextLiveCells[i][j] = 1;
                }
            }
        }
    }
}

//遍历周围细胞函数
int Widget::Around(QPair Point)
{
    int around = 0;
    int x, y;
    x = Point.first;
    y = Point.second;
    

    if(x==0 && y==0)
    {
        around = TopLeft(x,y);
        return around;
    }

    if(x==890 && y==0)
    {
        around = TopRight(x,y);
        return around;
    }

    if(x==0 && y==890)
    {
        around = BottomLeft(x,y);
        return around;
    }

    if(x==890 && y==890)
    {
        around = BottomRight(x,y);
        return around;
    }

    if(y==0)
    {
        around = TopSide(x,y);
        return around;
    }

    if(x==0)
    {
        around = LeftSide(x,y);
        return around;
    }

    if(x==890)
    {
        around = RightSide(x,y);
        return around;
    }

    if(y==890)
    {
        around = BottomSide(x,y);
        return around;
    }
    around = Mid(x,y);
    return around;
}

//首先,随机生成活细胞-黑色
void Widget::RandomCells()
{
    //qDebug() << " RandomCells " << endl;
    
    int x,y,x1,y1;
    for(int i=0; i pair(x,y);
        CellsPoint.push_back(pair);
        //放入LiveCells数组
        LiveCells[x][y] = 1;
    }
}

//添加方格线,每个各自的边长为10
void Widget::LinesPoint()
{
    //qDebug() << " LinesPoint " << endl;
    int x,y,x1,y1;//点的坐标
    QPoint p,p1;
    QLineF line;
    for(int i = 0;i <=800;i+= 10)
    {
        y = 0;
        x = i;
        y1 = 800;
        x1 = i;
        p.setX(x);
        p.setY(y);
        p1.setX(x1);
        p1.setY(y1);
        line.setPoints(p,p1);
        Lines.push_back(line);
        y = i;
        x = 0;
        y1 = i;
        x1 = 800;
        p.setX(x);
        p.setY(y);
        p1.setX(x1);
        p1.setY(y1);
        line.setPoints(p,p1);
        Lines.push_back(line);
    }
}

//所有显示的画图,必须直接或者简洁的调用画图事件,否则显示不出来
void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this); //创建画家类
    LinesPoint(); //绘制方格
    QPen pen;
    pen.setColor(Qt::black);
    pen.setWidth(1);
    painter.setPen(pen);
    painter.drawLines(Lines); //画方格
    QBrush brush; //设置填充笔刷
    brush.setColor(QColor(Qt::black)); //填充颜色
    brush.setStyle(Qt::SolidPattern); //填充形式-实色填充

    //填充细胞
    int num = 0;
    int x,y;
    while(num != CellsPoint.size())
    {
        x = CellsPoint.at(num).first;
        y = CellsPoint.at(num).second;
        painter.fillRect(QRect(QPoint(x,y),QPoint(x+10, y+10)), brush);
        num++;
    }
}

void Widget::timerEvent(QTimerEvent *event)
{
    NextCells();
    this->update();
}

void Widget::on_pushButton_Random_clicked()
{
    CellsPoint.clear(); //清空
    memset(LiveCells, 0, SIZE*SIZE*4); //清空
    //生成初始细胞
    RandomCells();
    this->update();
}

void Widget::on_pushButton_Start_clicked()
{
    TimerId = Widget::startTimer(TIME);
}

void Widget::on_pushButton_Stop_clicked()
{
    Widget::killTimer(TimerId);
}

ui界面




转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/311875.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号