Question

Hi I'd like to fill an ASCII Image with the Floodfill-alg. I always get error messages and I dont know why.

Here is my Main method with the input Image:

    public static void main(String[] args){
    Scanner sc = new Scanner("read 12\n+++++++++++++\n++++++++++#++\n++++++++++#++\n++++++++++#++\n++++++++++#++\n++++++++++#++\n++++++++++#++\n++++++++++#++\n++++++++++#++\n++++++++++#++\n++++++++++#++\n++++++++++#--\nfill 2 2 d");
    String read, numberst;
    String [] image;
    int number = 0, count = 0;
    Boolean error = false;

    read = sc.next();
    numberst = sc.next();

    if ((read + numberst).matches("read[0-9]+")) {
        number = Integer.parseInt(numberst);
    } else {
        error = true;
    }

    image = new String[number];

    System.out.println("image");

    while (sc.hasNextLine() && (error == false) && (count <= number - 1)) {
        image[count] = sc.next();
        //System.out.println(image[count] + " " + count);
        count++;
        if (image[0].length() != image[count - 1].length())  {
            error = true;
            System.out.println("INPUT MISMATCH");
        }
    }

    System.out.println("fill");
    while(sc.hasNextLine() && (error == false) && sc.hasNext()) {
        String fill = "", xstr = "", ystr = "", cstr;

        fill = sc.next();

        if (sc.hasNext()) {
            xstr = sc.next();   
        } else {
            error = true;
            System.out.println("INPUT MISMATCH");
        }

        if (sc.hasNext() && error == false){
            ystr = sc.next();
        } else {
            error = true;
            System.out.println("INPUT MISMATCH");
        }

        if (sc.hasNext() && error == false){
            cstr = sc.next();

            if ((fill + xstr + ystr + cstr).matches("fill[0-9]+[0-9]+.")) {
            int x = Integer.parseInt(xstr), y = Integer.parseInt(ystr);
            char c = cstr.charAt(0);

            if (x <= image[0].length() && y <= number) {
                fill(image, x, y, c);
            } else {
                error = true;
                System.out.println("OPERATION FAILED");
            }
            //System.out.println(fill + x + y + c);
        } else {
            error = true;
            System.out.println("INPUT MISMATCH");
        }

        } else {
            error = true;
            System.out.println("INPUT MISMATCH");
        }
        //System.out.println(error);
    }

    if (error == false) {
        for (int i = 0; i < number; ++i) {
        System.out.println(image[i]);
        }
    }
}

Here is the Code of my fill Method:

    public static void fill(String[] image, int x, int y, char c) {
    char old = (image[y]).charAt(x);
    Boolean r, l, o, u;

    image[y] = (image[y]).substring(0, x) + c + (image[y]).substring(x + 1);


    if ((x + 1) < image[0].length()) {
        r = (image[y].charAt(x + 1) == old);
    } else {
        r = false;
    }
    if ((x - 1) >= 0) {
        l = (image[y].charAt(x - 1) == old);
    }else {
        l = false;
    }
    if ((y - 1) >= 0) {
        o = (image[y - 1].charAt(x) == old);
    } else {
        o = false;
    }
    if ((y + 1) <= image.length) {
        u = (image[y + 1].charAt(x) == old);
    } else {
        u = false;
    }


    if (r == true) {
        fill(image, x + 1, y, c); //According to the Error message it looks like the Java Compiler switches between this and...
    }
    if (l == true) {
        fill(image, x - 1, y, c); //this line.
    }
    if (o == true) {
        fill(image, x, y - 1, c);
    }
    if (u == true) {
        fill(image, x, y + 1, c);
    }


}

Error message:

    at AsciiShop.fill(AsciiShop.java:122)
    at AsciiShop.fill(AsciiShop.java:119)
    at AsciiShop.fill(AsciiShop.java:122)
    at AsciiShop.fill(AsciiShop.java:119)
    at AsciiShop.fill(AsciiShop.java:122)
    at AsciiShop.fill(AsciiShop.java:119)
    at AsciiShop.fill(AsciiShop.java:122)
    at AsciiShop.fill(AsciiShop.java:119)
    at AsciiShop.fill(AsciiShop.java:122)

I have no Idea why this doesn't work. I hope you can help me.

Était-ce utile?

La solution

