上周为了最美代码编程比赛水的一个小程序
我想到写这玩意首先是因为这个:
math – Tweetable Mathematical Art – Programming Puzzles & Code Golf Stack Exchange
这里面有一段很有意思的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#include <iostream> #include <cmath> #include <cstdlib> #define DIM 1024 #define DM1 (DIM-1) #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 unsigned char GR(int,int); unsigned char BL(int,int); unsigned char RD(int i,int j){ // YOUR CODE HERE } unsigned char GR(int i,int j){ // YOUR CODE HERE } unsigned char BL(int i,int j){ // YOUR CODE HERE } void pixel_write(int,int); FILE *fp; int main(){ fp = fopen("MathPic.ppm","wb"); fprintf(fp, "P6\n%d %d\n255\n", DIM, DIM); for(int j=0;j<DIM;j++) for(int i=0;i<DIM;i++) pixel_write(i,j); fclose(fp); return 0; } void pixel_write(int i, int j){ static unsigned char color[3]; color[0] = RD(i,j)&255; color[1] = GR(i,j)&255; color[2] = BL(i,j)&255; fwrite(color, 1, 3, fp); } |
在三个函数中插入相应代码并给出返回值便可以得出一些非常excited的图像
于是我就想着用这玩意生成一个北邮的校徽
然而函数拟合了好几个小时还是不行
然后又想着这比赛是华为赞助的,干脆做个华为的logo
然后又试着去拟合,还是不行……
然后想着我这么菜,干脆做个画横平竖直的好画的图像
于是就想到了蒙德里安:
他的画大概是这种风格:
是不是看起来很简单?
于是就写个段辣鸡代码试着生成这种风格的画
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
#pragma warning(disable:4996) #include <cstdio> #include <cmath> #include <cstdlib> #define DIM 1024 int R[3] = { 255,0,0 }; //定义选择的颜色 int G[3] = { 255,255,0 }; int B[3] = { 0,0,255 }; int BK[3] = { 0,0,0 }; int WT[3] = { 255,255,255 }; int drawing_board[1024][1024][3]; int wr = 1, wc = 1; FILE *fp; void fillcolor(int x1, int y1, int x2, int y2, int color[]) { //对一个区域进行上色 for (int i = x1; i <= x2; i++) for (int j = y1; j <= y2; j++) { drawing_board[i][j][0] = color[0]; drawing_board[i][j][1] = color[1]; drawing_board[i][j][2] = color[2]; } } void pixel_write(int i, int j) { //输出一个像素 static unsigned char color[3]; color[0] = drawing_board[i][j][0] & 255; color[1] = drawing_board[i][j][1] & 255; color[2] = drawing_board[i][j][2] & 255; fwrite(color, 1, 3, fp); } void pixel_design(int x1, int y1, int x2, int y2, int deepth); int main() { printf("输入数字作为种子来得到一幅蒙德里安风格的格子画:"); int seed = 0; scanf("%d", &seed); srand(seed); fp = fopen("Mondrian.ppm", "wb"); fprintf(fp, "P6\n%d %d\n255\n", DIM, DIM); pixel_design(0, 0, DIM, DIM, 1); for (int j = 1; j < DIM; j++) //输出画到文件 for (int i = 0; i < DIM; i++) pixel_write(i, j); for (int i = 1; i < DIM; i++) pixel_write(i, 0); pixel_write(DIM, DIM); fclose(fp); return 0; } void pixel_design(int x1, int y1, int x2, int y2, int deepth) { if (rand() % (deepth + 2) > 2 || x2-x1<=100 || y2-y1<=100) { //是否对当前区域上色及上何种颜色 int selectcolor = (rand() % 14 + 1) / 2; //+1的作用是使黑色出现的概率为其他颜色的1/2 switch (selectcolor) { case 0: fillcolor(x1, y1, x2, y2, BK); break; case 1: fillcolor(x1, y1, x2, y2, R); break; case 2: fillcolor(x1, y1, x2, y2, G); break; case 3: fillcolor(x1, y1, x2, y2, B); break; default: fillcolor(x1, y1, x2, y2, WT); break; } return; } bool ishorizontal = rand() % (wr + wc) + 1>wr; //是否水平分割,水平分割的概率会随着次数的增加而减少 int side1 = 1, side2 = 1; while (rand() % 4 == 1) side1 = side1++; //确定分割比例 while (rand() % 4 == 1) side2 = side2++; if (ishorizontal&&y1 <= (y2 - y1) / (side1 + side2)*side1 + y1 - 3 && y2 >= (y2 - y1) / (side1 + side2)*side1 + y1 + 4) { wr = wr++; fillcolor(x1, (y2 - y1) / (side1 + side2)*side1 + y1 - 3, x2, (y2 - y1) / (side1 + side2)*side1 + y1 + 4, BK); pixel_design(x1, y1, x2, (y2 - y1) / (side1 + side2)*side1 + y1 - 4, deepth + 1); pixel_design(x1, (y2 - y1) / (side1 + side2)*side1 + y1 + 5, x2, y2, deepth + 1); } if ((!ishorizontal)&&x1 <= (x2 - x1) / (side1 + side2)*side1 + x1 - 3 && x2 >= (x2 - x1) / (side1 + side2)*side1 + x1 + 4) { wc = wc++; fillcolor((x2 - x1) / (side1 + side2)*side1 + x1 - 3, y1, (x2 - x1) / (side1 + side2)*side1 + x1 + 4, y2, BK); pixel_design(x1, y1, (x2 - x1) / (side1 + side2)*side1 + x1 - 4, y2, deepth + 1); pixel_design((x2 - x1) / (side1 + side2)*side1 + x1 + 5, y1, x2, y2, deepth + 1); } } |
那个可能很多人没见过的第一行是防止辣鸡VS对scanf报错的语句。
为了使图片尽可能美观,我对其中的几个参数修改了百十来次。
虽然最后只能使小部分随机种子生成的画作看起来不那么难看……
因为是完全随机的,所以生成什么样的画还得看脸……
本来还想做些比如随机对每个像素做些小小的修改,或在黑线旁加点白边什么的,后来想想这样可能会超出100行(还有我懒)就没这么改。
随便贴一张生成的图吧:
seed:12471
我觉得这个代码可以再优化一下。。让图像更丰富。
道理我都懂,可是懒的写+不知道怎么个丰富法+再写可能就超100行了
你觉得可以怎么改