อัลกอริธึมสี่เหลี่ยมจัตุรัสเล็ก ๆ


12

อัลกอริธึมแบบไดมอนด์สแควร์เป็นอัลกอริธึมการสร้างภูมิประเทศเศษส่วน (ความสูง) คุณสามารถหาคำอธิบายที่ดีว่ามันทำงานอย่างไรที่นี่:

http://www.gameprogrammer.com/fractal.html (ใช้เป็นข้อมูลอ้างอิง)

http://www.playfuljs.com/realistic-terrain-in-130-lines/ (การใช้งาน JS ที่ยอดเยี่ยมบางทีคุณอาจต้องการขโมย renderer ของเขาดูที่นี่ว่าอัลกอริทึมนี้มีความสามารถในhttp: // สาธิตได้อย่างไร playfuljs.com/terrain/ .)

แนวคิดทั่วไปคือคุณมี 4 มุมเป็นเมล็ด (ก) และคำนวณความสูงของจุดกึ่งกลางโดยเฉลี่ยทั้งสี่มุมเหล่านั้นและเพิ่มค่าสุ่มเช่นระหว่าง -0.5 ถึง 0.5 (b) หากคุณนำสิ่งนี้ไปใช้กับตารางคุณจะได้รับตารางของเพชรอีกครั้ง (สี่เหลี่ยมจตุรัส 45 °) และคุณทำซ้ำเหมือนเดิม (c, d) แต่ช่วงสุ่มจะลดลงเช่น -0.125 ถึง 0.125 เป็นต้น ป้อนคำอธิบายรูปภาพที่นี่

โปรแกรมของคุณต้องยอมรับอินพุตจำนวนหนึ่ง:

  • จำนวนเต็มที่กำหนดขนาดของตารางสี่เหลี่ยมที่มีความยาวด้านข้างl=1,2,3,... 2^l+1ที่l=10คุณจะต้องเก็บประมาณหนึ่งล้านหมายเลข
  • สี่เมล็ด (จุดลอย) สำหรับแต่ละมุม
  • พารามิเตอร์0<h<1ที่กำหนดความหยาบ ( Hในลิงก์) ซึ่งหมายถึงระยะเริ่มต้นของการสุ่ม
  • พารามิเตอร์a,bที่แสดงขอบเขตเริ่มต้นล่างและบนสำหรับช่วงสุ่มและได้รับการคูณด้วยhในแต่ละขั้นตอนการปรับแต่ง (จำนวนสุ่มได้รับการแต่งตั้งอย่างสม่ำเสมอระหว่างและab

เอาต์พุตจะต้องประกอบด้วยกริด 2d ที่เสร็จสิ้นแล้ว

ดังนั้นอัลกอริทึมคร่าวๆจะเป็นดังนี้:

Create a square grid with sidelength 2^l+1
Place seed values in the corners
Repeat:
  |  Perform square steps
  |  Refine Range: a = a*h; b=b*h;
  |  Perform diamond steps
  |  Refine Range

มีหนึ่งรายละเอียดที่คุณควรจะตระหนักถึงคือในขอบเขตของตารางที่คุณจะมีเพียงสามจุดของเพชรดังนั้นคุณควรคำนวณค่าเฉลี่ยของทั้งสามจุด

การแสดงตัวอย่างบางส่วน (โปรดบอกเราว่าพารามิเตอร์ที่คุณใช้) เป็นทางเลือก แต่เป็นที่นิยมและแน่นอนว่าไม่ได้เพิ่มไปยังจำนวนไบต์

การใช้งานอัลกอริธึมที่เปลี่ยนแปลงเล็กน้อยสามารถพบได้ที่นี่: เครื่องกำเนิดภูมิประเทศ voxel แบบขนานที่คาดการณ์ไว้

ฉันสร้างฟังก์ชั่นการวาดภาพเล็ก ๆ ใน javascript เพื่อแยกความสูงของแผนที่ใน 2d เป็นภาพระดับสีเทา http://jsfiddle.net/flawr/oy9kxpsx/

หากใครในพวกคุณกลายเป็นแฟนซี 3d และสามารถสร้างสคริปต์เพื่อดูแผนที่ในแบบ 3 มิติแจ้งให้เราทราบ! =)

