วาดป่าดำและขาวแบบสุ่ม


66

งานของคุณคือการเขียนโปรแกรมซึ่งจะวาดภาพขาวดำขนาด 800x600 ด้วยบางสิ่งที่คล้ายป่า

เช่นนี้ (มันเป็นภาพ dithered):

กฎระเบียบ

  • คุณไม่ได้รับอนุญาตให้ใช้ภาพที่มีอยู่ใด ๆ - คุณควรสร้างภาพที่มีอัลกอริธึมล้วนๆ
  • ใช้ 2 สีเท่านั้น - ดำและขาว (ไม่มีสีเทา)
  • แต่ละครั้งที่โปรแกรมรันอิมเมจควรใหม่ - สุ่มทุกครั้ง
  • ต้นหนึ่งไม่ได้เป็นป่า (สมมุติ 5 ต้นต่ำกว่า)
  • ไม่อนุญาตให้ใช้ห้องสมุดพิเศษสำหรับวาดต้นไม้ / ป่า
  • ตอบด้วยคะแนนโหวตมากที่สุดชนะ

9
คำถามนี้ดูเหมือนจะไม่อยู่ในหัวข้อเพราะเป็นการประกวดศิลปะมากกว่าการประกวดเขียนโปรแกรม
ProgramFOX

19
@ProgramFOX การเขียนโปรแกรมไม่ใช่ศิลปะใช่ไหม :)
Somnium

15
สำหรับหนึ่งฉันอยากเห็นบางรายการสำหรับความท้าทายนี้และรู้สึกผิดหวังที่ถูกระงับไว้
Braden ที่ดีที่สุด

3
ฉันชอบความท้าทายนี้ คำตอบที่ไม่ได้อยู่ในจิตวิญญาณของมันจะไม่ได้รับการสนับสนุนมากนักดังนั้นปัญหาคืออะไร
cjfaure

3
@cjfaure เพื่อวัตถุประสงค์ที่แตกต่างกันเช่นการสร้างแบบจำลองและรูปภาพสำหรับเกม
Somnium

คำตอบ:


98

C: 3863 1144 1023 999 942 927

โซลูชันดั้งเดิมบันทึก 2 ไฟล์ pnm ต่อการใช้งาน (หนึ่งไฟล์ที่มี g ต่อท้ายก่อนที่จะเปลี่ยนทิศทาง) เนื่องจากการทำ dithering นั้นไม่สวยงามสำหรับสองสามบรรทัดแรกจึงมีการแฮ็กเพื่อสร้างบรรทัดมากกว่าที่ต้องการและทำการครอบตัดระหว่างเอาต์พุต

โซลูชัน golfed มี dithering ง่ายขึ้นและบันทึกเฉพาะภาพ dithered (ไม่มีคำเตือนด้วย gcc -std = c11 -pedantic -Wall -Wextra)

ตัวอย่างภาพจากโปรแกรมต้นฉบับ 3 ตัวที่ทำงานอยู่และรุ่นหนึ่งที่ตีกอล์ฟ (ภาพสุดท้าย):

ตัวอย่างที่ 1 ตัวอย่างที่ 2 ตัวอย่างที่ 3 ตัวอย่างที่ 4

รุ่น golfed

  #include <math.h>
  #include <time.h>
  #include <stdlib.h>
  #include <stdio.h>
  #define D float
  #define R rand()/RAND_MAX
  #define Z(a,b,c) if(10.*R>a)T(h,s,j+b+c*R,g);
  #define U a[y][x]
  #define V e[y+1][x
  #define F(x) for(i=0;i<x;++i)
  int i,x,y,W=800,H=600;unsigned char a[600][800],c;D e[601][802],r,b,k,l,m,n,f,w,
  d,q=.01;void T(D h,D s,D j,D g){r=b=0;do{j+=.04*R-.02;h+=sin(j)*q;s+=cos(j)*q;b
  +=q;g+=q;f=525/d;r=.25-g/44;m=w*f+s*f+W/2;n=2*f-h*f+H/2;f*=r;for(y=n-f-2;y<n+f+2
  ;++y)if(y>=0&&y<H)for(x=m-f-2;x<m+f+2;++x)if(x>=0&&x<W)if(k=m-x,l=n-y,f>sqrt(k*k
  +l*l))if(U>d*3)U=d*3;}while(b<10*r+12*r*R&&r>q);if(r>q){Z(2,.26,.35)Z(2,-.26,-
  .35)Z(7,-.05,.1)}}int main(){FILE* o=fopen("i","wb");srand(time(0));F(W*H){y=i/W
  ;a[y][i%W]=(y<313)?255:6e3/(2*y-H);}F(200)w=1e2*R-60,d=80.*R+5,T(0,0,1.58,0);F(W
  *H){x=i%W;y=i/W;k=U+e[y][x+1];U=-(k>0);l=(k-U)*.1;e[y][x+2]+=l*4;V]+=l*2;V+1]+=l
  *3;V+2]+=l;}fprintf(o,"P5 800 600 255 ");fwrite(a,1,W*H,o);}

