加賀一稿一記

心は戦国

ライフゲームの出力

知り合いがライフゲームを実装していたので,つい自分も実装してしまった.
SNSに投稿しやすいように動画を出力する仕様にした.

コードは次の通り.
頭の悪いことにMat上でシミュレーションしているので実装が汚い.
動画を出力するだけならもっと簡単に実装できる.
(2次元配列上で適当にシミュレーションして結果だけ毎回Matに入れてavi書き込み)

#include "opencv2/opencv.hpp"
#include <random>

const int W = 640;
const int H = 480;
const int frame = 600;

int tmp[W][H];

int main(){

	std::random_device rd;

	cv::Mat lg(H, W, CV_8U, cv::Scalar(255));
	for (int y = 0; y < H;y++){
		for (int x = 0; x < W;x++){
			if (rd() % 2 == 1)lg.data[y*W + x] = 0;
		}
	}

	cv::Mat tmpmat(H, W, CV_8UC3, cv::Scalar(255, 255, 255));
	int step = tmpmat.step;
	int elem = tmpmat.elemSize();
	
	cv::VideoWriter avi(
		"lifegame.avi",
		CV_FOURCC_DEFAULT,
		15,
		cv::Size(W, H),
		true
	);	

	for (int i = 0; i < frame; i++){
		for (int y = 0; y < H; y++){
			for (int x = 0; x < W; x++){
				for (int c = 0; c < 3; c++){
					tmpmat.data[y*step + x*elem + c] = lg.data[y*W + x];
				}
				tmp[x][y] = 0;
				for (int cy = -1; cy <= 1; cy++){
					for (int cx = -1; cx <= 1; cx++){
						int ty = (y + H + cy) % H;
						int tx = (x + W + cx) % W;
						if (ty == y&&tx == x)continue;
						if (lg.data[ty*W + tx] == 0)tmp[x][y]++;
					}
				}
			}
		}
		for (int y = 0; y < H; y++){
			for (int x = 0; x < W; x++){
				if (lg.data[y*W + x] == 255 && tmp[x][y] == 3)lg.data[y*W + x] = 0;
				if (lg.data[y*W + x] == 0 && (tmp[x][y] <= 1 || 4 <= tmp[x][y]))lg.data[y*W + x] = 255;
			}
		}
		avi << tmpmat;
	}

	return 0;
}