康威生命游戏
1.MobaXterm个人版升级专业版2.VS studio上查看标准cout输出3.MQTT broker部署与测试4.局部变量的引用传递的风险5.cmake交叉编译6.“编码器UVW故障或内部故障”解决方法
7.康威生命游戏
8.C++标准库joinable和join的用法9.上传代码到新的远程仓库的方法10.Ubuntu查看包信息命令11.段错误的形成原因12.C++陷阱—指定的返回类型的函数实际没有返回时会发生什么13.python sklearn包的安装14.C++编译器对溢出的默认处理15.安装nginx时报错解决(configure error: the HTTP gzip module requires the zlib library)16.C++观察者模式的实现17.C++陷阱 — C++ auto变量类型推导18.浅谈数字证书19.C++之#和##符号的用法20.常用快排算法实现21.linux C++程序测试命令的一种实现22.几种常用数据结构的C语言实现23.umount命令提示busy无法正常卸载的解决24.关于C++作用域符的一种用法25.二维字符串数组的传参时与指针互转时的问题26.C语言月份字符转月份数值实现27.C语言实现split函数28.在代码中获得linux shell命令执行结果的方法29.CMake通过外部传参执行不同逻辑的2种方案30.模板函数使用类型推导时的bug31.Qt程序加载Qt platform plugin 'xcb' 出错问题解决32.cmake 之make pack报错解决简介
约翰·康威全名John Horton Conway,1937年12月26日出生于英国利物浦。他少时便对数学感兴趣,后来进入剑桥大学攻读数学专业,终于如愿以偿成了数学家。他活跃于有限群的研究、趣味数学、纽结理论、数论、组合博弈论和编码学等范畴。
约翰·康威最常被专业人士和大众拿来讨论的成果,就是他在1970年发明的生命游戏,Game of Life。它的意义在于验证了某些科学家的宇宙观,即最简单的逻辑规则能产生出复杂有趣的活动。
康威生命游戏是一个类似于模拟细胞存活的小游戏,规则虽然很简单,但它的魅力在于,不同的初始分布,最终会演化出许多有意思和意想不到的图案,其内涵无比的丰富。
规则
康威生命游戏在方格网上进行,有点像围棋。有填充的网格代表有生命,或理解成一个细胞。游戏规则只有四条:
- 当周围仅有1个或没有存活细胞时,原来的存活细胞进入死亡状态。(模拟生命数量稀少)
- 当周围有2个或3个存活细胞时, 网格保持原样。
- 当周围有4个及以上存活细胞时,原来的存活细胞亦进入死亡状态。(模拟生命数量过多)
- 当周围有3个存活细胞时,空白网格变成存活细胞。(模拟繁殖)
康威生命游戏的四条规则一目了然地对应着宇宙中的生命规律,它是一种元胞自动机(cellular automaton),体现了冯·诺依曼(Von Neumann)关于机器自我进化的思想。
实现
本人基于QT的一个实现,项目地址如下:
https://gitee.com/HuangLiDi/live-game.git
其核心代码非常简单,请参考最后的附录
参考文章
其有趣玩法和规则可以参考以下这两篇文章:
https://zhuanlan.zhihu.com/p/144162012
https://zhuanlan.zhihu.com/p/45026142
附录:核心代码
class CellsItem : public QGraphicsItem
{
public:
CellsItem();
explicit CellsItem(QRectF rect);
void SetRect(QRectF rect);
void SetBrush(const QColor & color);
void SetPen(const QPen & pen);
bool IsLive();
void setLive(bool live);
void setNextLiveState(bool live);
void Evolution();
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
private:
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
virtual QRectF boundingRect() const override;
QColor m_color;
QPen m_pen;
QRectF m_rect;
bool m_blLive = false;
bool m_bl_next = false;
};
class LivePlay
{
public:
static void play(int num, CellsItem *** cell_arry);
private:
static bool ruleCheck(int row, int column,int limit, CellsItem *** cell_arry);
};
CellsItem::CellsItem()
{
m_rect = QRectF(0,0,0,0);
m_color = Qt::white;
m_pen.setStyle(Qt::SolidLine);
m_pen.setWidth(1);
m_pen.setColor(Qt::lightGray);
setFlags(ItemIsSelectable);
setAcceptHoverEvents(true);
}
CellsItem::CellsItem(QRectF rect)
{
m_rect = rect;
m_color = Qt::black;
m_pen.setStyle(Qt::SolidLine);
m_pen.setWidth(1);
m_pen.setColor(Qt::lightGray);
setFlags(ItemIsSelectable);
setAcceptHoverEvents(true);
}
void CellsItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsItem::mousePressEvent(event);
m_blLive = !m_blLive;
update();
}
void CellsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsItem::mouseReleaseEvent(event);
update();
}
void CellsItem::SetRect(QRectF rect)
{
m_rect = rect;
}
void CellsItem::SetBrush(const QColor & color)
{
m_color = color;
}
void CellsItem::SetPen(const QPen & pen)
{
m_pen = pen;
}
bool CellsItem::IsLive()
{
return m_blLive;
}
void CellsItem::setLive(bool live)
{
m_blLive = live;
}
void CellsItem::setNextLiveState(bool live)
{
m_bl_next = live;
}
void CellsItem::Evolution()
{
if(m_blLive != m_bl_next)
{
m_blLive = m_bl_next;
update();
}
}
QRectF CellsItem::boundingRect() const
{
return m_rect;
}
void CellsItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
Q_UNUSED(widget);
#if 0
QColor fillColor = (option->state & QStyle::State_Selected) ? m_color : Qt::white;
#else
QColor fillColor = m_blLive ? m_color : Qt::white;
#endif
// if (option->state & QStyle::State_MouseOver)
// fillColor = fillColor.light(125);
painter->setPen(m_pen);
painter->fillRect(m_rect.adjusted(1,1,-1,-1), fillColor);
painter->drawRect(m_rect);
}
void LivePlay::play(int num, CellsItem *** cell_arry)
{
QList<QPair<int,int>> lst_play;
//细胞状态检查, 当前状态不变
for (int i = 0; i < num; i++){
for (int j = 0; j < num; j++){
bool ret = ruleCheck(i, j, num, cell_arry);
if (ret != cell_arry[i][j]->IsLive()){
cell_arry[i][j]->setNextLiveState(ret);
lst_play.append(qMakePair(i,j));
}
}
}
//进入细胞的下一个状态
for(const QPair<int,int> & pair: lst_play)
{
cell_arry[pair.first][pair.second]->Evolution();
}
}
bool LivePlay::ruleCheck(int row, int column, int limit, CellsItem *** cell_arry)
{
if(nullptr == cell_arry[row][column]){
return false;
}
CellsItem * p_Item = cell_arry[row][column];
int count = 0;
//检测周围一圈的细胞存活个数
for (int i = -1; i <= 1; i++){
for (int j = -1; j <= 1; j++) {
if (i == 0 && j == 0){
continue;
}
int r = row+i;
int l = column+j;
if (r >= 0 && r < limit
&& l >= 0 && l < limit){
if (cell_arry[r][l] && cell_arry[r][l]->IsLive())
count++;
}
}
}
if(p_Item->IsLive()){
//规则:孤独会致命,拥挤也一样
if (count <= 1 || count >= 4){
return false;
}
}
else {
//规则2:三人行,繁殖的最佳环境
if (count == 3){
return true;
}
}
return p_Item->IsLive();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!