รุ่นเดิม

  #include <math.h>
  #include <stdio.h>
  #include <stdlib.h>

  #define W 800
  #define H 600
  #define SPEED 0.01
  #define HEIGHT 11.0

  #define R(m) ((double)(m) * rand() / RAND_MAX)
  #define RAD(deg) ((deg) / 180.0 * M_PI)
  #define LIMIT(x, min, max) ((x) < (min) ? (min) : (x) > (max) ? (max) : (x))

  void shade(void);
  void growTree(double dist, double side, double h, double s, double alpha, double grown);
  void plot(double dist, double side, double h, double s, double alpha, double diam);
  void dither(void);
  void writeImg(int dither);

  unsigned char img[H+10][W];
  double err[H+10+2][W+4];
  long tim;

  int main(void)
  {
     int i;
     tim = time(0);
     srand(tim);
     shade();
     for(i = 0; i < 200; ++i)
     {
        growTree(5 + R(75), -60 + R(120), 0.0, 0.0, RAD(90), 0.0);
     }
     writeImg(0);
     dither();
     writeImg(1);
  }

  void shade(void)
  {
     int y;
     for(y = -10; y < H; ++y)
     {
        double dist = H * 3.5 / (2 * y - H);
        unsigned char color = dist / 80 * 255;
        if(y <= H / 2 || dist > 80) color = 255;
        memset(img[y+10], color, W);
     }
  }

  void growTree(double dist, double side, double h, double s, double alpha, double grown)
  {
     double diam, branchLength = 0.0;

     do
     {
        alpha += R(RAD(3)) - RAD(1.5);
        h += sin(alpha) * SPEED;
        s += cos(alpha) * SPEED;
        branchLength += SPEED;
        grown += SPEED;
        diam = (1.0 - grown / HEIGHT) * 0.5;
        plot(dist, side, h, s, alpha, diam);
     } while(branchLength < 5 * diam + R(6 * diam) && diam > 0.02);

     if(diam > 0.02)
     {
        int br = 0;

        if(R(10) > 2) br++,growTree(dist, side, h, s, alpha + RAD(15) + R(RAD(20)), grown);
        if(R(10) > 2) br++,growTree(dist, side, h, s, alpha - RAD(15) - R(RAD(20)), grown);
        if(R(10) < 2 || br == 0) growTree(dist, side, h, s, alpha - RAD(2.5) + R(RAD(5)), grown);
     }
  }

  void plot(double dist, double side, double h, double s, double alpha, double diam)
  {
     int x, y;
     double scale = H / 4.0 * 3.5 / dist;
     double x0 = side * scale + s * scale + W / 2.0;
     double y0 = H / 2.0 + 2.0 * scale - h * scale;
     diam *= scale;
     h *= scale;
     s *= scale;
     for(y = y0 - diam / 2 - 2; y < y0 + diam / 2 + 2; ++y)
     {
        if(y < -10 || y >= H) continue;
        for(x = x0 - diam / 2 - 2; x < x0 + diam / 2 + 2; ++x)
        {
           double dx, dy, d;
           if(x < 0 || x >= W) continue;
           dx = x0 - x;
           dy = y0 - y;
           d = diam / 2 - sqrt(dx * dx + dy * dy) + 0.5;
           if(d > 0)
           {
              unsigned char color = dist / 80 * 255;
              if(img[y+10][x] > color) img[y+10][x] = color;
           }
        }
     }
  }

  void dither(void)
  {
     int x0, x, y;
     for(y = -10; y < H; ++y)
     {
        for(x0 = 0; x0 < W; ++x0)
        {
           double error, oldpixel;
           unsigned char newpixel;
           if(y%2) x = W - 1 - x0;
           else x = x0;
           oldpixel = img[y+10][x] + err[y+10][x+2];
           newpixel = oldpixel > 127 ? 255 : 0;
           img[y+10][x] = newpixel;
           error = oldpixel - newpixel;
           err[y+10  ][x+1+2*(1-y%2)] += error * 7 / 48;
           err[y+10  ][x+4*(1-y%2)] += error * 5 / 48;
           err[y+10+1][x  ] += error * 3 / 48;
           err[y+10+1][x+1] += error * 5 / 48;
           err[y+10+1][x+2] += error * 7 / 48;
           err[y+10+1][x+3] += error * 5 / 48;
           err[y+10+1][x+4] += error * 3 / 48;
           err[y+10+2][x  ] += error * 1 / 48;
           err[y+10+2][x+1] += error * 3 / 48;
           err[y+10+2][x+2] += error * 5 / 48;
           err[y+10+2][x+3] += error * 3 / 48;
           err[y+10+2][x+4] += error * 1 / 48;
        }
     }
  }

  void writeImg(int dither)
  {
     FILE* fp;
     char buffer[32];
     sprintf(buffer, "%ld%s.pnm", tim, dither ? "" : "g");
     fp = fopen(buffer, "wb");
     fprintf(fp, "P5\n%d %d\n255\n", W, H);
     fwrite(&img[10][0], 1, W * H, fp);
     fclose(fp);
  }

