菱形算法不起作用(从JS到JAVA重写代码)

时间:2016-03-27 10:54:47

标签: javascript java algorithm

我正在尝试从JS重写代码到Java。代码是Diamond square算法。

来源是:http://www.playfuljs.com/realistic-terrain-in-130-lines/

我重写了代码,但我的代码无效......

输出不好。

Java中的代码是:

public class MapGenerator {

    public static void main(String[] args) {
        MapGenerator mg = new MapGenerator(9);
        mg.generate();
        mg.printMap();
    }

    private int size, max;
    double[] map;
    int[][] matrix;

    public MapGenerator(int detail) {
        this.size = (int) Math.pow(2, detail) + 1;
        this.max = this.size - 1;
        this.map = new double[this.size * this.size];
    }

    private double get(int x, int y) {
        if (x < 0 || x > this.max || y < 0 || y > this.max) {
            return -1;
        }
        return this.map[x + this.size * y];
    }

    private void set(int x, int y, double val) {
        this.map[x + this.size * y] = val;
    }

    public void generate() {
        set(0, 0, max);
        set(this.max, 0, max / 2);
        set(this.max, this.max, 0);
        set(0, this.max, max / 2);
        divide(this.max);

        buildMatrix();
        saveTerrain(0, 0, 0, 0, matrix, "vystup.ter");
    }

    private void buildMatrix() {
        matrix = new int[size][size];

        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                matrix[i][j] = (int) map[i + j];
            }
        }

    }

    private void divide(int size) {
        //? 
        double roughness = 0.7;

        int x, y, half = size / 2;
        double scale = roughness * size;

        if (half < 1) {
            return;
        }
        for (y = half; y < max; y += size) {
            for (x = half; x < max; x += size) {
                square(x, y, half, Library.randInt(0, 100) * scale * 2 - scale);
            }
        }
        for (y = 0; y <= max; y += half) {
            for (x = (y + half) % size; x <= max; x += size) {
                diamond(x, y, half, Library.randInt(0, 100) * scale * 2 - scale);
            }
        }
        divide(size / 2);
    }

    private void square(int x, int y, int size, double offset) {

        double tmp_1 = get(x, y - size);   // top
        double tmp_2 = get(x + size, y);      // right
        double tmp_3 = get(x, y + size);     // bottom
        double tmp_4 = get(x - size, y);       // left

        set(x, y, ((tmp_1 + tmp_2 + tmp_3 + tmp_4) / 4.0) + offset);
    }

    private void diamond(int x, int y, int size, double offset) {
        double tmp_1 = get(x, y - size);      // top
        double tmp_2 = get(x + size, y);      // right
        double tmp_3 = get(x, y + size);      // bottom
        double tmp_4 = get(x - size, y);      // left

        set(x, y, ((tmp_1 + tmp_2 + tmp_3 + tmp_4) / 4.0) + offset);
    }

    public void printMap() {
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                System.out.print(matrix[i][j] + " ");
            }
            System.out.println("");
        }
    }

    public void saveTerrain(int canonX, int canonY, int targetX, int targetY,
            int[][] terrain, String fName) {
        int height = terrain.length;
        int width = terrain[0].length;

        DataOutputStream fout = null;
        try {
            // Samotný zápis dat
            fout = new DataOutputStream(new FileOutputStream(fName));

            fout.writeInt(width);
            fout.writeInt(height);
            fout.writeInt(canonX);
            fout.writeInt(canonY);
            fout.writeInt(targetX);
            fout.writeInt(targetY);

            for (int y = 0; y < height; ++y) {
                for (int x = 0; x < width; ++x) {
                    fout.writeInt(terrain[y][x]);
                }
            }
        } /*
         * Následuje pouze zavření souboru a ošetrení výjimek
         */ catch (FileNotFoundException e) {
            System.err.println("Nepovedlo se otevrit vystupni soubor.");
        } catch (IOException e) {
            System.err.println("Nepovedlo se zapsat vystupni soubor.");
        } finally {
            try {
                if (fout != null) {
                    fout.close();
                }
            } catch (IOException e) {
                System.err.println("Nepovedlo se uzavrit vystupni soubor.");
            }
        }
    }
}