คำตอบ:


8

Java, 1017 ไบต์

อินพุตเป็นรายการที่คั่นด้วยช่องว่างดังนี้: l s1 s2 s3 s4 h a b.

เอาท์พุทเป็น 2d-array ที่มีตัวเลข

โปรแกรม:

import java.util.*;import static java.lang.Math.*;class C{public static void main(String[]a){int b=a.length,d=0;float[]c=new float[b];for(;d<b;){c[d]=Float.parseFloat(a[d++]);}e=(int)(pow(2,c[0])+1);f=new float[e][e];f[0][0]=c[1];f[0][e-1]=c[2];f[e-1][0]=c[3];f[e-1][e-1]=c[4];g=c[5];float h=c[6],i=c[7];s(0,0,e-1,e-1,h,i);System.out.print(Arrays.deepToString(f));}static int e;static float[][]f;static float g;static void s(int q,int r,int s,int t,float h,float i){if(s-q<2|t-r<2|q<0|r<0|s>=e|t>=e)return;float o,p;int m=(q+s)/2,n=(r+t)/2;f[m][n]=(float)(a(q,r,s,r,q,t,s,t)+random()*(i-h)-h);d(m,r,m-q,o=h*g,p=i*g);d(q,n,m-q,o,p);d(m,t,m-q,o,p);d(s,n,m-q,o,p);}static void d(int x,int y,int e,float h,float i){float o,p;f[x][y]=(float)(a(x,y-e,x+e,y,x,y+e,x-e,y)+random()*(i-h)-h);s(x-e,y-e,x,y,o=h*g,p=i*g);s(x,y-e,x+e,y,o,p);s(x-e,y,x,y+e,o,p);s(x,y,x+e,y+e,o,p);}static float a(int...j){float k=0,l=0;for(int d=0;d<j.length;d+=2){if(j[d]<0|j[d+1]<0|j[d]>=e|j[d+1]>=e)continue;l++;k+=f[j[d]][j[d+1]];}return k/l;}}

โปรแกรมที่เยื้องและแสดงแผนที่:

import java.util.*;
import java.awt.image.*;
import java.awt.*;
import javax.swing.*;
import static java.lang.Math.*;

class D{

    public static void main(String[]a){
        int b=a.length,d=0;
        float[]c=new float[b];
        for(;d<b;){
            c[d]=Float.parseFloat(a[d++]);
        }
        e=(int)(pow(2,c[0])+1);
        f=new float[e][e];
        f[0][0]=c[1];
        f[0][e-1]=c[2];
        f[e-1][0]=c[3];
        f[e-1][e-1]=c[4];
        g=c[5];
        float h=c[6],i=c[7];
        s(0,0,e-1,e-1,h,i);
        showImage(f);
    }

    static int e;
    static float[][]f;
    static float g;

    static void s(int q,int r,int s,int t,float h,float i){
        if(s-q<2|t-r<2|q<0|r<0|s>=e|t>=e)
            return;
        float o,p;
        int m=(q+s)/2,n=(r+t)/2;
        f[m][n]=(float)(a(q,r,s,r,q,t,s,t)+random()*(i+h)-h);
        d(m,r,m-q,o=h*g,p=i*g);
        d(q,n,m-q,o,p);
        d(m,t,m-q,o,p);
        d(s,n,m-q,o,p);
    }

    static void d(int x,int y,int e,float h,float i){
        float o,p;
        f[x][y]=(float)(a(x,y-e,x+e,y,x,y+e,x-e,y)+random()*(i-h)+h);
        s(x-e,y-e,x,y,o=h*g,p=i*g);
        s(x,y-e,x+e,y,o,p);
        s(x-e,y,x,y+e,o,p);
        s(x,y,x+e,y+e,o,p);
    }