3
+1 รูปสวย. อย่างไรก็ตามนี่คือการประกวดความนิยมไม่ใช่โค้ดกอล์ฟ ดังนั้นไม่จำเป็นต้องเล่นกอล์ฟ :)
Vectorized

2
ดูดีฉันมีความคิดคล้าย ๆ กัน แต่ขี้เกียจเกินไป =) ฉันคิดว่าคุณสามารถลองสุ่มความลึกของการเรียกซ้ำของกิ่งฉันคิดว่ามันจะดูเป็นธรรมชาติมากกว่า
ข้อบกพร่อง

3
ฉันรู้ว่าฉันไม่ต้องการเล่นกอล์ฟ แต่ก็เป็นส่วนที่สนุกที่สุดสำหรับฉัน!
Manuel Kasten

2
นี่คือรูปหล่อ
เควนติน

12
นอกจากนี้ฉันยังใส่เวอร์ชั่นที่ไม่ได้ลงในโทนซีเปีย - งดงาม! ดูที่นี่: i.imgur.com/lCrJCp7.jpg
DreamWarrior

42

Java Jungle

(954 golfed)

เต็มไปด้วยพงลึกบิดเป็นป่าที่ไม่ได้สำรวจได้ง่าย

ป้อนคำอธิบายรูปภาพที่นี่

มันเป็นการเดินสุ่มเศษส่วนที่มีเถาองุ่นที่หดตัวช้า ฉันวาด 75 คนจากนั้นค่อยๆเปลี่ยนจากสีขาวที่ด้านหลังเป็นสีดำขึ้นด้านหน้า จากนั้นฉันก็ทิ้งสิ่งทั้งปวงไว้โดยไม่ต้องลงมือปรับรหัส Averroes ' ที่นี่เพื่อสิ่งนั้น

Golfed: (เพราะคนอื่นตัดสินใจ)

import java.awt.*;import java.awt.image.*;import java.util.*;class P{static Random rand=new Random();public static void main(String[]a){float c=255;int i,j;Random rand=new Random();final BufferedImage m=new BufferedImage(800,600,BufferedImage.TYPE_INT_RGB);Graphics g=m.getGraphics();for(i=0;i++<75;g.setColor(new Color((int)c,(int)c,(int)c)),b(g,rand.nextInt(800),599,25+(rand.nextInt(21-10)),rand.nextInt(7)-3),c-=3.4);for(i=0;i<800;i++)for(j=0;j<600;j++)if(((m.getRGB(i,j)>>>16)&0xFF)/255d<rand.nextFloat()*.7+.05)m.setRGB(i,j,0);else m.setRGB(i,j,0xFFFFFF);new Frame(){public void paint(Graphics g){setSize(800,600);g.drawImage(m,0,0,null);}}.show();}static void b(Graphics g,float x,float y,float s,float a){if(s>1){g.fillOval((int)(x-s/2),(int)(y-s/2),(int)s,(int)s);s-=0.1;float n,t,u;for(int i=0,c=rand.nextInt(50)<1?2:1;i++<c;n=a+rand.nextFloat()-0.5f,n=n<-15?-15:n>15?15:n,t=x+s/2*(float)Math.cos(n),u=y-s/2*(float)Math.sin(n),b(g,t,u,s,n));}}}

รหัสเดิมของ Sane:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.JFrame;

public class Paint {

    static int minSize = 1;
    static int startSize = 25;
    static double shrink = 0.1;
    static int branch = 50;
    static int treeCount = 75;

    static Random rand = new Random();
    static BufferedImage img;

    public static void main(String[] args) {
        img = new BufferedImage(800,600,BufferedImage.TYPE_INT_ARGB);
        forest(img);
        dither(img);
        new JFrame() {
            public void paint(Graphics g) {
                setSize(800,600);
                g.drawImage(img,0,0,null);
            }
        }.show();
    }

    static void forest(BufferedImage img){
        Graphics g = img.getGraphics();
        for(int i=0;i<treeCount;i++){
            int c = 255-(int)((double)i/treeCount*256);
            g.setColor(new Color(c,c,c));
            tree(g,rand.nextInt(800), 599, startSize+(rand.nextInt(21-10)), rand.nextInt(7)-3);
        }
    }

    static void tree(Graphics g, double x, double y, double scale, double angle){
        if(scale < minSize)
            return;
        g.fillOval((int)(x-scale/2), (int)(y-scale/2), (int)scale, (int)scale);
        scale -= shrink;
        int count = rand.nextInt(branch)==0?2:1;
        for(int i=0;i<count;i++){
            double newAngle = angle + rand.nextDouble()-0.5;
            if(newAngle < -15) newAngle = -15;
            if(newAngle > 15) newAngle = 15;
            double nx = x + (scale/2)*Math.cos(newAngle);
            double ny = y - (scale/2)*Math.sin(newAngle);
            tree(g, nx, ny, scale, newAngle);
        }
    }

