c++ opengl实现Wolfram一维细胞自动机

188 阅读2分钟

细胞自动机简介

乌尔姆(Stanislaw M. Ulam)和冯·诺伊曼(John von Neumann)为了研究机器人自我复制的可能性,在上个世纪50年代提出一种叫做细胞自动机(Cellular Automaton)的离散型动力系统(Discrete Dynamical Systems)。细胞自动机是研究复杂系统行为的理论框架之一,也是人工智能在这个领域的雏形之一。1982年Wolfram发表了第一篇关于细胞自动机的学术论文,由此开始了对细胞自动机的研究。Wolfram着重研究空间维度为二维的细胞自动机。细胞可能具有的状态只有两种,用颜色表示成黑色或白色。全体细胞中的每一个只根据上一迭代过程中与该细胞紧相邻的三个细胞的状态来决定自己下一步的状态,所有细胞在根据上一步结果确定自己在这一步中将有的状态后,全体细胞同时改变自己的状态到新状态。其结果和细胞自动机的初始条件很有关系。被这样设定的细胞自动机叫做一维细胞自动机。 用文字来叙述就是:当某细胞的上一行相邻三个细胞为全黑、全白或者左侧一个细胞为黑时,该细胞为白色,否则为黑色。设定一个简单的细胞初始状态,譬如在第一行只有一个黑色细胞,根据规则110,细胞自动机就可以自动把其余的细胞变成黑色或保留白色。那么下面用来c++和opengl来实现第30号宇宙的图形,也就是我们现在的宇宙。

代码实现

#include <GL/glut.h>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
using namespace std;
const int WINDOW_WIDTH = 800, WINDOW_HEIGHT = 800;
const int MAP_SCALE = 4;
const int MAP_SIZE = WINDOW_HEIGHT / MAP_SCALE * 2;
int MAP[MAP_SIZE][MAP_SIZE];
static int nx = 30;//默认为30号宇宙
void Wolfram() {
  int rule[8];int n = nx;
  for (int i = 128, t = 7; t >= 0; i /= 2, --t) {
    if (n >= i) {
      rule[t] = 1; n -= i;
    } else
      rule[t] = 0;
  }
  MAP[MAP_SIZE / 2][MAP_SIZE - 1] = 1;
  glClear(GL_COLOR_BUFFER_BIT);
  glColor3f(0.1, 0.1, 0.1);
  glBegin(GL_QUADS);
  glVertex2d(MAP_SIZE / 2 - 0.5, MAP_SIZE - 0.5);
  glVertex2d(MAP_SIZE / 2 - 0.5, MAP_SIZE - 1.5);
  glVertex2d(MAP_SIZE / 2 + 0.5, MAP_SIZE - 1.5);
  glVertex2d(MAP_SIZE / 2 + 0.5, MAP_SIZE - 0.5);
  glEnd();
  glFlush();
  for (int i = MAP_SIZE - 2; i >= 0; --i) {
    for (int j = 0; j < MAP_SIZE; j++) {
      int t = MAP[(j - 1 + MAP_SIZE) % MAP_SIZE][i + 1] * 4 +
              MAP[j][i + 1] * 2 + MAP[(j + 1 + MAP_SIZE) % MAP_SIZE][i + 1];
      MAP[j][i] = rule[t];
    }
    glBegin(GL_QUADS);
    for (int j = 0; j < MAP_SIZE; ++j)
      if (MAP[j][i]) {
        glVertex2d(j - 0.5, i + 0.5);
        glVertex2d(j - 0.5, i - 0.5);
        glVertex2d(j + 0.5, i - 0.5);
        glVertex2d(j + 0.5, i + 0.5);
      }
    glEnd();
    glFlush();
  }
}
int main(int argc, char **argv) {
  glutInit(&argc, argv);
  if (argc == 2) {
    nx = atoi(argv[1]);
  }
  glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
  glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
  glutCreateWindow("OpenGL");
  glClearColor(1.0, 1.0, 1.0, 0.0);
  glMatrixMode(GL_PROJECTION);
  gluOrtho2D(0.0, GLdouble(MAP_SIZE), 0.0, GLdouble(MAP_SIZE));
  glutDisplayFunc(&Wolfram);
  glutMainLoop();
}

运行效果

下面这里呢,是演示86号宇宙。输入参数表示多少号宇宙,然后运行程序打印该宇宙【也就是我们所在30号宇宙的反码】 image.png

温馨提示

题外话,至于opengl如何编译,或者是如何使用我就不说了。会编译的人,就可以运行,我呢人狠话不多,那如果你不狠,那请勿尝试。