Ayo malas dan sesuaikan jawaban saya dari pertanyaan ini !
Algoritma menghitung "jalur ular" mulai dari sudut kiri atas yang mengisi seluruh persegi panjang. Ular hanya bisa naik, turun, kiri, kanan.
Jalur ular diikuti dan diisi dengan warna pertama, lalu warna kedua, dll ... dengan memperhitungkan persentase warna
Algoritma ini menghasilkan banyak garis lurus; untuk memperbaikinya, saya mendeteksi mereka dan menggantinya dengan "gelombang" yang menjaga jumlah piksel yang sama.
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
Dark Age of Camelot (213 307 1 1 1)
Kode:
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;
}
}