    static void dither(BufferedImage img) {
        for (int i=0;i<800;i++)
            for (int j=0;j<600;j++) {
                double lum = ((img.getRGB(i, j) >>> 16) & 0xFF) / 255d;
                if (lum <= threshold[rand.nextInt(threshold.length)]-0.2)
                    img.setRGB(i, j, 0xFF000000);
                else
                    img.setRGB(i, j, 0xFFFFFFFF);
            }
    }

    static double[] threshold = { 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31,
            0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42,
            0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53,
            0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6, 0.61, 0.62, 0.63, 0.64,
            0.65, 0.66, 0.67, 0.68, 0.69 };

}

อีกหนึ่ง? เอาล่ะ! อันนี้มีการปรับ dithering ลงเล็กน้อยดังนั้นคนผิวดำที่อยู่ข้างหน้าจึงราบเรียบมาก

ป้อนคำอธิบายรูปภาพที่นี่

โชคไม่ดีที่ dither ไม่แสดงรายละเอียดที่ละเอียดของเลเยอร์เถาวัลย์ นี่คือรุ่น greyscale สำหรับการเปรียบเทียบ:

ป้อนคำอธิบายรูปภาพที่นี่


1
ดี ดีใจรหัสของฉันเป็นประโยชน์;)
Averroes

1
ฉันอ่านที่ไหนเลยในกฎที่จำเป็นต้องมี dithering ฉันคิดว่าเวอร์ชั่นที่ไม่มีการปรับแต่งนั้นดูสวยงามกว่ามาก
Lars Ebert

4
@ ไม่จำเป็นต้องใช้ dithering แต่จะต้องใช้เฉพาะขาวดำเท่านั้นไม่อนุญาตให้ใช้ค่าสีเทา ....
Manuel Kasten

31

Javascript + HTML - ไม่เล่นกอล์ฟ

การย้าย javascript ของอัลกอริทึมของ @Manuel Kansten - มันช่างน่าทึ่งที่ต้นไม้เหล่านี้ดูดีแค่ไหน

เพื่อทำสิ่งที่แตกต่างฉันวาดภาพสีจากนั้น dither เพื่อ b / w ในขั้นตอนสุดท้าย

ฉันไม่รู้ว่าทำไม แต่ป่าของฉันนั้นมืดมนกว่าและน่าเคารพน้อยกว่าของมานูเอล

ทดสอบกับJSfiddleหรือเรียกใช้ตัวอย่างใหม่ด้านล่าง นั่นไม่เร็ว จงอดทนและเฝ้าดูการเติบโตของป่า

ป่า 1 ป่า 1 สี

ป่า 2 ป่า 2 สี

W=800
H=600
canvas.width = W;
canvas.height = H;

var ctx = canvas.getContext("2d");

R=function(m) { return m * Math.random()};
RAD=function(deg) { return deg / 180 * Math.PI};
LIMIT=function(x, min, max) {return x < min ? min : x > max ? max : x};
var SPEED = 0.01, HEIGHT = 11.0;

// Ground
var grd = ctx.createLinearGradient(0,0,0,H);
grd.addColorStop(0,"#88ccff");
grd.addColorStop(0.45,"#ffffee");
grd.addColorStop(0.5,"#80cc80");
grd.addColorStop(1,"#001100");
ctx.fillStyle = grd;
ctx.fillRect(0,0, W,H);


Plot = function(dist, side, h, s, alpha, diam)
{
    var x, y, a1,a2,scale = H/4 * 3.5 / dist, 
        x0 = side * scale + s * scale + W/2,
        y0 = H/2 + 2.5*scale - h*scale;
    
    k = dist
    if (diam > 0.05) {
        red = k*3|0;     
        green = k|0;
        a1=alpha+1
        a2=alpha-1
    }
    else
    {
        green= 80+(1-diam)*k*2|0;
        red = k|0;
        a1=0;
        a2=2*Math.PI;
    }
    diam *= scale;
    h *= scale;
    s *= scale;
    ctx.beginPath();
    ctx.arc(x0,y0,diam/2, a1,a2);//lpha-1, alpha+1);//0,2*Math.PI);
    ctx.fillStyle = 'rgb('+red+','+green+',0)';
    ctx.fill();
}

Grow = function(dist, side, h, s, alpha, grown)
{
    var diam, branchLength = 0.0;
    diam = (1.0 - grown / HEIGHT) * 0.5;
    do
    {
        alpha += R(RAD(3)) - RAD(1.5);
        h += Math.sin(alpha) * SPEED;
        s += Math.cos(alpha) * SPEED;
        branchLength += SPEED;
        grown += SPEED;
        diam = (1.0 - grown / HEIGHT) * 0.5;
        Plot(dist, side, h, s, alpha, diam);
    } while(branchLength < 5 * diam + R(6 * diam) && diam > 0.02);

    if (diam > 0.02)
    {
        var br = 0;

        if(R(10) > 2) br++,Grow(dist, side, h, s, alpha + RAD(15) + R(RAD(20)), grown);
        if(R(10) > 2) br++,Grow(dist, side, h, s, alpha - RAD(15) - R(RAD(20)), grown);
        if(R(10) < 2 || br == 0) Grow(dist, side, h, s, alpha - RAD(2.5) + R(RAD(5)), grown);
    }
}

