生命游戏中,对于任意细胞:
每个细胞有两种状态:存活或死亡。每个细胞与以自身为中心的周围八格细胞产生互动。
1.当前细胞为存活状态时,当周围的活细胞低于2个时, 该细胞因孤独而死亡;
2.当前细胞为存活状态时,当周围有2个或3个活细胞时, 该细胞保持原样;
3.当前细胞为存活状态时,当周围有3个以上活细胞时,该细胞因资源匮乏而死亡;
4.当前细胞为死亡状态时,当周围有3个活细胞时,该细胞变成存活状态(模拟繁殖)。
活细胞的周围只能有2个或3个细胞,否则死亡。
死细胞的周围如果有3个活细胞,复活。
否则不变。
黑格代表活细胞,白格代表死细胞
设置widget主页面的长宽,确定像素范围。
选取像素宽度,画线
通过随机数生成随机细胞,使用矩形填充代表细胞,因为矩形有四个点,我们以左上角的点为枢纽点
确定像素位置关系后,填充
实现生命游戏算法函数
使用定时器,定时调用函数,刷新widget,自动调用painterEvent事件,完成下一次绘画
#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界面



