Lassen Sie uns faul sein und meine Antwort von dieser Frage anpassen !
Der Algorithmus berechnet ausgehend von der oberen linken Ecke einen "Schlangenpfad", der das gesamte Rechteck ausfüllt. Die Schlange kann nur hoch, runter, links, rechts gehen.
Der Schlangenpfad wird verfolgt und mit der ersten Farbe, dann der zweiten Farbe usw. gefüllt, wobei die Farbprozentsätze berücksichtigt werden
Dieser Algorithmus erzeugt viele gerade Linien. um es zu verbessern, erkenne ich sie und ersetze sie durch "Wellen", die die gleiche Anzahl von Pixeln behalten.
Parameter: 380 260 233 420 1300 3511 4772 5089 9507 22107 25117 26744
Parameter: 380 260 8 5 6 7 8 4 5 6 7 9 4 6 9 5 8 7 5
Dunkles Zeitalter von Camelot (213 307 1 1 1)
Der Code:
package map;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
public class GenMap2 {
private enum State { NO, YES, SHIFT };
public final static int TOP = 1, BOTTOM = 2, LEFT = 4, RIGHT = 8;
enum Action { ADD_LINE_TOP, ADD_LINE_LEFT, DOUBLE_SIZE, CREATE};
public static void main(String[] args) throws IOException {
int w = Integer.parseInt(args[0]), h = Integer.parseInt(args[1]);
List<Integer> areas = new ArrayList<Integer>();
int total = 0;
for (int i = 2; i < args.length; i++) {
int area = Integer.parseInt(args[i]);
areas.add(area);
total += area;
}
Collections.sort(areas);
Collections.reverse(areas);
int [][] tab = build(w, h);
BufferedImage dest = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
int [] black = {0, 0, 0};
for (int j = 0; j < dest.getHeight(); j++) {
for (int i = 0; i < dest.getWidth(); i++) {
dest.getRaster().setPixel(i, j, black);
}
}
int x = 0, y = -1;
int go = BOTTOM, previous = BOTTOM;
List<Color> colors = new ArrayList<Color>();
Random rand = new Random(0); // prog must be deterministic
while (colors.size() < areas.size()) {
Color c = new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
boolean ok = true;
for (Color existing : colors) {
if (existing.equals(c)) {
ok = false;
break;
}
}
if (ok) {
colors.add(c);
}
}
int [][] map = new int[w][h];
int cpt = 0;
while (true) {
if (go == BOTTOM) y++;
if (go == TOP) y--;
if (go == LEFT) x--;
if (go == RIGHT) x++;
int tmp = (int)(((long)cpt) * total / (w * h));
int i = 0;
for (i = 0; i < areas.size(); i++) {
int area = areas.get(i);
if (tmp < area) {
break;
}
tmp -= area;
}
map[x][y] = i;
previous = go;
go = -1;
if ((tab[x][y] & TOP) != 0 && previous != BOTTOM) go = TOP;
if ((tab[x][y] & BOTTOM) != 0 && previous != TOP) go = BOTTOM;
if ((tab[x][y] & LEFT) != 0 && previous != RIGHT) go = LEFT;
if ((tab[x][y] & RIGHT) != 0 && previous != LEFT) go = RIGHT;
if (go == -1) break;
cpt++;
}
String [] src0 = srcPattern(16);
String [] repl0 = destPattern(16);
while (findPattern(map, src0, Arrays.asList(repl0, flip(repl0)))){}
while (findPattern(map, rotate(src0), Arrays.asList(rotate(repl0), rotate(flip(repl0))))){}
String [] src1 = srcPattern(8);
String [] repl1 = destPattern(8);
while (findPattern(map, src1, Arrays.asList(repl1, flip(repl1)))){}
while (findPattern(map, rotate(src1), Arrays.asList(rotate(repl1), rotate(flip(repl1))))){}
String [] src2 = srcPattern(4);
String [] repl2 = destPattern(4);
while (findPattern(map, src2, Arrays.asList(repl2, flip(repl2)))){}
while (findPattern(map, rotate(src2), Arrays.asList(rotate(repl2), rotate(flip(repl2))))){}
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
Color c = colors.get(map[x][y]);
dest.getRaster().setPixel(x, y, new int[] {c.getRed(), c.getGreen(), c.getBlue()});
}
}
ImageIO.write(dest, "png", new FileOutputStream("map.png"));
}
private static Random randPat = new Random(0);
private static String [] srcPattern(int size) {
String [] ret = new String[size*2];
for (int i = 0; i < size*2; i++) {
ret[i] = "";
for (int j = 0; j < size*4; j++) {
ret[i] += i < size ? "1" : "2";
}
}
return ret;
}
private static String [] destPattern(int size) {
String [] ret = new String[size*2];
for (int i = 0; i < size*2; i++) {
ret[i] = "";
for (int j = 0; j < size*2; j++) {
//int target = (int)((1 + Math.sin(j * Math.PI * .5/ size) * .4) * size);
int target = (int)((1 + (Math.cos(j * Math.PI/ size) - 1) * .2) * size);
ret[i] += (i < target) ? '1' : '2';
}
}
for (int i = 0; i < size*2; i++) {
for (int j = 0; j < size*2; j++) {
ret[i] += ret[size*2 - 1 - i].charAt(size*2 - 1 - j) == '1' ? '2' : '1';
}
}
return ret;
}
private static String [] flip(String [] pat) {
String [] ret = new String[pat.length];
for (int i = 0; i < ret.length; i++) {
ret[i] = new StringBuilder(pat[i]).reverse().toString();
}
return ret;
}
private static String [] rotate(String [] pat) {
String [] ret = new String[pat[0].length()];
for (int i = 0; i < ret.length; i++) {
ret[i] = "";
for (int j = 0; j < pat.length; j++) {
ret[i] += pat[j].charAt(i);
}
}
return ret;
}
private static boolean findPattern(int [][] map, String [] src, List<String []> dest) {
for (int y = 0; y < map[0].length - src.length; y++) {
for (int x = 0; x < map.length - src[0].length(); x++) {
int c1 = -1, c2 = -1;
boolean wrong = false;
for (int y1 = 0; y1 < src.length; y1++) {
for (int x1 = 0; x1 < src[0].length(); x1++) {
if (src[y1].charAt(x1) == '1') {
if (c1 == -1) {
c1 = map[x+x1][y+y1];
} else {
if (c1 != map[x+x1][y+y1]) {
wrong = true;
}
}
}
if (src[y1].charAt(x1) == '2') {
if (c2 == -1) {
c2 = map[x+x1][y+y1];
} else {
if (c2 != map[x+x1][y+y1]) {
wrong = true;
}
}
}
if (c1 != -1 && c1 == c2) wrong = true;
if (wrong) break;
}
if (wrong) break;
}
if (!wrong) {
System.out.println("Found match at " + x + " " + y);
String [] repl = dest.get(randPat.nextInt(dest.size()));
for (int y1 = 0; y1 < src.length; y1++) {
for (int x1 = 0; x1 < src[0].length(); x1++) {
map[x+x1][y+y1] = repl[y1].charAt(x1) == '1' ? c1 : c2;
}
}
return true;
}
}
}
return false;
}
public static int [][] build(int width, int height) {
List<Action> actions = new ArrayList<Action>();
while (height>1 && width>1) {
if (height % 2 == 1) {
height--;
actions.add(Action.ADD_LINE_TOP);
}
if (width % 2 == 1) {
width--;
actions.add(Action.ADD_LINE_LEFT);
}
if (height%2 == 0 && width%2 == 0) {
actions.add(Action.DOUBLE_SIZE);
height /= 2;
width /= 2;
}
}
actions.add(Action.CREATE);
Collections.reverse(actions);
int [][] tab = null;
for (Action action : actions) {
if (action == Action.CREATE) {
tab = new int[width][height];
if (height >= width) {
for (int i = 0; i < height-1; i++) {
tab[0][i] = TOP|BOTTOM;
}
tab[0][height-1] = TOP;
} else {
tab[0][0] = TOP|RIGHT;
for (int i = 1; i < width-1; i++) {
tab[i][0] = RIGHT|LEFT;
}
tab[width-1][0] = LEFT;
}
}
if (action == Action.DOUBLE_SIZE) {
tab = doubleTab(tab);
}
if (action == Action.ADD_LINE_TOP) {
int [][] tab2 = new int[tab.length][tab[0].length+1];
for (int i = 0; i < tab.length; i++) {
for (int j = 0; j < tab[0].length; j++) {
tab2[i][j+1] = tab[i][j];
}
}
tab2[0][0] = BOTTOM|RIGHT;
for (int i = 1; i < tab.length-1; i++) {
tab2[i][0] = RIGHT|LEFT;
}
tab2[tab.length-1][0] = TOP|LEFT;
mirror(tab2);
tab = tab2;
}
if (action == Action.ADD_LINE_LEFT) {
int [][] tab2 = new int[tab.length+1][tab[0].length];
for (int i = 0; i < tab.length; i++) {
for (int j = 0; j < tab[0].length; j++) {
tab2[i+1][j] = tab[i][j];
}
}
tab2[0][0] = BOTTOM|RIGHT;
tab2[1][0] |= LEFT;
tab2[1][0] -= TOP;
for (int i = 1; i < tab[0].length-1; i++) {
tab2[0][i] = TOP|BOTTOM;
}
tab2[0][tab[0].length-1] = TOP|BOTTOM;
flip(tab2);
tab = tab2;
}
}
return tab;
}
private static void mirror(int [][] tab) {
for (int i = 0; i < tab.length/2; i++) {
for (int j = 0; j < tab[0].length; j++) {
int tmp = tab[tab.length - 1 - i][j];
tab[tab.length - 1 - i][j] = tab[i][j];
tab[i][j] = tmp;
}
}
for (int i = 0; i < tab.length; i++) {
for (int j = 0; j < tab[0].length; j++) {
if ((tab[i][j] & LEFT)!=0 && (tab[i][j] & RIGHT)==0) {
tab[i][j] -= LEFT; tab[i][j] |= RIGHT;
} else if ((tab[i][j] & RIGHT)!=0 && (tab[i][j] & LEFT)==0) {
tab[i][j] -= RIGHT; tab[i][j] |= LEFT;
}
}
}
}
private static void flip(int [][] tab) {
for (int i = 0; i < tab.length; i++) {
for (int j = 0; j < tab[0].length/2; j++) {
int tmp = tab[i][tab[0].length - 1 - j];
tab[i][tab[0].length - 1 - j] = tab[i][j];
tab[i][j] = tmp;
}
}
for (int i = 0; i < tab.length; i++) {
for (int j = 0; j < tab[0].length; j++) {
if ((tab[i][j] & TOP)!=0 && (tab[i][j] & BOTTOM)==0) {
tab[i][j] -= TOP; tab[i][j] |= BOTTOM;
} else if ((tab[i][j] & BOTTOM)!=0 && (tab[i][j] & TOP)==0) {
tab[i][j] -= BOTTOM; tab[i][j] |= TOP;
}
}
}
}
public static int [][] doubleTab(int [][] tab) {
boolean [][] shiftTop = new boolean[tab.length][],
shiftLeft = new boolean[tab.length][],
shiftBottom = new boolean[tab.length][],
shiftRight = new boolean[tab.length][];
for (int i = 0; i < tab.length; i++) {
shiftTop[i] = new boolean[tab[i].length];
shiftLeft[i] = new boolean[tab[i].length];
shiftBottom[i] = new boolean[tab[i].length];
shiftRight[i] = new boolean[tab[i].length];
}
int x = 0, y = -1;
for (int i = 0; i < tab.length; i++) {
if ((tab[i][0] & TOP) != 0) {
x = i;
}
}
int go = BOTTOM, previous = BOTTOM;
boolean init = false;
while (true) {
if (go == BOTTOM) y++;
if (go == TOP) y--;
if (go == LEFT) x--;
if (go == RIGHT) x++;
previous = go;
go = -1;
if ((tab[x][y] & TOP) != 0 && previous != BOTTOM) go = TOP;
if ((tab[x][y] & BOTTOM) != 0 && previous != TOP) go = BOTTOM;
if ((tab[x][y] & LEFT) != 0 && previous != RIGHT) go = LEFT;
if ((tab[x][y] & RIGHT) != 0 && previous != LEFT) go = RIGHT;
if (previous == BOTTOM) {
shiftTop[x][y] = y==0 ? init : shiftBottom[x][y-1];
}
if (previous == TOP) {
shiftBottom[x][y] = shiftTop[x][y+1];
}
if (previous == RIGHT) {
shiftLeft[x][y] = shiftRight[x-1][y];
}
if (previous == LEFT) {
shiftRight[x][y] = shiftLeft[x+1][y];
}
if (go == -1) break;
if (previous == BOTTOM && go == LEFT) {
shiftLeft[x][y] = !shiftTop[x][y];
}
if (previous == BOTTOM && go == RIGHT) {
shiftRight[x][y] = shiftTop[x][y];
}
if (previous == BOTTOM && go == BOTTOM) {
shiftBottom[x][y] = shiftTop[x][y];
}
if (previous == TOP && go == LEFT) {
shiftLeft[x][y] = shiftBottom[x][y];
}
if (previous == TOP && go == RIGHT) {
shiftRight[x][y] = !shiftBottom[x][y];
}
if (previous == TOP && go == TOP) {
shiftTop[x][y] = shiftBottom[x][y];
}
if (previous == RIGHT && go == TOP) {
shiftTop[x][y] = !shiftLeft[x][y];
}
if (previous == RIGHT && go == BOTTOM) {
shiftBottom[x][y] = shiftLeft[x][y];
}
if (previous == RIGHT && go == RIGHT) {
shiftRight[x][y] = shiftLeft[x][y];
}
if (previous == LEFT && go == TOP) {
shiftTop[x][y] = shiftRight[x][y];
}
if (previous == LEFT && go == BOTTOM) {
shiftBottom[x][y] = !shiftRight[x][y];
}
if (previous == LEFT && go == LEFT) {
shiftLeft[x][y] = shiftRight[x][y];
}
}
int [][] tab2 = new int[tab.length * 2][];
for (int i = 0; i < tab2.length; i++) {
tab2[i] = new int[tab[0].length * 2];
}
for (int i = 0; i < tab.length; i++) {
for (int j = 0; j < tab[0].length; j++) {
State left = State.NO, right = State.NO, top = State.NO, bottom = State.NO;
if ((tab[i][j] & LEFT) != 0) {
left = shiftLeft[i][j] ? State.SHIFT : State.YES;
}
if ((tab[i][j] & TOP) != 0) {
top = shiftTop[i][j] ? State.SHIFT : State.YES;
}
if ((tab[i][j] & RIGHT) != 0) {
right = shiftRight[i][j] ? State.SHIFT : State.YES;
}
if ((tab[i][j] & BOTTOM) != 0) {
bottom = shiftBottom[i][j] ? State.SHIFT : State.YES;
}
int [] comp = compute(left, top, right, bottom);
tab2[i*2][j*2] = comp[0];
tab2[i*2+1][j*2] = comp[1];
tab2[i*2][j*2+1] = comp[2];
tab2[i*2+1][j*2+1] = comp[3];
}
}
return tab2;
}
private static int [] compute(State left, State top, State right, State bottom) {
// |
// --+
//
if (left == State.YES && top == State.SHIFT) {
return new int[] {LEFT|BOTTOM, TOP|BOTTOM, TOP|RIGHT, TOP|LEFT};// "v^>^";
}
if (left == State.SHIFT && top == State.YES) {
return new int[] {TOP|RIGHT, LEFT|BOTTOM, LEFT|RIGHT, LEFT|TOP}; //"^<>^";
}
//
// --+
// |
if (left == State.YES && bottom == State.YES) {
return new int[] {LEFT|RIGHT, LEFT|BOTTOM, RIGHT|BOTTOM, LEFT|TOP}; //">vv<";
}
if (left == State.SHIFT && bottom == State.SHIFT) {
return new int[] {RIGHT|BOTTOM, LEFT|BOTTOM, LEFT|TOP, TOP|BOTTOM}; //">v^v";
}
// |
// +--
//
if (right == State.SHIFT && top == State.SHIFT) {
return new int [] {RIGHT|BOTTOM,LEFT|TOP,TOP|RIGHT, LEFT|RIGHT}; //" v<>>";
}
if (right == State.YES && top == State.YES) {
return new int [] {TOP|BOTTOM,RIGHT|BOTTOM,TOP|RIGHT,TOP|LEFT}; //"v>>^";
}
//
// +--
// |
if (right == State.YES && bottom == State.SHIFT) {
return new int [] {RIGHT|BOTTOM, LEFT|RIGHT, TOP|RIGHT, LEFT|BOTTOM}; //"v<>v";
}
if (right == State.SHIFT && bottom == State.YES) {
return new int [] {RIGHT|BOTTOM, LEFT|BOTTOM, TOP|BOTTOM, RIGHT|TOP}; //"v<v^";
}
//
// --+--
//
if (right == State.YES && left == State.YES) {
return new int [] {LEFT|BOTTOM, RIGHT|BOTTOM, TOP|RIGHT, LEFT|TOP};
}
if (right == State.SHIFT && left == State.SHIFT) {
return new int [] {RIGHT|BOTTOM, LEFT|BOTTOM, LEFT|TOP, RIGHT|TOP};
}
// |
// +
// |
if (top == State.YES && bottom == State.YES) {
return new int [] {TOP|RIGHT, LEFT|BOTTOM, BOTTOM|RIGHT, LEFT|TOP};
}
if (top == State.SHIFT && bottom == State.SHIFT) {
return new int [] {RIGHT|BOTTOM, LEFT|TOP, RIGHT|TOP, LEFT|BOTTOM};
}
//
// +--
//
if (right == State.YES && bottom == State.NO && left == State.NO && top == State.NO) {
return new int [] {BOTTOM, RIGHT|BOTTOM, TOP|RIGHT, LEFT|TOP};
}
if (right == State.SHIFT && bottom == State.NO && left == State.NO && top == State.NO) {
return new int [] {RIGHT|BOTTOM, LEFT|BOTTOM, TOP, RIGHT|TOP};
}
// |
// +
//
if (top == State.YES && bottom == State.NO && left == State.NO && right == State.NO) {
return new int [] {TOP|RIGHT, LEFT|BOTTOM, RIGHT, LEFT|TOP};
}
if (top == State.SHIFT && bottom == State.NO && left == State.NO && right == State.NO) {
return new int [] {BOTTOM|RIGHT, LEFT|TOP, TOP|RIGHT, LEFT};
}
//
// +
// |
if (bottom == State.YES && top == State.NO && left == State.NO && right == State.NO) {
return new int [] {RIGHT, LEFT|BOTTOM, BOTTOM|RIGHT, LEFT|TOP};
}
if (bottom == State.SHIFT && top == State.NO && left == State.NO && right == State.NO) {
return new int [] {BOTTOM|RIGHT, LEFT, TOP|RIGHT, LEFT|BOTTOM};
}
//
// --+
//
if (left == State.YES && bottom == State.NO && right == State.NO && top == State.NO) {
return new int [] {LEFT|BOTTOM, BOTTOM, TOP|RIGHT, LEFT|TOP};
}
if (left == State.SHIFT && bottom == State.NO && right == State.NO && top == State.NO) {
return new int [] {BOTTOM|RIGHT, LEFT|BOTTOM, LEFT|TOP, TOP};
}
return null;
}
}