trees=[]
for(i = 0; i < 300; ++i) trees.push({ z: 1+R(70), s:R(120)-60 });
trees.sort( function (a,b) { return a.z - b.z} );

Draw = function()
{
    t = trees.pop();
    if (t)
    {
        Grow(t.z, t.s, 0, 0, RAD(90), 0);
        setTimeout(Draw, 100);
    }
    else 
    {
        var e,c,d,p,i,l, img = ctx.getImageData(0,0,W,H);
        l = img.data.length;
        for (i = 0; i < l-W*4-4; i+=4)
        {
            c = (img.data[i]+img.data[i+1])/2|0
            c = img.data[i]
            d = c > 120 + R(16) ? 255 : 0
            e = c - d;
            img.data[i]=img.data[i+1]=img.data[i+2]=d
            c = (img.data[i+4]+img.data[i+5])/2|0
            
            c = LIMIT(c + ((e*7)>>4),0,255)
            img.data[i+4]=img.data[i+5]=img.data[i+6]=c
            p = i+W*4
            c = (img.data[p-4]+img.data[p-3])/2|0
            c = LIMIT(c + ((e*3)>>4),0,255)
            img.data[p-4]=img.data[p-3]=img.data[p-2]=c
            c = (img.data[p]+img.data[p+1])/2|0
            c = LIMIT(c+ ((e*5)>>4),0,255)
            img.data[p]=img.data[p+1]=img.data[p+2]=c
            c = (img.data[p+4]+img.data[p+5]*2)/3|0
            c = LIMIT(c + (e>>4),0,255)
            img.data[p+4]=img.data[p+5]=img.data[p+6]=c
    
        }
        bwcanvas.width = W;
        bwcanvas.height = H;
        var bwx = bwcanvas.getContext("2d");
        bwx.putImageData(img,0,0);
    }
}

setTimeout(Draw, 10);
<canvas id='bwcanvas'  width="2" height="2"></canvas>
<canvas id='canvas'  width="2" height="2"></canvas>


2
ฉันคิดว่ามันเป็นดิน ต้นไม้ของมานูเอลกลมกลืนกับพื้นดินสร้างภาพลักษณ์ที่มืดสลัว ระนาบกราวด์ของคุณมีน้ำหนักเบาทำให้มีลักษณะโปร่งโล่งและมีคอนทราสต์สูง นอกจากนี้ท้องฟ้าสีทึบและระยะทางที่จางหายไปในรูปภาพของมานูเอลยังช่วยสร้างภาพลักษณ์ของหมอกหรือหมอกควันที่คลุมเครือ (ใจคุณฉันชอบรูปลักษณ์ที่แตกต่างกันของคุณ)
Ilmari Karonen

ใช่นี่เป็นสวนผลไม้สำหรับป่าลึกของมานูเอล
shadowtalker

23

ศิลปะที่ไม่มีบริบท 3 (1133)

CF เป็นภาษาที่แสดงกราฟิกแบบเวกเตอร์ดังนั้นฉันจึงไม่สามารถหลีกเลี่ยงการต่อต้าน ฉันทำงานรอบ ๆ โดยวาดสี่เหลี่ยมที่เดียวกันหลาย ๆNครั้ง หมอกจะกระทำโดยการวาดสี่เหลี่ยมเล็ก ๆ ในสถานที่สุ่ม

startshape main

W = 80*0.6
H = 60*0.6

N = 3

CF::Background = [ b -1 ]
CF::Size = [ x 0 y -20 s W H ]
CF::Color = 0
CF::ColorDepth = 16
CF::MinimumSize = 0.6

shape main {
  transform [ z 0 y (H/2) b 1 ]
  loop 30 [ z -1 y -2 ] {
    loop 200000 []
      SQUARE1 [ s (0.1/3) x -W..W y -H..H z -0.5..0.5 ]
  }

  transform [ b -1 z 3 ]
  loop 14 [[ s 1.1 y -0.8..-1 s 0.6 z -3 ]] {
    loop 14 [] tree [ x (-30..-20) z (-3..3) ]
    loop 14 [] tree [ x (20..30) z (-3..3) ]
  }
}

shape tree {
  branch [ ]
}

shape branch
rule 7 {
  transform [ s (1..2) 1]
  SQUARE1 [ ]

  branch [ y (0.2..0.3) x (-0.05..0.05) s 0.994 r (-6..6) z (-0.3..0.3)  ]
  branch1 [ b 0.001 z -2 r -20..20 ]
}
rule 0.001 { }
rule 0.3 { branch [ r 4..20 ] }
rule 0.3 { branch [ r -4..-20 ] }

shape branch1
rule 90 { }
rule { branch [ r -22..22 s 0.8..1 ] }

path SQUARE1 {
  MOVETO( 0.5,  0.5)
  LINETO(-0.5,  0.5)
  LINETO(-0.5, -0.5)
  LINETO( 0.5, -0.5)
  CLOSEPOLY()
  loop N [] FILL()[]
}

