Tembel olalım ve cevabımı bu soruya uyarlayalım !
Algoritma, tüm dikdörtgeni dolduran sol üst köşeden başlayarak bir "yılan yolu" hesaplar. Yılan sadece yukarı, aşağı, sola, sağa gidebilir.
Yılan yolu izlenir ve renk yüzdeleri hesaba katılarak ilk renk, ardından ikinci renk vb. İle doldurulur.
Bu algoritma birçok düz çizgi üretir; iyileştirmek için, onları algılar ve aynı piksel miktarını koruyan "dalgalar" ile değiştiririm.
Parametreler: 380 260 233 420 1300 3511 4772 5089 9507 22107 25117 26744
Parametreler: 380 260 8 5 6 7 8 4 5 6 7 9 4 6 9 5 8 7 5
Camelot'un Karanlık Çağı (213 307 1 1 1)
Kod:
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;
}
}