任何人都可以帮助我吗?

algo的输出是int[][],我使用另一个程序来显示图像..

可视化输出:

OUTPUT IMAGE LINK

这就是它的外观

OUTPUT IMAGE LINK

我没有收到错误,但输出错误。 谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

我昨天编写了同样的东西(来自同一个来源),由于细分区域的方形步长重叠和同一步骤中的不规则性,递归方法非常棘手。因此,我决定从头开始以迭代的方式执行此操作(由于我的编程环境中没有堆/堆栈,所以速度更快),因为您可以看到我从130行到50左右的评论。

这是我在 C ++ 中执行此操作(非递归):

void diamond_square(int size)
    {
    picture pic;
    int x,y,xx,yy,xs,ys,d,d2,r;
    for (xs=1;xs<size;xs<<=1); xs>>=1; ys=xs;   // align  to power of 2
    pic.resize(xs+1,ys+1); pic.pf=_pf_u;        // resize image to power of 2 +1
    d=xs; d2=d>>1; r=128;                       // init step,half step and randomness
    Randomize();
    pic.p[ 0][ 0].dd=r;                         // set corners values (should be random but I want this)
    pic.p[ 0][xs].dd=r;
    pic.p[ys][ 0].dd=r;
    pic.p[ys][xs].dd=r;
    for (;d2;d=d2,d2>>=1)                       // subdivide step until full image is filled
        {
        // diamond
        for (y=d2,yy=ys-d2;y<=yy;y+=d)
         for (x=d2,xx=xs-d2;x<=xx;x+=d)
          pic.p[y][x].dd=((pic.p[y-d2][x-d2].dd+pic.p[y-d2][x+d2].dd+pic.p[y+d2][x-d2].dd+pic.p[y+d2][x+d2].dd)>>2)+Random(r);
        // square
        for (y=d2,yy=ys-d2;y<=yy;y+=d)
         for (x=d ,xx=xs-d ;x<=xx;x+=d)
          pic.p[y][x].dd=((pic.p[y][x-d2].dd+pic.p[y][x+d2].dd+pic.p[y-d2][x].dd+pic.p[y+d2][x].dd)>>2)+Random(r);
        for (y=d ,yy=ys-d ;y<=yy;y+=d)
         for (x=d2,xx=xs-d2;x<=xx;x+=d)
          pic.p[y][x].dd=((pic.p[y][x-d2].dd+pic.p[y][x+d2].dd+pic.p[y-d2][x].dd+pic.p[y+d2][x].dd)>>2)+Random(r);
        for (x=d2,xx=xs-d2;x<=xx;x+=d)
            {
            y= 0; pic.p[y][x].dd=((pic.p[y][x-d2].dd+pic.p[y][x+d2].dd+pic.p[y+d2][x].dd)/3)+Random(r);
            y=ys; pic.p[y][x].dd=((pic.p[y][x-d2].dd+pic.p[y][x+d2].dd+pic.p[y-d2][x].dd)/3)+Random(r);
            }
        for (y=d2,yy=ys-d2;y<=yy;y+=d)
            {
            x= 0; pic.p[y][x].dd=((pic.p[y][x+d2].dd+pic.p[y-d2][x].dd+pic.p[y+d2][x].dd)/3)+Random(r);
            x=xs; pic.p[y][x].dd=((pic.p[y][x-d2].dd+pic.p[y-d2][x].dd+pic.p[y+d2][x].dd)/3)+Random(r);
            }
        // adjust randomness
        r=(r*220)>>8; if (r<2) r=2;
        }
    // here pic holds the terrain map
    }

我使用自己的picture课程,所以这里有一些成员:

  • resize(xs,ys)将图片大小调整为新分辨率
  • p[ys][xs].dd是32位无符号整数DWORD
  • 形式的像素访问
  • pf是像素格式(您可以忽略它)

这是diamond_square(513);

的结果

example

您可以使用r randomnes初始值和调整值来改变行为。您也可以更改初始角点值。

请注意我程序中的本地int xs,ys变量保持2值的功率而不是2 +1的功率!!!