shape S {
  SQUARE [ a -1 ]
  loop 1000 [ ] SQUARE [ x (-0.5..0.5) y (-0.5..0.5) s 0.01..0.001 ]
}

ป้อนคำอธิบายรูปภาพที่นี่

แสดงผลมากขึ้นโดยใช้ตัวเลขที่แตกต่างกัน ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่


1
ฉันได้รับว่าไม่มีตัวเลือกที่ผิดเพี้ยน แต่ผลลัพธ์ควรเป็นสีดำ / ขาวเท่านั้น
Geobits

1
คุณหาทางหนีไม่ได้เหรอ? มันเป็นคำตอบที่ไม่ถูกต้อง
edc65

1
คุณไม่จำเป็นต้องโฉบเฉี่ยว แต่คุณต้องใช้เพียง 2 สีคือขาวดำ การใช้ greyscale ไม่ตรงกับกฎ คำถามได้รับการแก้ไขเพื่อลบความคลุมเครือ ฉันขอแนะนำให้ใช้วิธีการบางอย่างเพื่อให้ได้สิ่งนี้ไม่ว่าจะเป็นเรื่องไร้สาระหรือไม่ก็ตามเพื่อให้คุณสามารถแก้ไขคำตอบของคุณก่อนที่ downvotes จะมาถึงมากเกินไป
trichoplax

ในฐานะที่เป็นข้อเสนอแนะในกรณีที่ช่วย: คุณสามารถใช้วิธีการปัจจุบันของสี่เหลี่ยมโปร่งใสเพื่อให้ได้ภาพขาวดำแทนที่จะโปร่งใสบางส่วนใช้ความโปร่งใสเต็มรูปแบบในรูปแบบกริดของบางประเภทเพื่อให้เซลล์กริดอื่นทุกเซลล์เท่านั้น มีความโปร่งใส
trichoplax

1
สิ่งนี้ใกล้เข้ามามากแล้วที่อยู่ในจิตวิญญาณของคำถาม
trichoplax

19

C: 301

โปรแกรมนี้สร้างภาพนามธรรมที่เรียบง่ายในรูปแบบPGM คุณสามารถเปิดด้วย GIMP

int x,y,i,d,w;srand(time(NULL));unsigned char p[480000];FILE *f=fopen("a.pgm","w");fprintf(f,"P5\n800 600\n1\n");i=480000;while(i--)p[i]=i>240000|(i%800+i/800&3)!=0;i=100;while(i--){d=(11000-i*i)/99;y=300+1100/d;x=rand()%800;while(y--){w=300/d;while(w--)p[y*800+w+x]=0;}}fwrite(p, 1, 480000, f);fclose(f);

นี่คือตัวอย่างการเรียกใช้:สร้างรูปภาพ


34
ดูเหมือนว่าบาร์โค้ดจะเป็นป่ามากกว่า :) :)
Sylwester

6
bartree forest คว่ำ
Fabricio

5
เมื่อเลื่อนลงฉันคิดว่าเบราว์เซอร์ของฉันไม่สามารถแสดงภาพได้อย่างถูกต้อง ฉันจะให้คะแนนโบนัสแก่คุณเป็นจำนวนมากหากบาร์ ธ ของคุณสแกนด้วยเครื่องสแกนบาร์โค้ดให้ URL เพื่อรับการท้าทายนี้ ยกเว้นว่ามันจะไม่เป็นป่าสุ่ม
nwp

6
ฉันสแกนและสแกนเนอร์บาร์โค้ดของฉันสาปแช่งฉัน ขอขอบคุณ.
PlasmaHH

1
@nwp คุณสามารถใช้รหัสสุ่มจากฐานข้อมูล UPCได้
สแกน

18

IFS กับ JAVA

วิธีนี้ใช้ Iterated Function System (IFS) เพื่ออธิบายทรีหนึ่ง (โปรโต) IFS ถูกนำไปใช้ 100 ครั้ง (= ฟอเรสต์) ก่อนที่ต้นไม้แต่ละต้นจะถูกทาสี (ปลูกในป่า) IFS จะถูกเปลี่ยนเล็กน้อย (สุ่มสไตล์การเดิน) ดังนั้นต้นไม้แต่ละต้นจึงดูแตกต่างกันเล็กน้อย

รูปภาพมาจากเมล็ดสุ่ม:

  • -824737443
  • -1220897877
  • -644492215
  • 1133984583

ไม่จำเป็นต้องมี dithering

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.*;

public class IFS {
    static Random random=new Random();
    static int BLACK = 0xff000000;
    static int treeCount = 100;
    static Random rand = new Random();
    static int Height = 600;
    static int Width = 800;
    static BufferedImage img = new BufferedImage(Width, Height, BufferedImage.TYPE_INT_ARGB);

