java - 绘制填充多维数组

标签 java arrays algorithm multidimensional-array

我的目标是一种“绘画填充”功能,人们可能会在许多图像编辑程序中看到这种功能。也就是说,给定一个屏幕(由二维颜色数组表示)、一个点和一种新颜色,填充周围区域,直到颜色从原始颜色发生变化。

我已经为二维数组实现了它,代码如下:

public static void paint (int [][] screen,int OldColor,int NewColor,int y,int x)
    {   
        if(y>screen.length-1||y<0||x>screen[0].length||x<0||screen[y][x]!=OldColor)
          return;
        screen[y][x]=NewColor;
        paint(screen,OldColor,NewColor,y-1,x);
        paint(screen, OldColor, NewColor, y+1, x);
        paint(screen, OldColor, NewColor, y, x-1);
        paint(screen, OldColor, NewColor, y, x+1);
    }

但我想为 3D 等多维数组实现它,可以通过添加来解决:

paint(screen, OldColor, NewColor, y, x,z-1);
paint(screen, OldColor, NewColor, y, x,z+1);

但是想象一下数组是 100 D...我该如何解决这个问题?

最佳答案

感谢 @Spektre 关于点结构的建议,我成功编写了一个简单的 N 维洪水填充。

我使用字符矩阵代替图像来简化编码。将其更改为 int 作为颜色值并更改其他矩阵的数据类型,将为您完成 100D :)

在这个简单的程序中,我尝试用“B”填充所有“A”,它填充所有连接的字符值,类似于 Ant 巢。您可以使用其他图层追踪 A 之间的连接,以查看填充路径。

在第二张图片中(Im1,故意添加了一个 B,然后在其上方添加了一个无法从填充点访问的 A),效果也很好。

package test;

import java.awt.Point;
import java.util.LinkedList;
import java.util.Queue;

/**
 *
 * @author Pasban
 */
public class NDFloodFill {

    public int N1 = 8; // width
    public int N2 = 6; // height
    public int N = 3; // number of layers
    public ImageData[] images = new ImageData[N];

    public static void main(String[] args) {
        NDFloodFill ndf = new NDFloodFill();

        //print original data
        //ndf.print();
        ndf.fill(0, 0, 0, 'A', 'B');
        ndf.print();
    }

    public NDFloodFill() {
        String im0 = ""
                + "AA...A..\n"
                + ".....A..\n"
                + "....AA..\n"
                + "........\n"
                + "........\n"
                + "...AA.AA";

        String im1 = ""
                + ".A..A...\n"
                + "....B...\n"
                + "..AAA...\n"
                + "........\n"
                + "...AA.A.\n"
                + "..AA..A.";

        String im2 = ""
                + ".A......\n"
                + ".AA.....\n"
                + "..A.....\n"
                + "..A.....\n"
                + "..A.AAA.\n"
                + "..A.....";

        images[0] = new ImageData(im0, 0);
        images[1] = new ImageData(im1, 1);
        images[2] = new ImageData(im2, 2);
    }

    private void print() {
        for (int i = 0; i < N; i++) {
            System.out.println(images[i].getImage());
        }
    }

    private void fill(int x, int y, int index, char original, char fill) {
        Queue<PixFill> broadCast = new LinkedList<>();
        broadCast.add(new PixFill(new Point(x, y), index));
        for (int i = 0; i < N; i++) {
            images[i].reset();
        }
        while (!broadCast.isEmpty()) {
            PixFill pf = broadCast.remove();
            Queue<PixFill> newPoints = images[pf.index].fillArea(pf.xy, original, fill);
            if (newPoints != null) {
                broadCast.addAll(newPoints);
            }
        }
    }

    public class PixFill {

        Point xy;
        int index;

        public PixFill(Point xy, int index) {
            this.xy = xy;
            this.index = index;
        }

        @Override
        public String toString() {
            return this.xy.x + " : " + this.xy.y + " / " + this.index;
        }
    }

    public class ImageData {

        char[][] pix = new char[N1][N2];
        boolean[][] done = new boolean[N1][N2];
        int index;

        public ImageData(String image, int index) {
            int k = 0;
            this.index = index;
            for (int y = 0; y < N2; y++) { // row
                for (int x = 0; x < N1; x++) { // column
                    pix[x][y] = image.charAt(k++);
                }
                k++; // ignoring the \n char
            }
        }

        public void reset() {
            for (int y = 0; y < N2; y++) {
                for (int x = 0; x < N1; x++) {
                    done[x][y] = false;
                }
            }
        }

        public String getImage() {
            String ret = "";
            for (int y = 0; y < N2; y++) { // row
                String line = "";
                for (int x = 0; x < N1; x++) { // column
                    line += pix[x][y];
                }
                ret += line + "\n";
            }
            return ret;
        }

        public Queue<PixFill> fillArea(Point p, char original, char fill) {
            if (!(p.x >= 0 && p.y >= 0 && p.x < N1 && p.y < N2) || !(pix[p.x][p.y] == original)) {
                return null;
            }

            // create queue for efficiency
            Queue<Point> list = new LinkedList<>();
            list.add(p);

            // create broadcasting to spread filled points to othwer layers
            Queue<PixFill> broadCast = new LinkedList<>();
            while (!list.isEmpty()) {
                p = list.remove();
                if ((p.x >= 0 && p.y >= 0 && p.x < N1 && p.y < N2) && (pix[p.x][p.y] == original) && (!done[p.x][p.y])) {
                    //fill
                    pix[p.x][p.y] = fill;
                    done[p.x][p.y] = true;
                    //look for neighbors

                    list.add(new Point(p.x - 1, p.y));
                    list.add(new Point(p.x + 1, p.y));
                    list.add(new Point(p.x, p.y - 1));
                    list.add(new Point(p.x, p.y + 1));
                    // there will not be a duplicate pixFill as we always add the filled points that are not filled yet,
                    // so duplicate fill will never happen, so do pixFill :)

                    // add one for upper layer
                    if (index < N - 1) {
                        broadCast.add(new PixFill(p, index + 1));
                    }

                    // add one for lower layer
                    if (index > 0) {
                        broadCast.add(new PixFill(p, index - 1));
                    }

                    //layers out of range <0, N> can be filtered
                }
            }

            return broadCast;
        }
    }
}

关于java - 绘制填充多维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30016956/

相关文章:

python - 如何将2个不同维度的numpy数组相乘

c++ - 为什么这个变量需要是静态的?

sql - 如何找到最常见标签的记录,如StackOverflow中的相关问题

algorithm - 最佳地分配任务给 worker

java - log4j:归档文件删除策略

java - 如何使用 Spring Data JPA 从列中获取链接和值?

ios - 数组不在 View Controller ios 之间传递

c++ - TMP : how to generalize a Cartesian Product of Vectors?

java - 将 JSON 解析为 java 对象

java - 是否可以通过 POST 发送 JSONArray 而不是 JSONObject?