At first you are doing FloodFill wrong: you should check whether or not to proceed to the direction right before you proceed; you are checking all directions first and then proceed to them. This results in processing positions that already have been replaced causing infinite loop. At second there's a mistype in if ((y + 1) <= image.length) - there should be strict <.

Minimal changes to your fill method would be:

public static void fill(String[] image, int x, int y, char c) {
    char old = (image[y]).charAt(x);

    image[y] = (image[y]).substring(0, x) + c + (image[y]).substring(x + 1);

    if ((x + 1) < image[0].length() && 
            image[y].charAt(x + 1) == old) {
        fill(image, x + 1, y, c);
    }

    if ((x - 1) >= 0 &&
            image[y].charAt(x - 1) == old) {
        fill(image, x - 1, y, c);
    }

    if ((y - 1) >= 0 &&
            image[y - 1].charAt(x) == old) {
        fill(image, x, y - 1, c);
    }

    if ((y + 1) < image.length &&
            image[y + 1].charAt(x) == old) {
        fill(image, x, y + 1, c);
    }
}

But still I'd suggest to implement FloodFill in a more "standard" way (see http://en.wikipedia.org/wiki/Flood_fill) with passing the replacement color and checking it explicitly for every processed node - it makes the code much more robust and clear.

See example (your main method left almost intact, fill rewritten):

public static void main(String[] args) {
    Scanner sc = new Scanner(
            "read 12\n"
            + "+++++++++++++\n"
            + "++++++++++#++\n"
            + "++++++++++#++\n"
            + "++++++++++#++\n"
            + "++++++++++#++\n"
            + "++++++++++#++\n"
            + "++++++++++#++\n"
            + "++++++++++#++\n"
            + "++++++++++#++\n"
            + "++++++++++#++\n"
            + "++++++++++#++\n"
            + "++++++++++#--\n"
            + "fill 2 2 d");
    String read, numberst;
    String[] image;
    int number = 0, count = 0;
    Boolean error = false;

    read = sc.next();
    numberst = sc.next();

    if ((read + numberst).matches("read[0-9]+")) {
        number = Integer.parseInt(numberst);
    } else {
        error = true;
    }

    image = new String[number];

    System.out.println("image");

    while (sc.hasNextLine() && (error == false) && (count <= number - 1)) {
        image[count] = sc.next();
        // System.out.println(image[count] + " " + count);
        count++;
        if (image[0].length() != image[count - 1].length()) {
            error = true;
            System.out.println("INPUT MISMATCH");
        }
    }

    System.out.println("fill");
    while (sc.hasNextLine() && (error == false) && sc.hasNext()) {
        String fill = "", xstr = "", ystr = "", cstr;

        fill = sc.next();

        if (sc.hasNext()) {
            xstr = sc.next();
        } else {
            error = true;
            System.out.println("INPUT MISMATCH");
        }

        if (sc.hasNext() && error == false) {
            ystr = sc.next();
        } else {
            error = true;
            System.out.println("INPUT MISMATCH");
        }

        if (sc.hasNext() && error == false) {
            cstr = sc.next();

            if ((fill + xstr + ystr + cstr).matches("fill[0-9]+[0-9]+.")) {
                int x = Integer.parseInt(xstr), y = Integer.parseInt(ystr);
                char c = cstr.charAt(0);

                if (x <= image[0].length() && y <= number) {
                    fill(image, x, y, image[y].charAt(x), c);
                } else {
                    error = true;
                    System.out.println("OPERATION FAILED");
                }
                // System.out.println(fill + x + y + c);
            } else {
                error = true;
                System.out.println("INPUT MISMATCH");
            }

        } else {
            error = true;
            System.out.println("INPUT MISMATCH");
        }
        // System.out.println(error);
    }

    if (error == false) {
        for (int i = 0; i < number; ++i) {
            System.out.println(image[i]);
        }
    }
}

public static void fill(final String[] image, final int x, final int y, final char oldValue, final char newValue) {
    if (oldValue == image[y].charAt(x)) {
        image[y] = image[y].substring(0, x) + newValue + image[y].substring(x + 1);

        if ((x + 1) < image[y].length()) {
            fill(image, x + 1, y, oldValue, newValue);
        }

        if ((x - 1) >= 0) {
            fill(image, x - 1, y, oldValue, newValue);
        }

        if ((y - 1) >= 0) {
            fill(image, x, y - 1, oldValue, newValue);
        }

        if ((y + 1) < image.length) {
            fill(image, x, y + 1, oldValue, newValue);
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top