    static double[][] ifs=new double[][] {//Tree 3 {; Paul Bourke  http://ecademy.agnesscott.edu/~lriddle/ifskit/gallery/bourke/bourke.ifs
       {0.050000,  0.000000,  0.000000,  0.600000,  0.000000,  0.000000,  0.028000},
       {0.050000,  0.000000,  0.000000, -0.500000,  0.000000,  1.000000,  0.023256},
       {0.459627, -0.321394,  0.385673,  0.383022,  0.000000,  0.600000,  0.279070},
       {0.469846, -0.153909,  0.171010,  0.422862,  0.000000,  1.100000,  0.209302},
       {0.433013,  0.275000, -0.250000,  0.476314,  0.000000,  1.000000,  0.555814 /*Paul Bourke has: 0.255814*/},
       {0.421325,  0.257115, -0.353533,  0.306418,  0.000000,  0.700000,  0.304651 /*Paul Bourke has: 0.204651*/},
    };

    public static void main(String[] args) {
        int seed=random.nextInt();
        //seed=-1220897877;
        random=new Random(seed);
        for (int t = 0; t < treeCount; t++) {
            for (int i = 0; i < ifs.length; i++) {
                for (int j = 0; j < ifs[0].length; j++) {
                    ifs[i][j]=R(ifs[i][j]);
                }
            }
            tree(random.nextDouble(), 0.1*random.nextDouble());
        }
        JFrame frame = new JFrame(""+seed) {
            public void paint(Graphics g) {
                setSize(800,600);
                g.drawImage(img,0,0,null);
            }
        };
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    private static void tree(double x0, double dist) {
        double y0=Math.atan(dist+0.01);
        double scale=Math.atan(0.01)/y0;
        double x=0;
        double y=0;
        for (int n = 0; n < 200000/Math.pow(20*dist+1, 8); n++) {
            int k = select(ifs);
            double newx=ifs[k][0]*x + ifs[k][1]*y + ifs[k][2];
            double newy=ifs[k][3]*x + ifs[k][4]*y + ifs[k][5];
            x=newx;
            y=newy;
            newx= Width*(0.5*scale*newx+x0);
            newy= Height*((1-0.5*scale*newy)-y0-0.1);
            if (0<=newx && newx<Width && 0<=newy && newy<Height) {
                img.setRGB((int)newx, (int)newy, BLACK);
            }
        }
    }

    private static double R(double x) {
        return (1+ 0.01*random.nextGaussian())*x;
    }

    private static int select(double[][] ifs) {
        int k;
        double sum=0;
        for(k=0; k<ifs.length; k++) {
            sum+=ifs[k][6];
        }
        double r=sum*random.nextDouble();
        sum=ifs[0][6];
        for(k=0; k<ifs.length-1 && r>sum; k++) {
            sum+=ifs[k+1][6];
        }
        return k;
    }
}

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่


ภาพสุดท้ายดูดีที่สุด อย่างไรก็ตามฉันคิดว่าคุณควรลองต้นไม้น้อยลงเพราะตอนนี้มีพื้นที่ที่ไม่รู้จักสีดำอยู่เสมอ แต่บนขอบมันดูดีกว่า
Somnium

"ความงามอยู่ในสายตาของคนดู." ฉันทดสอบรูปแบบมากมาย ในตอนท้ายฉันมาด้วย treeCount = 100 ทุกคนยินดีที่จะคัดลอกและเปลี่ยนโซลูชันของฉัน
Bob Genom

15

ฉันสังเกตเห็นการขาดพระเยซูที่แตกต่างกันอย่างชัดเจนดังนั้นฉันจึงแฮ็คบางอย่างเข้าด้วยกันใน Python

from PIL import Image
import random

#Generates the seed for a tree
def makeSeed(y):
    random.seed()
    seed_x = random.randint(10, 590)
    seed_y = y
    width = random.randint(5, 10)
    height = random.randint(width*5, width*30)

    return (seed_x, seed_y, width, height)

#Grows the vertical components
def growStems(seed_data, pixel_field):
    seed_x = seed_data[0]
    seed_y = seed_data[1]
    width = seed_data[2]
    height = seed_data[3]
    for x in range(seed_x, seed_x+width):
        for y in range(seed_y-height, seed_y):
            pixel_field[x][y] = (0, 0, 0)
            #Dithering
            if seed_y > 300 and seed_y < 320:
                if (x+y)%2==0:
                    pixel_field[x][y] = (255, 255, 255)
            elif seed_y >= 320 and seed_y < 340:
                if (x+y)%4==0:
                    pixel_field[x][y] = (255, 255, 255)
            elif seed_y >= 340 and seed_y < 360:
                if (x+y)%8==0:
                    pixel_field[x][y] = (255, 255, 255)

    return pixel_field

#Grows the horizontal components
def growBranches(seed_data, pixel_field):
    seed_x = seed_data[0]
    seed_y = seed_data[1]
    width = seed_data[2]
    height = seed_data[3]
    branch_height = seed_y-height
    branch_width = width
    branch_length = 2
    max_prev = branch_length
    branches = []
    while(branch_height >= seed_y-height and branch_height < seed_y-(3*width) and branch_length < height/3):
        branches.append((branch_height, branch_width, branch_length))
        branch_height+= 4
        branch_length+=2
        #Gives the conifer unevenness to make it look more organic
        if random.randint(0,110) > 100 and branch_length > max_prev:
            max_prev = branch_length
            branch_length -= branch_length/4
    max_length = height/3