    static float a(int...j){
        float k=0,l=0;
        for(int d=0;d<j.length;d+=2){
            if(j[d]<0|j[d+1]<0|j[d]>=e|j[d+1]>=e)
                continue;
            l++;
            k+=f[j[d]][j[d+1]];
        }
        return k/l;
    }

    public static void showImage(float[][] f){
        float maxHeight = Float.MIN_VALUE;
        float minHeight = Float.MAX_VALUE;
        for (float[] row : f){
            for (float height : row){
                if (height > maxHeight){
                    maxHeight = height;
                }
                if (height < minHeight){
                    minHeight = height;
                }
            }
        }
        int e = f.length;
        BufferedImage image = new BufferedImage(e, e, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < e; x++){
            for (int y = 0; y < e; y++){
                Color color = Color.getHSBColor((float)((f[x][y] - minHeight)/(maxHeight - minHeight)), 1, 1);
                image.setRGB(x,y,color.getRGB());
            }
        }
        JFrame frame = new JFrame("Picture");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new JComponent(){

            @Override
            public void paint(Graphics g){
                g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
            }

        });
        frame.setVisible(true);
        frame.setBounds(0,0,e,e);
    }

}

นี่คือฟังก์ชั่นใน Java เพื่อแสดงแผนที่:

public static void showImage(float[][] map){
    float maxHeight = Float.MIN_VALUE;
    float minHeight = Float.MAX_VALUE;
    for (float[] row : map){
        for (float height : row){
            if (height > maxHeight){
                maxHeight = height;
            }
            if (height < minHeight){
                minHeight = height;
            }
        }
    }
    int size = map.length;
    BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
    for (int x = 0; x < size; x++){
        for (int y = 0; y < size; y++){
            Color color = Color.getHSBColor((float)((map[x][y] - minHeight)/(maxHeight - minHeight)), 1, 1);
            image.setRGB(x,y,color.getRGB());
        }
    }
    JFrame frame = new JFrame("Picture");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new JComponent(){

        @Override
        public void paint(Graphics g){
            g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
        }

    });
    frame.setVisible(true);
    frame.setBounds(0,0,size,size);
}

7ทั้งหมดของภาพเหล่านี้มีขนาดของ 4 เมล็ด5, 10, และ1520

aและbเป็น-10และ10ตามลำดับ

เริ่มต้นความหยาบที่.1และเพิ่มขึ้นโดยขึ้นอยู่กับ.11

หนึ่งสองสามสี่ห้าหกเจ็ดแปดเก้าสิบ

สร้างรหัสภูมิประเทศเร็ว ๆ นี้ !!!

ภาพเร็ว ๆ นี้ !!!


ขอบคุณมาก! บางทีคุณอาจให้ชั้นเรียนที่มีการนำเข้าที่จำเป็นทั้งหมดดังนั้นจึงไม่จำเป็นต้องมีการดัดแปลงครั้งใหญ่? นั่นจะยอดเยี่ยม!
ข้อบกพร่อง

@ flawr ฉันกำลังทำงานกับมัน
TheNumberOne

เพิ่งทำให้มันใช้งานได้ถ้าคุณรู้วิธีที่จะทำมันจะดีมากถ้าคุณสามารถทำให้หน้าต่างแสดง 'uncollapsed' อย่างน้อยในเครื่องของฉันคุณต้องเปิดมันทุกครั้งที่เริ่มมัน นี่คือวิธีที่ฉันเรียนจบ: pastebin.com/pRAMst4d
ข้อบกพร่อง

มันดูยอดเยี่ยม! โดยเฉพาะอย่างยิ่งฉันชอบวิธีที่สง่างามที่คุณกำลังเผชิญกับขอบเขตที่จุดยอดหนึ่งหายไป =)
ข้อบกพร่อง

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