【问题标题】:Diamond-square algorithm not working (rewrite code from JS to JAVA)Diamond-square 算法不起作用(将代码从 JS 重写为 JAVA)
【发布时间】:2016-07-14 18:42:16
【问题描述】:

我正在尝试将代码从 JS 重写为 Java。代码为菱形平方算法。

来源为: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.");
            }
        }
    }
}

谁能帮帮我?

算法的输出是int[][],我使用另一个程序进行图像化..

输出的可视化:

这就是它应该看起来的样子

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

【问题讨论】:

  • 您是否遇到任何编译错误?预期的输出是什么,你得到了什么?在您的问题中包含所有内容。没有人会为了理解它应该做什么而调试 100 行代码。
  • 我没有收到错误,但输出错误
  • 你能给我们预期的和实际的输出吗?
  • 预期输出为:http://i.stack.imgur.com/po8b4.png,我的算法的实际输出存在问题。
  • @Spektre 我以 513x513 的分辨率进行测试,但仍然存在同样的问题。

标签: javascript java algorithm


【解决方案1】:

我昨天在编写同样的代码(来自同一来源),由于细分区域的平方步重叠和同一步中的不规则性,递归方法非常棘手。所以我决定从头开始以迭代方式(由于在我的编程环境中没有堆/堆栈垃圾,这要快得多),因为你可以看到我使用 cmets 从 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); 的结果

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

当心我程序中的本地 int xs,ys 变量拥有 2 个值的幂,而不是 2 +1 的幂!!!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    • 2014-09-20
    • 2016-08-22
    • 2017-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多