    for x in range(seed_x-max_length, seed_x+max_length):
        for y in range(seed_y-height, seed_y):
            for branch in branches:
                bh = branch[0]
                bw = branch[1]
                bl = branch[2]
                #Establishing whether a point is "in" a branch
                if x >= seed_x-bl+(width/2) and x <= seed_x+bl+(width/2):
                    if x > 1 and x < 599:
                        if y >= bh-(bw/2) and y <= bh+(bw/2):
                            if y < 400 and y > 0:
                                pixel_field[x][y] = (0, 0, 0)
                                #Dithering
                                if seed_y > 300 and seed_y < 320:
                                    if (x+y)%2==0:
                                        pixel_field[x][y] = (255, 255, 255)
                                elif seed_y >= 320 and seed_y < 340:
                                    if (x+y)%4==0:
                                        pixel_field[x][y] = (255, 255, 255)
                                elif seed_y >= 340 and seed_y < 360:
                                    if (x+y)%8==0:
                                        pixel_field[x][y] = (255, 255, 255)

    return pixel_field


def growTrees(n):
    pixel_field = [[(255, 255, 255) for y in range(400)] for x in range(600)]
    #Create the ground
    for i in range(600):    
        for j in range(400):
            if pixel_field[i][j]==(255,255,255) and j > 300:
                if (i+j)%2 == 0:
                    pixel_field[i][j]=(0,0,0)
    seed_ys=[]
    #Generates seeds for the trees and orders them back to front to make the dithering work
    for t in range(n):
        seed_ys.append(random.randint(300,390))
    seed_ys.sort()

    for s in range(len(seed_ys)):
        seed= makeSeed(seed_ys[s])
        pixel_field = growStems(seed, pixel_field)
        pixel_field = growBranches(seed, pixel_field)
    return pixel_field

def makeForest():
    forest = growTrees(25)
    img = Image.new( 'RGB', (600,400), "white") # create a new black image
    pixels = img.load() # create the pixel map
    for i in range(img.size[0]):    # for every pixel:
        for j in range(img.size[1]):
            if pixels[i,j]==(255,255,255) and j > 300:
                if (i+j)%2 == 0:
                    pixels[i,j]=(0,0,0)
            pixels[i,j] = forest[i][j] # set the colour accordingly

    img.save("Forest25.jpg")

if __name__ == '__main__':
    makeForest()

ป่ามีต้นไม้ 5 ต้น ป่ามีต้นไม้ 10 ต้น ป่าที่มีต้นไม้ 25 ต้น

นี่คือรหัสกอล์ฟครั้งแรกของฉันมันสนุกมาก!


1
ดูดี! ฉันชอบมัน.
TonySniper

5

คำตอบนี้ไม่สวยเท่าที่ฉันคาดหวัง แต่มันเป็นก้าวสำคัญสำหรับความคิด 3 มิติที่ฉันกำลังทำอยู่และฉันชอบความคิดที่จะจำลองต้นไม้ที่ได้รับทรัพยากรป้อนคำอธิบายรูปภาพที่นี่

package forest;

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Forest extends Canvas{
    private int[] heights = new int[800];
    private BufferedImage buffered_image;
    File outputFile = new File("saved.png");
    Random r = new Random();
    public Forest() {
        buffered_image = new BufferedImage(800, 600,
                BufferedImage.TYPE_INT_RGB);
        for( int j = 0; j < 800; j++){
            heights[j] = -10000;
            for(int k = 0; k < 600; k++){
                buffered_image.setRGB(j, k, 0xFFFFFF);
            }
        }
        for(int i = 0; i < 7; i ++){
            heights[r.nextInt(800)] = 0;
        }

        this.setPreferredSize(new Dimension(800, 600));
        this.setSize(new Dimension(800, 600));
        for( int i = 0; i < 200000; i++){
            int x = r.nextInt(798) + 1;
            heights[x] =  Math.min(599, heights[x - 1] == heights[x + 1] ? heights[x] : Math.max(Math.max(heights[x - 1], heights[x]),heights[x + 1]) + 1);
            buffered_image.setRGB(x, Math.min(599, 600 - heights[x]), 0);
        } 

        try {

            ImageIO.write(buffered_image, "png", outputFile);
        } catch (IOException e) {

        }
        update();
    }
    public void repaint(){
        if(this.getGraphics() != null)
        paint(this.getGraphics());
    }


    public void paint(Graphics g) {
        g.drawImage(buffered_image, 0, 0, this);
    }

    public void update() {  
        repaint();
    }

    public static void main(String[] args) throws IOException {
        JFrame main_frame = new JFrame();
        main_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel top_panel = new JPanel();
        top_panel.setLayout(new BorderLayout());
        Forest s = new Forest();
        top_panel.add(s, BorderLayout.CENTER);
        main_frame.setContentPane(top_panel);

        main_frame.pack();
        main_frame.setVisible(true);
    }

}

6
อาจพลิกมันในแนวตั้งเพื่อให้มันคล้ายกับต้นสน?
Somnium
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.