我有一项任务,但我不知道如何开始。如果有人知道,请发给我一些帖子的链接。 我有一个最小的Java类,我需要更新“填充”方法,以便它按照以下描述工作:
假装您正在使用MS Paint或类似的图形应用程序。您的工作是实施铲斗填充工具。更具体地说,给定一个二维网格,用户点击的(X,Y)位置和颜色,设计一个可用于填充网格的适当部分的算法。
铲斗填充算法应该“绘制”连接到用户点击的像素的所有像素,一直到颜色变化的边界。因此,例如,如果用户点击白色像素并指定绿色,则桶填充工具将所有触摸的白色像素转换为绿色像素。但是,它不会影响图像中完全独立部分的白色像素。
最小的Java类:
class BucketFill {
private char[][] pixels;
public BucketFill(char[][] pixels) {
this.pixels = pixels;
}
public void fill(int x, int y, char color) {
// TODO: make this method work
}
public void inspect() {
for (int y = 0; y < pixels.length; y++) {
for (int x = 0; x < pixels[y].length; x++) {
System.out.print(pixels[y][x]);
}
System.out.print("\n");
}
}
public static void main(String argv[]) {
char pixels[][] =
{
{ 'O', 'X', 'X', 'X', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'O', '#', 'O', 'X' },
{ 'X', 'O', 'O', 'O', 'X' },
{ 'X', 'X', 'X', 'X', 'X' },
{ 'X', 'X', 'X', '#', '#' },
{ 'X', 'X', 'X', 'X', 'X' }
};
BucketFill bucketFill = new BucketFill(pixels);
bucketFill.fill(0, 0, '*');
bucketFill.fill(3, 0, 'O');
bucketFill.fill(2, 1, '@');
bucketFill.inspect();
}
}
答案 0 :(得分:3)
您可以使用Flood Fill Algorithm。 Flood Fill
您可以使用基于堆栈的递归来实现它。它只是递归地为连接的节点着色。
答案 1 :(得分:0)
这是我使用Java的方法-随时提出改进建议:
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Value;
import java.util.Arrays;
import java.util.Queue;
import java.util.function.Function;
import java.util.stream.Collectors;
public class FloodFill {
/**
* @param area The whole area
* @param x User target position X
* @param y User target position Y
* @param color The new color
*/
public static void paint(int[][] area, int x, int y, int color) {
Coordinates target = new Coordinates(x, y);
Queue<Coordinates> queue = Arrays.stream(Direction.values()).map(direction -> direction.getNextPosition().apply(target))
.collect(Collectors.toCollection(LinkedNoReenterQueue::new));
paint(area, queue, color, area[x][y]);
switchColor(area, target, color);
}
@RequiredArgsConstructor
@Getter
private enum Direction {
NORTH(coordinates -> {
return new Coordinates(coordinates.x, coordinates.y + 1);
}),
SOUTH(coordinates -> {
return new Coordinates(coordinates.x, coordinates.y - 1);
}),
EAST(coordinates -> {
return new Coordinates(coordinates.x + 1, coordinates.y);
}),
WEST(coordinates -> {
return new Coordinates(coordinates.x - 1, coordinates.y);
}),
NORTHEAST(coordinates -> {
return new Coordinates(coordinates.x + 1, coordinates.y + 1);
}),
NORTHWEST(coordinates -> {
return new Coordinates(coordinates.x - 1, coordinates.y + 1);
}),
SOUTHEAST(coordinates -> {
return new Coordinates(coordinates.x + 1, coordinates.y - 1);
}),
SOUTHWEST(coordinates -> {
return new Coordinates(coordinates.x - 1, coordinates.y - 1);
});
private final Function<Coordinates, Coordinates> nextPosition;
}
@Value
private static class Coordinates {
int x;
int y;
}
private static void switchColor(int[][] area, Coordinates coordinates, int color) {
area[coordinates.x][coordinates.y] = color;
}
private static boolean shouldSwitch(int[][] area, Coordinates coordinates, int previousColor) {
return area[coordinates.x][coordinates.y] == previousColor;
}
private static boolean isValid(int[][] area, Coordinates coordinates) {
return coordinates.getX() >= 0 && coordinates.getY() >= 0 && coordinates.getX() < area.length && coordinates.getY() < area[0].length;
}
private static void paint(int[][] area, Queue<Coordinates> queue, int newColor, int oldColor) {
while (!queue.isEmpty()) {
Coordinates nextPosition = queue.poll();
if (isValid(area, nextPosition) && shouldSwitch(area, nextPosition, oldColor)) {
switchColor(area, nextPosition, newColor);
for (Direction direction : Direction.values()) {
queue.add(direction.getNextPosition().apply(nextPosition));
}
}
}
}
}
为避免重复填充相同的像素,请考虑以下数据结构:
导入java.util。*;
public abstract class NoReenterQueue<E> extends AbstractQueue<E> {
private Set<E> ledger;
protected NoReenterQueue() {
this.ledger = new HashSet<>();
}
@Override
public final boolean offer(E e) {
if (!ledger.contains(e)) {
ledger.add(e);
insert(e);
}
return true;
}
protected abstract boolean insert(E e);
}
并且:
import java.util.Iterator;
import java.util.LinkedList;
public class LinkedNoReenterQueue<E> extends NoReenterQueue<E>{
private LinkedList<E> linkedList = new LinkedList<>();
@Override
protected boolean insert(E e) {
return linkedList.add(e);
}
@Override
public Iterator<E> iterator() {
return linkedList.iterator();
}
@Override
public int size() {
return linkedList.size();
}
@Override
public E poll() {
return linkedList.poll();
}
@Override
public E peek() {
return linkedList.peek();
}
}
例如:
2222222
2111112
2122212
2122212
2122212
2111112
2222222
给出target =(3,3)和newColor = 3:
2222222
2111112
2133312
2133312
2133312
2111112
2222222