标签:
昨晚在微信公众号看到 《有没有一段代码,让你觉得人类的智慧也可以璀璨无比》里面介绍了一个叫《Tweetable Mathematical Art》的代码游戏,看完我激动不已,这些人都太NB了。
我迫不及待要试一下,可惜该游戏原来的框架生成的图片上ppm格式的,在Windwos上打开比较麻烦,所以我索性写了一个生成bmp格式的代码框架。
如果有新idea的话可以在body.hpp中加入一个新类就可以了,这个代码框架可在linux和Windows上跑。
pic.hpp
#ifndef _PIC_HPP_ #define _PIC_HPP_ #include <cstdio> #include <cstring> class pic { public: pic() {} virtual ~pic() {} /* ----x------------------------------> | y | | v */ virtual void set(unsigned int x, unsigned int y, unsigned char r, unsigned char g, unsigned char b) = 0; bool save(const char * fname) { char * new_name = new char[strlen(fname) + strlen(ext) + 2]; sprintf(new_name, "%s.%s", fname, ext); FILE * f = fopen(new_name, "wb"); delete [] new_name; if(f == NULL) return false; fwrite(p, 1, sz, f); fclose(f); return true; } protected: unsigned char * p; unsigned int sz; unsigned int w; unsigned int h; char ext[8]; }; class ppm : public pic { public: ppm(unsigned int width, unsigned int height) { w = width & 0xFFF; h = height & 0xFFF; char hdr[64]; sprintf(hdr, "P6\n%u %u\n255\n", w, h); hdr_offset = strlen(hdr); sz = hdr_offset + (w * h * 3); p = new unsigned char[sz]; memcpy(p, hdr, hdr_offset); memset(p + hdr_offset, 0xFF, sz - hdr_offset); strcpy(ext, "ppm"); } void set(unsigned int x, unsigned int y, unsigned char r, unsigned char g, unsigned char b) { if(x < w && y < h) { unsigned int offset = hdr_offset + (w * 3 * y) + (x * 3); p[offset] = r; p[offset + 1] = g; p[offset + 2] = b; } } ~ppm() { delete [] p; } private: unsigned int hdr_offset; }; class bmp : public pic { public: bmp(unsigned int width, unsigned int height) { w = width & 0xFFF; h = height & 0xFFF; w3 = (w * 3 + 3) & ~3; sz = 54 + (w3 * h); p = new unsigned char[sz]; memset(p, 0, 54); memset(p + 54, 0xFF, sz - 54); p[0] = ‘B‘; p[1] = ‘M‘; p[2] = sz; p[3] = sz >> 8; p[4] = sz >> 16; p[5] = sz >> 24; p[10] = 54; p[14] = 40; p[18] = w; p[19] = w >> 8; p[22] = h; p[23] = h >> 8; p[26] = 1; p[28] = 24; p[34] = sz - 54; p[35] = (sz - 54) >> 8; p[36] = (sz - 54) >> 16; p[37] = (sz - 54) >> 24; strcpy(ext, "bmp"); } ~bmp() { delete [] p; } void set(unsigned int x, unsigned int y, unsigned char r, unsigned char g, unsigned char b) { if(x < w && y < h) { unsigned int offset = 54 + w3 * (h - 1 - y) + x * 3; p[offset] = b; p[offset + 1] = g; p[offset + 2] = r; } } private: unsigned int w3; }; #endif
core.hpp
#ifndef _CORE_HPP_ #define _CORE_HPP_ #include <cstring> #include <cstdlib> #include <cstdio> struct core { core() { DIM = 1024; } virtual ~core() {} virtual unsigned char RD(int i, int j) = 0; virtual unsigned char GR(int i, int j) = 0; virtual unsigned char BL(int i, int j) = 0; unsigned int DIM; }; typedef core * (*INIT_FUNC_PTR)(); struct name_class { char name[64]; INIT_FUNC_PTR func; }; static unsigned int n_c_num = 0; static name_class n_c_list[128]; static int reg_n_c(const char * name, INIT_FUNC_PTR func){ if(strlen(name) >= sizeof(n_c_list[0].name) || n_c_num >= sizeof(n_c_list)/sizeof(n_c_list[0])) { printf("Error at %s line %d\n", __FILE__, __LINE__); exit(1); } strcpy(n_c_list[n_c_num].name, name); n_c_list[n_c_num].func = func; n_c_num++; return 0; } #define REG(NAME) static core * NAME##_init() { return new NAME; } static int NAME##_reg_ = reg_n_c(#NAME, NAME##_init); #endif
body.hpp
#ifndef _BODY_HPP_ #define _BODY_HPP_ #include "core.hpp" #include <cmath> #define _sq(x) ((x)*(x)) // square #define _cb(x) abs((x)*(x)*(x)) // absolute value of cube #define _cr(x) (unsigned char)(pow((x),1.0/3.0)) // cube root // // // // // // struct colorful : public core { unsigned char RD(int i,int j){ return (char)(_sq(cos(atan2(j-512.,i-512)/2))*255); } unsigned char GR(int i,int j){ return (char)(_sq(cos(atan2(j-512.,i-512)/2-2*acos(-1.)/3))*255); } unsigned char BL(int i,int j){ return (char)(_sq(cos(atan2(j-512.,i-512)/2+2*acos(-1.)/3))*255); } }; REG(colorful); struct flat : public core { unsigned char RD(int i,int j){ float s=3./(j+99); return (int((i+DIM)*s+j*s)%2+int((DIM*2-i)*s+j*s)%2)*127; } unsigned char GR(int i,int j){ float s=3./(j+99); return (int((i+DIM)*s+j*s)%2+int((DIM*2-i)*s+j*s)%2)*127; } unsigned char BL(int i,int j){ float s=3./(j+99); return (int((i+DIM)*s+j*s)%2+int((DIM*2-i)*s+j*s)%2)*127; } }; REG(flat); struct ripple : public core { unsigned char RD(int i,int j){ float s=3./(j+99); float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s; return (int((i+DIM)*s+y)%2+int((DIM*2-i)*s+y)%2)*127; } unsigned char GR(int i,int j){ float s=3./(j+99); float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s; return (int((i+DIM)*s+y)%2+int((DIM*2-i)*s+y)%2)*127; } unsigned char BL(int i,int j){ float s=3./(j+99); float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s; return (int((i+DIM)*s+y)%2+int((DIM*2-i)*s+y)%2)*127; } }; REG(ripple); struct cripple : public core { unsigned char RD(int i,int j){ float s=3./(j+99); float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s; return (int((i+DIM)*s+y)%2+int((DIM*2-i)*s+y)%2)*127; } unsigned char GR(int i,int j){ float s=3./(j+99); float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s; return (int(5*((i+DIM)*s+y))%2+int(5*((DIM*2-i)*s+y))%2)*127; } unsigned char BL(int i,int j){ float s=3./(j+99); float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s; return (int(29*((i+DIM)*s+y))%2+int(29*((DIM*2-i)*s+y))%2)*127; } }; REG(cripple); struct randx: public core { #define r(n)(rand()%n) unsigned char RD(int i,int j){ static char c[1024][1024];return!c[i][j]?c[i][j]=!r(999)?r(256):RD((i+r(2))%1024,(j+r(2))%1024):c[i][j]; } unsigned char GR(int i,int j){ static char c[1024][1024];return!c[i][j]?c[i][j]=!r(999)?r(256):GR((i+r(2))%1024,(j+r(2))%1024):c[i][j]; } unsigned char BL(int i,int j){ static char c[1024][1024];return!c[i][j]?c[i][j]=!r(999)?r(256):BL((i+r(2))%1024,(j+r(2))%1024):c[i][j]; } }; REG(randx); struct omg1: public core { unsigned char RD(int i,int j){ float x=0,y=0;int k;for(k=0;k++<256;){float a=x*x-y*y+(i-768.0)/512;y=2*x*y+(j-512.0)/512;x=a;if(x*x+y*y>4)break;}return k>31?256:k*8; } unsigned char GR(int i,int j){ float x=0,y=0;int k;for(k=0;k++<256;){float a=x*x-y*y+(i-768.0)/512;y=2*x*y+(j-512.0)/512;x=a;if(x*x+y*y>4)break;}return k>63?256:k*4; } unsigned char BL(int i,int j){ float x=0,y=0;int k;for(k=0;k++<256;){float a=x*x-y*y+(i-768.0)/512;y=2*x*y+(j-512.0)/512;x=a;if(x*x+y*y>4)break;}return k; } }; REG(omg1); struct omg2: public core { unsigned char RD(int i,int j){ double a=0,b=0,c,d,n=0; while((c=a*a)+(d=b*b)<4&&n++<880) {b=2*a*b+j*8e-9-.645411;a=c-d+i*8e-9+.356888;} return 255*pow((n-80)/800,3.); } unsigned char GR(int i,int j){ double a=0,b=0,c,d,n=0; while((c=a*a)+(d=b*b)<4&&n++<880) {b=2*a*b+j*8e-9-.645411;a=c-d+i*8e-9+.356888;} return 255*pow((n-80)/800,.7); } unsigned char BL(int i,int j){ double a=0,b=0,c,d,n=0; while((c=a*a)+(d=b*b)<4&&n++<880) {b=2*a*b+j*8e-9-.645411;a=c-d+i*8e-9+.356888;} return 255*pow((n-80)/800,.5); } }; REG(omg2); // // // // // // #endif
main.cc
/* http://www.zhihu.com/question/30262900 http://www.matrix67.com/blog/archives/6039 http://codegolf.stackexchange.com/questions/35569/tweetable-mathematical-art */ #include "body.hpp" #include "pic.hpp" int main(int argc, char * argv[]) { if(argc != 3) { printf("Usage: %s <-all|name> <bmp|ppm>\n", argv[0]); printf("name list:\n"); for(unsigned int i = 0; i < n_c_num; i++) { printf("\t%s\n", n_c_list[i].name); } return 1; } for(unsigned int i = 0; i < n_c_num; i++) { if(strcmp(argv[1], "-all")==0 || strcmp(argv[1], n_c_list[i].name)==0) { core * c = n_c_list[i].func(); pic * p; if(argv[2][0] == ‘b‘) { p = new bmp(c->DIM, c->DIM); } else { p = new ppm(c->DIM, c->DIM); } for(unsigned int y = 0; y < c->DIM; y++) for(unsigned int x = 0; x < c->DIM; x++) p->set(x, y, c->RD(x,y), c->GR(x,y), c->BL(x,y)); p->save(n_c_list[i].name); delete p; delete c; } } return 0; }
Makefile
all:: exe ./math_art -all bmp exe:: g++ -Wall main.cc -lm -o math_art clean:: rm -f math_art *.bmp *.ppm
build.bat
@call "C:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86 @del *.bmp 2>nul @cl main.cc & main.exe -all bmp & del main.obj main.exe @pause
Tweetable Mathematical Art 代码框架
标签:
原文地址:http://my.oschina.net/2bit/blog/498193