Created
April 8, 2018 15:33
-
-
Save 8q/9dbaf37c5a72d59fadc08d0a6a9a7674 to your computer and use it in GitHub Desktop.
mischan.png[83x100], takagiya.png[80x80]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.List; | |
import java.util.Iterator; | |
import java.util.Arrays; | |
Stage stage; | |
Population population; | |
int LIFE_TIME = 400; | |
float MUTATION_RATE = 0.025; | |
int POPULATION_NUM = 20; | |
int _lifetimeCounter = 0; | |
void setup() | |
{ | |
size(1280, 720); | |
noStroke(); | |
stage = new Stage(); | |
population = new Population(); | |
} | |
void draw() | |
{ | |
displayInfo(); | |
stage.draw(); | |
if (_lifetimeCounter < LIFE_TIME) | |
{ | |
population.run(); | |
population.updateFitness(); | |
population.draw(); | |
_lifetimeCounter++; | |
} else | |
{ | |
DNA bestDNA = population.bestDNA(); | |
println(bestDNA.fitness); | |
if(bestDNA.isFinished()) | |
{ | |
noLoop(); | |
bestDNA.player.draw(); | |
return; | |
} | |
_lifetimeCounter = 0; | |
population.selection(); | |
population.generate(); | |
} | |
} | |
void displayInfo() | |
{ | |
fill(0); | |
rect(0, 640, 1280, 80); | |
fill(255, 255, 0); | |
textFont (createFont("MS Gothic", 48, true)); | |
textSize(48); | |
text("第" + (population.generations + 1) + "世代", 10, 695); | |
textSize(24); | |
text((_lifetimeCounter) + "/" + LIFE_TIME, 300, 697); | |
} | |
class Population | |
{ | |
DNA[] dnas = new DNA[POPULATION_NUM]; | |
List<DNA> matingPool = new ArrayList<DNA>(); | |
int generations = 0; | |
Population() | |
{ | |
for (int i = 0; i < dnas.length; i++) | |
{ | |
dnas[i] = new DNA(); | |
} | |
} | |
void run() | |
{ | |
for (DNA dna : dnas) | |
{ | |
dna.run(); | |
} | |
} | |
void draw() | |
{ | |
for (DNA dna : dnas) | |
{ | |
dna.player.draw(); | |
} | |
} | |
void updateFitness() | |
{ | |
for (DNA dna : dnas) | |
{ | |
dna.updateFitness(); | |
} | |
} | |
DNA bestDNA() | |
{ | |
int pos = 0; | |
float maxFitness = 0; | |
for (int i = 0; i < dnas.length; i++) | |
{ | |
if (dnas[i].fitness > maxFitness) | |
{ | |
maxFitness = dnas[i].fitness; | |
pos = i; | |
} | |
} | |
return dnas[pos]; | |
} | |
void selection() | |
{ | |
matingPool.clear(); | |
float maxFitness = bestDNA().fitness; | |
for (int i = 0; i < dnas.length; i++) | |
{ | |
float fitness = map(dnas[i].fitness, 0, maxFitness, 0, 1); | |
int n = int(fitness * 100); | |
for (int j = 0; j < n; j++) | |
{ | |
matingPool.add(dnas[i]); | |
} | |
} | |
} | |
void generate() | |
{ | |
for (int i = 0; i < dnas.length; i++) | |
{ | |
int a = int(random(matingPool.size())); | |
int b = int(random(matingPool.size())); | |
DNA partnerA = matingPool.get(a); | |
DNA partnerB = matingPool.get(b); | |
DNA child = partnerA.crossover(partnerB); | |
child.mutate(); | |
dnas[i] = child; | |
} | |
generations++; | |
} | |
} | |
class DNA | |
{ | |
char[] genes; | |
Player player = new Player(); | |
float fitness = 0; | |
DNA() | |
{ | |
genes = new char[LIFE_TIME]; | |
for (int i = 0; i < genes.length; i++) | |
{ | |
genes[i] = (char)random(0, 4); | |
} | |
} | |
boolean isFinished() | |
{ | |
return fitness > 0.00011; | |
} | |
void run() | |
{ | |
if(isFinished()) return; | |
switch(genes[_lifetimeCounter]) | |
{ | |
case 0: | |
player.move(15, 0); | |
break; | |
case 1: | |
player.move(0, 15); | |
break; | |
case 2: | |
player.move(-15, 0); | |
break; | |
case 3: | |
player.move(0, -15); | |
break; | |
} | |
} | |
float updateFitness() | |
{ | |
float newFitness = pow(1 / (PVector.dist(new PVector(stage.target.x, stage.target.y), new PVector(player.x, player.y))), 2); | |
return fitness = fitness < newFitness ? newFitness : fitness; | |
} | |
DNA crossover(DNA partner) | |
{ | |
DNA child = new DNA(); | |
int midpoint = int(random(genes.length)); | |
for (int i = 0; i < genes.length; i++) | |
{ | |
if (i > midpoint) | |
child.genes[i] = genes[i]; | |
else | |
child.genes[i] = partner.genes[i]; | |
} | |
return child; | |
} | |
void mutate() | |
{ | |
for (int i = 0; i < genes.length; i++) | |
{ | |
if (random(1.0) < MUTATION_RATE) | |
{ | |
genes[i] = (char)random(0, 4); | |
} | |
} | |
} | |
} | |
class Player | |
{ | |
PImage img = loadImage("image/mischan.png"); | |
int x = 1180, y = 540, w = 50, h = 60; | |
void draw() | |
{ | |
image(img, x, y, w, h); | |
} | |
void move(int dx, int dy) | |
{ | |
if (!stage.isWall(x + dx, y + dy) && !stage.isWall(x + dx + w, y + dy) | |
&& !stage.isWall(x + dx, y + dy + h) && !stage.isWall(x + dx + w, y + dy + h) | |
&& x + dx >= 0 && x + dx + w <= 1280 | |
&& y + dy >= 0 && y + dy + h <= 640) | |
{ | |
x += dx; | |
y += dy; | |
} | |
} | |
} | |
class Stage | |
{ | |
class Target | |
{ | |
int x = 0, y = 0, w = 100, h = 100; | |
PImage img = loadImage("image/takagiya.png"); | |
void draw() | |
{ | |
fill(220, 20, 60); | |
rect(x, y, w, h); | |
image(img, x + w * 0.1, y + h * 0.1, w * 0.8, w * 0.8); | |
} | |
} | |
class Wall | |
{ | |
int x, y, w, h; | |
Wall(int x, int y, int w, int h) | |
{ | |
this.x = x; | |
this.y = y; | |
this.w = w; | |
this.h = h; | |
} | |
void draw() | |
{ | |
fill(210, 105, 30); | |
rect(x, y, w, h); | |
} | |
boolean isContain(int x, int y) | |
{ | |
return x >= this.x && x <= this.x + w && y >= this.y && y <= this.y + h; | |
} | |
} | |
Target target = new Target(); | |
Wall[] walls = | |
{ | |
new Wall(1010, 120, 110, 410), | |
new Wall(540, 0, 300, 380), | |
new Wall(600, 510, 180, 130), | |
new Wall(100, 440, 330, 200), | |
new Wall(150, 220, 220, 110), | |
new Wall(260, 110, 110, 110), | |
}; | |
void draw() | |
{ | |
fill(80, 200, 80); | |
rect(0, 0, 1280, 640); | |
for (Wall wall : walls) | |
{ | |
wall.draw(); | |
} | |
target.draw(); | |
} | |
boolean isWall(int x, int y) | |
{ | |
for (Wall wall : walls) | |
{ | |
if (wall.isContain(x, y)) | |
return true; | |
} | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment